From 435bbe2665a447048058660e86deb6ed2005c635 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 5 Feb 2021 14:31:46 +0530 Subject: [PATCH 001/868] wip: refactor website routing and rendering --- frappe/tests/test_website_new.py | 20 ++ frappe/utils/boilerplate.py | 1 - frappe/website/serve.py | 276 ++++++++++++++++++++++++++ frappe/www/_test/static-file-test.png | Bin 0 -> 440 bytes 4 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 frappe/tests/test_website_new.py create mode 100644 frappe/website/serve.py create mode 100644 frappe/www/_test/static-file-test.png diff --git a/frappe/tests/test_website_new.py b/frappe/tests/test_website_new.py new file mode 100644 index 0000000000..aa9e77d5ba --- /dev/null +++ b/frappe/tests/test_website_new.py @@ -0,0 +1,20 @@ +from __future__ import unicode_literals + +import unittest + +import frappe +from frappe.website import serve +from frappe.website.utils import get_home_page +from frappe.utils import set_request + +class TestWebsite(unittest.TestCase): + def test_static_page(self): + set_request(method='GET', path='/_test/static-file-test.png') + response = serve.StaticPage().get() + self.assertEquals(response.status_code, 200) + + def test_error_page(self): + set_request(method='GET', path='/error') + response = serve.TemplatePage().get() + self.assertEquals(response.status_code, 200) + print(response.get_data()) diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index 69d5726c34..e613c4d810 100755 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -330,7 +330,6 @@ Configuration for docs """ # source_link = "https://github.com/[org_name]/{app_name}" -# docs_base_url = "https://[org_name].github.io/{app_name}" # headline = "App that does everything" # sub_heading = "Yes, you got that right the first time, everything" diff --git a/frappe/website/serve.py b/frappe/website/serve.py new file mode 100644 index 0000000000..3f3e1d4571 --- /dev/null +++ b/frappe/website/serve.py @@ -0,0 +1,276 @@ +import frappe +import os, mimetypes + +from werkzeug.wrappers import Response +from werkzeug.wsgi import wrap_file + +from frappe.website.render import (resolve_path, build_response) +from frappe.website.redirect import resolve_redirect +from frappe.website.router import get_start_folders +from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, + get_toc, get_next_link) +from frappe.website.doctype.website_settings.website_settings import get_website_settings + +def render(path=None, http_status_code=None): + """render html page""" + if not path: + path = frappe.local.request.path + + try: + path = path.strip('/ ') + resolve_redirect(path) + path = resolve_path(path) + data = None + + response = StaticPage(path).get() + if not response: + response = TemplatePage(path).get() + if not response: + response = DocTypePage(path).get() + if not response: + response = TemplatePage('404').get() + except frappe.PermissionError as e: + response = TemplatePage('403').get() + except: + response = TemplatePage('error').get() + + return response + +class WebPage(object): + def __init__(self, path=None): + self.headers = None + self.status_code = 200 + if not path: + path = frappe.local.request.path + self.path = path.strip('/ ') + + def get(self): + if self.validate(): + return self.render() + + def validate(self): + pass + + def render(self): + pass + +class StaticPage(WebPage): + def validate(self): + if ('.' not in self.path): + return False + extn = self.path.rsplit('.', 1)[-1] + if extn in ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json'): + return False + + if self.find_path_in_apps(): + return True + + return False + + def find_path_in_apps(self): + for app in frappe.get_installed_apps(): + file_path = frappe.get_app_path(app, 'www') + '/' + self.path + if os.path.exists(file_path): + self.file_path = file_path + return True + return False + + def render(self): + try: + f = open(self.file_path, 'rb') + except IOError: + raise NotFound + + response = Response(wrap_file(frappe.local.request.environ, f), direct_passthrough=True) + response.mimetype = mimetypes.guess_type(self.file_path)[0] or 'application/octet-stream' + return response + +class TemplatePage(WebPage): + def validate(self): + for app in frappe.get_installed_apps(frappe_last=True): + if self.find_page_in_app(app): + return True + + def find_page_in_app(self, app): + ''' + Searches for file matching the path in the /www and /templates/pages folders + ''' + app_path = frappe.get_app_path(app) + folders = get_start_folders() + + for dirname in folders: + search_path = os.path.join(app_path, dirname, self.path) + for p in self.get_index_path_options(search_path): + file_path = frappe.as_unicode(p) + if os.path.exists(file_path) and not os.path.isdir(file_path): + self.app = app + self.app_path = app_path + self.dirname = dirname + self.file_path = file_path + self.template_path = os.path.relpath(file_path, self.app_path) + return True + + def get_index_path_options(self, search_path): + return ( + search_path, + search_path + '.html', + search_path + '.md', + search_path + '/index.html', + search_path + '/index.md') + + def render(self): + return build_response(self.path, self.get_html(), self.status_code, self.headers) + + def get_html(self): + # context object should be separate from self for security + # because it will be accessed via the user defined template + self.context = frappe._dict() + + self.set_pymodule() + self.setup_template() + + if self.pymodule_name: + self.update_context() + + if self.source: + html = frappe.render_template(self.source, self.context) + + elif self.template_path: + html = self.render_template() + + html = self.update_toc(html) + + return html + + def set_pymodule(self): + ''' + A template may have a python module with a `get_context` method along with it in the + same folder. Also the hyphens will be coverted to underscore for python module names. + This method sets the pymodule_name if it exists. + ''' + self.basepath = self.template_path.rsplit('.', 1)[0] + self.pymodule_name = None + + # replace - with _ in the internal modules names + self.pymodule_path = os.path.join(self.basepath.replace("-", "_") + ".py") + + if os.path.exists(os.path.join(self.app_path, self.pymodule_path)): + self.pymodule_name = self.app + "." + self.pymodule_path.replace(os.path.sep, ".")[:-3] + + def setup_template(self): + '''Setup template source, frontmatter and markdown conversion''' + self.source = self.get_raw_template() + + if self.template_path.endswith(('.md', '.html')): + self.extract_frontmatter() + + self.convert_from_markdown() + + if self.extends_template(): + self.context.base_template_path = self.context.base_template_path or 'templates/base.html' + else: + self.source = None # clear the source + + # TODO: setup index.txt ? + + def update_context(self): + self.set_page_properties() + self.context.update(get_website_settings(self.context)) + self.context.update(frappe.local.conf.get("website_context") or {}) + + self.pymodule = frappe.get_module(self.pymodule_name) + + if self.pymodule: + self.set_pymodule_properties() + + data = self.run_pymodule_method('get_context') + # some methods may return a "context" object + if data: self.context.update(data) + + # TODO: self.context.children = self.run_pymodule_method('get_children') + + self.context.developer_mode = frappe.conf.developer_mode + + def set_pymodule_properties(self): + for prop in ("base_template_path", "template", "no_cache", "sitemap", + "condition_field"): + if hasattr(self.pymodule, prop): + self.context[prop] = getattr(self.pymodule, prop) + + def set_page_properties(self): + self.context.template = self.template_path + + def run_pymodule_method(self, method): + if hasattr(self.pymodule, method): + try: + return getattr(self.pymodule, method)(self) + except (frappe.PermissionError, frappe.DoesNotExistError, frappe.Redirect): + raise + except: + if not frappe.flags.in_migrate: + frappe.errprint(frappe.utils.get_traceback()) + + def render_template(self): + if self.path.endswith('min.js'): + # directly serve min.js pages using the jloader to find it in various apps + # (can be used as static?) + html = self.get_raw_template() + else: + html = frappe.get_template(self.template_path).render(self.context) + + def extends_template(self): + return (self.template_path.endswith(('.html', '.md', )) + and ('{%- extends' in self.source + or '{% extends' in self.source)) + + def get_raw_template(self): + return frappe.get_jloader().get_source(frappe.get_jenv(), self.template_path)[0] + + def load_colocated_files(self): + '''load co-located css/js files with the same name''' + js_path = self.basepath + '.js' + if os.path.exists(js_path) and '{% block script %}' not in self.source: + self.colocated_js = self.get_colocated_file(js_path) + + css_path = self.basepath + '.css' + if os.path.exists(css_path) and '{% block style %}' not in self.source: + self.colocated_css = self.get_colocated_file(css_path) + + def get_colocated_file(self, path): + with io.open(path, 'r', encoding = 'utf-8') as f: + return f.read() + + def extract_frontmatter(self): + try: + # values will be used to update page_info + res = get_frontmatter(self.source) + if res['attributes']: + self.context.update(res['attributes']) + self.source = res['body'] + except Exception: + pass + + def convert_from_markdown(self): + if self.template_path.endswith('.md'): + self.source = frappe.utils.md_to_html(self.source) + self.page_toc_html = self.toc_html + + if not self.show_sidebar: + self.source = '
' + self.source + '
' + + def update_toc(self, html): + if '{index}' in html: + html = html.replace('{index}', get_toc(self.path)) + + if '{next}' in html: + html = html.replace('{next}', get_next_link(self.path)) + + return html + + +class DocTypePage(WebPage): + pass + +class WebFormPage(WebPage): + pass + diff --git a/frappe/www/_test/static-file-test.png b/frappe/www/_test/static-file-test.png new file mode 100644 index 0000000000000000000000000000000000000000..b51db82f82b906b30609f807f0f663cac40d20b4 GIT binary patch literal 440 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$a>caTa()7Beu2se&-0XOPMVpde#$ zkh>GZx^prwfgF}}M_)$E)e-c@Na=xA}jv*C{Z|`n2ZE+NFc(}bULexYtxXVk! zRa1H)JCmwK`xQRZ9Zdhl)Xnb@xa7e_h#Kc{rb11QMP%$ zyna9bX2;pHxqo~9%j-KE^?Uy3M6(kqS{SBbSa7?V|4TdH>w?cef9;X4JIhPRIT!|D tb@a_URnxz=-&b0D_xf+-FaWXL-%6{zP`s|39McHmdb;|#taD0e0su)Qf|39L literal 0 HcmV?d00001 From 3f38c3300462dfcda96638c0597216613bf21f19 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 5 Feb 2021 15:54:23 +0530 Subject: [PATCH 002/868] fix: status_code, login page works --- frappe/app.py | 8 ++++++-- frappe/tests/test_website_new.py | 17 ++++++++++++++++- frappe/website/serve.py | 18 ++++++++++-------- frappe/www/error.py | 2 ++ 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/frappe/app.py b/frappe/app.py index adf2bfa8c9..9495268f00 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -18,7 +18,8 @@ import frappe.handler import frappe.auth import frappe.api import frappe.utils.response -import frappe.website.render +import frappe.website.serve +import frappe.website.page from frappe.utils import get_site_name, sanitize_html from frappe.middlewares import StaticDataMiddleware from frappe.utils.error import make_error_snapshot @@ -73,7 +74,10 @@ def application(request): response = frappe.utils.response.download_private_file(request.path) elif request.method in ('GET', 'HEAD', 'POST'): - response = frappe.website.render.render() + if frappe.conf.flag_new_website: + response = frappe.website.serve.render() + else: + response = frappe.website.render.render() else: raise NotFound diff --git a/frappe/tests/test_website_new.py b/frappe/tests/test_website_new.py index aa9e77d5ba..34786611d6 100644 --- a/frappe/tests/test_website_new.py +++ b/frappe/tests/test_website_new.py @@ -8,6 +8,12 @@ from frappe.website.utils import get_home_page from frappe.utils import set_request class TestWebsite(unittest.TestCase): + def setUp(self): + frappe.set_user('Guest') + + def tearDown(self): + frappe.set_user('Administrator') + def test_static_page(self): set_request(method='GET', path='/_test/static-file-test.png') response = serve.StaticPage().get() @@ -16,5 +22,14 @@ class TestWebsite(unittest.TestCase): def test_error_page(self): set_request(method='GET', path='/error') response = serve.TemplatePage().get() + self.assertEquals(response.status_code, 500) + + def test_login(self): + set_request(method='GET', path='/login') + response = serve.TemplatePage().get() self.assertEquals(response.status_code, 200) - print(response.get_data()) + + html = frappe.safe_decode(response.get_data()) + + self.assertTrue('// login.js' in html) + self.assertTrue('' in html) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 3f3e1d4571..a0710b9988 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -22,6 +22,8 @@ def render(path=None, http_status_code=None): path = resolve_path(path) data = None + # there is no way to determine the type of the page based on the route + # so evaluate each type of page sequentially response = StaticPage(path).get() if not response: response = TemplatePage(path).get() @@ -93,7 +95,8 @@ class TemplatePage(WebPage): def find_page_in_app(self, app): ''' - Searches for file matching the path in the /www and /templates/pages folders + Searches for file matching the path in the /www + and /templates/pages folders ''' app_path = frappe.get_app_path(app) folders = get_start_folders() @@ -128,9 +131,7 @@ class TemplatePage(WebPage): self.set_pymodule() self.setup_template() - - if self.pymodule_name: - self.update_context() + self.update_context() if self.source: html = frappe.render_template(self.source, self.context) @@ -178,18 +179,19 @@ class TemplatePage(WebPage): self.context.update(get_website_settings(self.context)) self.context.update(frappe.local.conf.get("website_context") or {}) - self.pymodule = frappe.get_module(self.pymodule_name) - - if self.pymodule: + if self.pymodule_name: + self.pymodule = frappe.get_module(self.pymodule_name) self.set_pymodule_properties() data = self.run_pymodule_method('get_context') + # some methods may return a "context" object if data: self.context.update(data) # TODO: self.context.children = self.run_pymodule_method('get_children') self.context.developer_mode = frappe.conf.developer_mode + self.status_code = self.context.http_status_code or 200 def set_pymodule_properties(self): for prop in ("base_template_path", "template", "no_cache", "sitemap", @@ -203,7 +205,7 @@ class TemplatePage(WebPage): def run_pymodule_method(self, method): if hasattr(self.pymodule, method): try: - return getattr(self.pymodule, method)(self) + return getattr(self.pymodule, method)(self.context) except (frappe.PermissionError, frappe.DoesNotExistError, frappe.Redirect): raise except: diff --git a/frappe/www/error.py b/frappe/www/error.py index 161038373d..9274fe7c26 100644 --- a/frappe/www/error.py +++ b/frappe/www/error.py @@ -8,5 +8,7 @@ no_cache = 1 def get_context(context): if frappe.flags.in_migrate: return + context.http_status_code = 500 + print(frappe.get_traceback().encode("utf-8")) return {"error": frappe.get_traceback().replace("<", "<").replace(">", ">") } From 4369b8c0dc3d88c3d37af7ead06a4b35e4812778 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 12 Feb 2021 10:02:10 +0530 Subject: [PATCH 003/868] fix(rendering): add doctype generate pages --- frappe/app.py | 7 +- frappe/sessions.py | 3 +- frappe/tests/test_website_new.py | 20 ++- frappe/website/context.py | 2 +- frappe/website/render.py | 7 + frappe/website/serve.py | 231 ++++++++++++++++++++++++++++--- frappe/www/404.py | 2 + 7 files changed, 241 insertions(+), 31 deletions(-) diff --git a/frappe/app.py b/frappe/app.py index 9495268f00..52a8d2fe1c 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -18,8 +18,6 @@ import frappe.handler import frappe.auth import frappe.api import frappe.utils.response -import frappe.website.serve -import frappe.website.page from frappe.utils import get_site_name, sanitize_html from frappe.middlewares import StaticDataMiddleware from frappe.utils.error import make_error_snapshot @@ -74,10 +72,7 @@ def application(request): response = frappe.utils.response.download_private_file(request.path) elif request.method in ('GET', 'HEAD', 'POST'): - if frappe.conf.flag_new_website: - response = frappe.website.serve.render() - else: - response = frappe.website.render.render() + response = frappe.website.render.render() else: raise NotFound diff --git a/frappe/sessions.py b/frappe/sessions.py index 1ca1d4ee6f..dddeb6f37f 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -169,7 +169,8 @@ def get_csrf_token(): def generate_csrf_token(): frappe.local.session.data.csrf_token = frappe.generate_hash() - frappe.local.session_obj.update(force=True) + if not frappe.flags.in_test: + frappe.local.session_obj.update(force=True) class Session: def __init__(self, user, resume=False, full_name=None, user_type=None): diff --git a/frappe/tests/test_website_new.py b/frappe/tests/test_website_new.py index 34786611d6..3d4c2a69ef 100644 --- a/frappe/tests/test_website_new.py +++ b/frappe/tests/test_website_new.py @@ -6,7 +6,6 @@ import frappe from frappe.website import serve from frappe.website.utils import get_home_page from frappe.utils import set_request - class TestWebsite(unittest.TestCase): def setUp(self): frappe.set_user('Guest') @@ -21,15 +20,30 @@ class TestWebsite(unittest.TestCase): def test_error_page(self): set_request(method='GET', path='/error') - response = serve.TemplatePage().get() + response = serve.get_response() self.assertEquals(response.status_code, 500) def test_login(self): set_request(method='GET', path='/login') - response = serve.TemplatePage().get() + response = serve.get_response() self.assertEquals(response.status_code, 200) html = frappe.safe_decode(response.get_data()) self.assertTrue('// login.js' in html) self.assertTrue('' in html) + + def test_app(self): + frappe.set_user('Administrator') + set_request(method='GET', path='/app') + response = serve.get_response() + self.assertEquals(response.status_code, 200) + + html = frappe.safe_decode(response.get_data()) + self.assertTrue('window.app = true;' in html) + frappe.local.session_obj = None + + def test_not_found(self): + set_request(method='GET', path='/_test/missing') + response = serve.get_response() + self.assertEquals(response.status_code, 404) diff --git a/frappe/website/context.py b/frappe/website/context.py index 4236971aec..abda2e3f4f 100644 --- a/frappe/website/context.py +++ b/frappe/website/context.py @@ -243,7 +243,7 @@ def add_metatags(context): tags["og:title"] = tags["twitter:title"] = title tags["twitter:card"] = "summary" - if "description" not in tags and context.description: + if not tags.get('description') and context.description: tags["description"] = context.description description = tags.get("description") diff --git a/frappe/website/render.py b/frappe/website/render.py index 2f8bc59d6d..ce9647c62a 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -26,6 +26,13 @@ from frappe.translate import guess_language class PageNotFoundError(Exception): pass def render(path=None, http_status_code=None): + if frappe.conf.flag_new_website: + from frappe.website.serve import get_response + return get_response() + else: + return render(path, http_status_code) + +def _render(path=None, http_status_code=None): """render html page""" if not path: path = frappe.local.request.path diff --git a/frappe/website/serve.py b/frappe/website/serve.py index a0710b9988..ec54e8c149 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -6,12 +6,13 @@ from werkzeug.wsgi import wrap_file from frappe.website.render import (resolve_path, build_response) from frappe.website.redirect import resolve_redirect -from frappe.website.router import get_start_folders +from frappe.website.router import (get_start_folders, get_doctypes_with_web_view, + get_page_info_from_web_page_with_dynamic_routes) from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, get_toc, get_next_link) from frappe.website.doctype.website_settings.website_settings import get_website_settings -def render(path=None, http_status_code=None): +def get_response(path=None, http_status_code=None): """render html page""" if not path: path = frappe.local.request.path @@ -87,7 +88,120 @@ class StaticPage(WebPage): response.mimetype = mimetypes.guess_type(self.file_path)[0] or 'application/octet-stream' return response -class TemplatePage(WebPage): +class BaseTemplatePage(WebPage): + def init_context(self): + self.context = frappe._dict() + self.context.update(get_website_settings(self.context)) + self.context.update(frappe.local.conf.get("website_context") or {}) + + def add_csrf_token(self, html): + if frappe.local.session: + return html.replace("", ''.format( + frappe.local.session.data.csrf_token)) + else: + return html + + def post_process_context(self): + self.add_metatags() + # add_sidebar_and_breadcrumbs(context) + + self.set_base_template_if_missing() + self.set_title_with_prefix() + self.update_website_context() + + # set using frappe.respond_as_web_page + if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): + context.update(frappe.local.response.context) + + # to be able to inspect the context dict + # Use the macro "inspect" from macros.html + self.context._context_dict = self.context + + def set_base_template_if_missing(self): + if not self.context.base_template_path: + app_base = frappe.get_hooks("base_template") + self.context.base_template_path = app_base[-1] if app_base else "templates/base.html" + + def set_title_with_prefix(self): + if (self.context.title_prefix and self.context.title + and not self.context.title.startswith(self.context.title_prefix)): + self.context.title = '{0} - {1}'.format(self.context.title_prefix, self.context.title) + + def update_website_context(self): + # apply context from hooks + update_website_context = frappe.get_hooks('update_website_context') + for method in update_website_context: + values = frappe.get_attr(method)(self.context) + if values: + self.context.update(values) + + def add_metatags(self): + self.tags = frappe._dict(self.context.get("metatags") or {}) + self.init_metatags_from_context() + self.set_opengraph_tags() + self.set_twitter_tags() + self.set_meta_published_on() + self.set_metatags_from_website_route_meta() + + self.context.metatags = self.tags + + def init_metatags_from_context(self): + for key in ('title', 'description', 'image', 'author', 'url', 'published_on'): + if not key in self.tags and self.context.get(key): + self.tags[key] = self.context[key] + + if not self.tags.get('title'): self.tags['title'] = self.context.get('name') + + if self.tags.get('image'): + self.tags['image'] = frappe.utils.get_url(self.tags['image']) + + self.tags["language"] = frappe.local.lang or "en" + + def set_opengraph_tags(self): + if "og:type" not in self.tags: + self.tags["og:type"] = "article" + + for key in ('title', 'description', 'image', 'author', 'url'): + if self.tags.get(key): + self.tags['og:' + key] = self.tags.get(key) + + def set_twitter_tags(self): + for key in ('title', 'description', 'image', 'author', 'url'): + if self.tags.get(key): + self.tags['twitter:' + key] = self.tags.get(key) + + if self.tags.get('image'): + self.tags['twitter:card'] = "summary_large_image" + else: + self.tags["twitter:card"] = "summary" + + def set_meta_published_on(self): + if "published_on" in self.tags: + self.tags["datePublished"] = self.tags["published_on"] + del self.tags["published_on"] + + def set_metatags_from_website_route_meta(self): + ''' + Get meta tags from Website Route meta + they can override the defaults set above + ''' + route = self.context.path + if route == '': + # homepage + route = frappe.db.get_single_value('Website Settings', 'home_page') + + route_exists = (route + and not route.endswith(('.js', '.css')) + and frappe.db.exists('Website Route Meta', route)) + + if route_exists: + website_route_meta = frappe.get_doc('Website Route Meta', route) + for meta_tag in website_route_meta.meta_tags: + d = meta_tag.get_meta_dict() + self.tags.update(d) + + +class TemplatePage(BaseTemplatePage): def validate(self): for app in frappe.get_installed_apps(frappe_last=True): if self.find_page_in_app(app): @@ -127,19 +241,16 @@ class TemplatePage(WebPage): def get_html(self): # context object should be separate from self for security # because it will be accessed via the user defined template - self.context = frappe._dict() + self.init_context() self.set_pymodule() self.setup_template() self.update_context() - - if self.source: - html = frappe.render_template(self.source, self.context) - - elif self.template_path: - html = self.render_template() + self.post_process_context() + html = self.render_template() html = self.update_toc(html) + html = self.add_csrf_token(html) return html @@ -176,8 +287,6 @@ class TemplatePage(WebPage): def update_context(self): self.set_page_properties() - self.context.update(get_website_settings(self.context)) - self.context.update(frappe.local.conf.get("website_context") or {}) if self.pymodule_name: self.pymodule = frappe.get_module(self.pymodule_name) @@ -213,12 +322,15 @@ class TemplatePage(WebPage): frappe.errprint(frappe.utils.get_traceback()) def render_template(self): - if self.path.endswith('min.js'): - # directly serve min.js pages using the jloader to find it in various apps - # (can be used as static?) - html = self.get_raw_template() - else: - html = frappe.get_template(self.template_path).render(self.context) + if self.source: + html = frappe.render_template(self.source, self.context) + elif self.template_path: + if self.path.endswith('min.js'): + html = self.get_raw_template() # static + else: + html = frappe.get_template(self.template_path).render(self.context) + + return html def extends_template(self): return (self.template_path.endswith(('.html', '.md', )) @@ -270,8 +382,87 @@ class TemplatePage(WebPage): return html -class DocTypePage(WebPage): - pass +class DocTypePage(BaseTemplatePage): + def validate(self): + ''' + Find a document with matching `route` from all doctypes with `has_web_view`=1 + ''' + if self.search_in_doctypes_with_web_view(): + return True + + if self.search_web_page_dynamic_routes(): + return True + + return False + + def search_in_doctypes_with_web_view(self): + for doctype in get_doctypes_with_web_view(): + filters = dict(route=self.path) + meta = frappe.get_meta(doctype) + condition_field = self.get_condition_field(meta) + + if condition_field: + filters[condition_field] = 1 + + try: + self.docname = frappe.db.get_value(doctype, filters, 'name') + if self.docname: + self.doctype = doctype + self.meta = meta + return True + except Exception as e: + if not frappe.db.is_missing_column(e): raise e + + def search_web_page_dynamic_routes(self): + d = get_page_info_from_web_page_with_dynamic_routes(self.path) + if d: + self.doctype = 'Web Page' + self.docname = d.name + self.meta = frappe.get_meta(self.doctype) + return True + else: + return False + + def render(self): + self.doc = frappe.get_doc(self.doctype, self.docname) + self.init_context() + self.update_context() + self.post_process_context() + + html = frappe.get_template(self.context.template_path).render(self.context) + html = self.add_csrf_token(html) + + return build_response(self.path, html, self.status_code, self.headers) + + def update_context(self): + self.context.doc = self.doc + self.context.update(self.context.doc.as_dict()) + self.context.update(self.context.doc.get_website_properties()) + + if not self.context.template_path: + self.context.template_path = self.context.doc.meta.get_web_template() + + if hasattr(self.doc, "get_context"): + ret = self.doc.get_context(self.context) + + if ret: + self.context.update(ret) + + for prop in ("no_cache", "sitemap"): + if not prop in self.context: + self.context[prop] = getattr(self.doc, prop, False) + + def get_condition_field(self, meta): + condition_field = None + if meta.is_published_field: + condition_field = meta.is_published_field + elif not meta.custom: + controller = get_controller(doctype) + condition_field = controller.website.condition_field + + return condition_field + + class WebFormPage(WebPage): pass diff --git a/frappe/www/404.py b/frappe/www/404.py index c9de234743..e02e1c3929 100644 --- a/frappe/www/404.py +++ b/frappe/www/404.py @@ -2,3 +2,5 @@ # MIT License. See license.txt from __future__ import unicode_literals +def get_context(context): + context.http_status_code = 404 From 46dc5af29a81bbe00b022e30e096add46ecb88dd Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 15 Feb 2021 12:55:47 +0530 Subject: [PATCH 004/868] fix(list): make list pages work --- frappe/website/doctype/blog_post/blog_post.py | 5 --- frappe/website/render.py | 5 +-- frappe/website/router.py | 2 +- frappe/website/serve.py | 34 +++++++++++++------ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/frappe/website/doctype/blog_post/blog_post.py b/frappe/website/doctype/blog_post/blog_post.py index 28549225be..e7c2772c69 100644 --- a/frappe/website/doctype/blog_post/blog_post.py +++ b/frappe/website/doctype/blog_post/blog_post.py @@ -13,11 +13,6 @@ from frappe.website.utils import (find_first_image, get_html_content_based_on_ty get_comment_list) class BlogPost(WebsiteGenerator): - website = frappe._dict( - route = 'blog', - order_by = "published_on desc" - ) - def make_route(self): if not self.route: return frappe.db.get_value('Blog Category', self.blog_category, diff --git a/frappe/website/render.py b/frappe/website/render.py index ce9647c62a..21d5dda8d5 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -26,11 +26,12 @@ from frappe.translate import guess_language class PageNotFoundError(Exception): pass def render(path=None, http_status_code=None): - if frappe.conf.flag_new_website: + # temp feature flag + if True or frappe.conf.flag_new_website: from frappe.website.serve import get_response return get_response() else: - return render(path, http_status_code) + return _render(path, http_status_code) def _render(path=None, http_status_code=None): """render html page""" diff --git a/frappe/website/router.py b/frappe/website/router.py index 946c83811a..5244c57ba8 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -441,4 +441,4 @@ def get_doctypes_with_web_view(): return frappe.cache().get_value('doctypes_with_web_view', _get) def get_start_folders(): - return frappe.local.flags.web_pages_folders or ('www', 'templates/pages') \ No newline at end of file + return frappe.local.flags.web_pages_folders or ('www', 'templates/pages') diff --git a/frappe/website/serve.py b/frappe/website/serve.py index ec54e8c149..6784dbefd9 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -29,7 +29,9 @@ def get_response(path=None, http_status_code=None): if not response: response = TemplatePage(path).get() if not response: - response = DocTypePage(path).get() + response = ListPage(path).get() + if not response: + response = DocumentPage(path).get() if not response: response = TemplatePage('404').get() except frappe.PermissionError as e: @@ -117,6 +119,11 @@ class BaseTemplatePage(WebPage): # Use the macro "inspect" from macros.html self.context._context_dict = self.context + # context sends us a new template path + if self.context.template: + self.template_path = self.context.template + + def set_base_template_if_missing(self): if not self.context.base_template_path: app_base = frappe.get_hooks("base_template") @@ -200,7 +207,6 @@ class BaseTemplatePage(WebPage): d = meta_tag.get_meta_dict() self.tags.update(d) - class TemplatePage(BaseTemplatePage): def validate(self): for app in frappe.get_installed_apps(frappe_last=True): @@ -222,8 +228,6 @@ class TemplatePage(BaseTemplatePage): if os.path.exists(file_path) and not os.path.isdir(file_path): self.app = app self.app_path = app_path - self.dirname = dirname - self.file_path = file_path self.template_path = os.path.relpath(file_path, self.app_path) return True @@ -244,9 +248,9 @@ class TemplatePage(BaseTemplatePage): self.init_context() self.set_pymodule() - self.setup_template() self.update_context() self.post_process_context() + self.setup_template() html = self.render_template() html = self.update_toc(html) @@ -380,9 +384,18 @@ class TemplatePage(BaseTemplatePage): html = html.replace('{next}', get_next_link(self.path)) return html - - -class DocTypePage(BaseTemplatePage): +class ListPage(TemplatePage): + def validate(self): + if frappe.db.get_value('DocType', self.path): + self.app = 'frappe' + self.app_path = frappe.get_app_path('frappe') + self.doctype = self.path + self.path = 'list' + self.template_path = 'www/list.html' + frappe.local.form_dict.doctype = self.doctype + return True + return False +class DocumentPage(BaseTemplatePage): def validate(self): ''' Find a document with matching `route` from all doctypes with `has_web_view`=1 @@ -462,8 +475,7 @@ class DocTypePage(BaseTemplatePage): return condition_field - - +class PrintPage(TemplatePage): + pass class WebFormPage(WebPage): pass - From 75ba0ca6a9be2f8a1d43529ff8a28a43efc42457 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 15 Feb 2021 13:49:38 +0530 Subject: [PATCH 005/868] fix(minor): website/serve.py --- frappe/website/serve.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 6784dbefd9..8f686144f1 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -113,7 +113,7 @@ class BaseTemplatePage(WebPage): # set using frappe.respond_as_web_page if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): - context.update(frappe.local.response.context) + self.context.update(frappe.local.response.context) # to be able to inspect the context dict # Use the macro "inspect" from macros.html @@ -384,6 +384,7 @@ class TemplatePage(BaseTemplatePage): html = html.replace('{next}', get_next_link(self.path)) return html + class ListPage(TemplatePage): def validate(self): if frappe.db.get_value('DocType', self.path): @@ -395,6 +396,7 @@ class ListPage(TemplatePage): frappe.local.form_dict.doctype = self.doctype return True return False + class DocumentPage(BaseTemplatePage): def validate(self): ''' @@ -477,5 +479,6 @@ class DocumentPage(BaseTemplatePage): class PrintPage(TemplatePage): pass + class WebFormPage(WebPage): pass From e79e1420612b814f1e65ce9b4021d0c31f00d00a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 15 Feb 2021 17:43:17 +0530 Subject: [PATCH 006/868] fix(minor): fix some tests and merge old and new website tests --- .../print_settings/print_settings.json | 4 +- frappe/tests/test_website.py | 46 ++++++++++- frappe/tests/test_website_new.py | 49 ------------ frappe/website/render.py | 2 +- frappe/website/serve.py | 80 ++++++++++++++----- frappe/www/message.py | 8 +- 6 files changed, 113 insertions(+), 76 deletions(-) delete mode 100644 frappe/tests/test_website_new.py diff --git a/frappe/printing/doctype/print_settings/print_settings.json b/frappe/printing/doctype/print_settings/print_settings.json index d64cb4c6d3..31962be050 100644 --- a/frappe/printing/doctype/print_settings/print_settings.json +++ b/frappe/printing/doctype/print_settings/print_settings.json @@ -148,7 +148,7 @@ "label": "Print Style" }, { - "default": "Modern", + "default": "Redesign", "fieldname": "print_style", "fieldtype": "Link", "in_list_view": 1, @@ -183,7 +183,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2020-10-22 23:42:09.471022", + "modified": "2021-02-15 14:16:18.474254", "modified_by": "Administrator", "module": "Printing", "name": "Print Settings", diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index c5da2bdfb7..91e08db457 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -4,13 +4,19 @@ import unittest import frappe from frappe.website import render +from frappe.website import serve from frappe.website.utils import get_home_page from frappe.utils import set_request - class TestWebsite(unittest.TestCase): + def setUp(self): + frappe.set_user('Guest') + + def tearDown(self): + frappe.set_user('Administrator') def test_home_page_for_role(self): + frappe.set_user('Administrator') frappe.delete_doc_if_exists('User', 'test-user-for-home-page@example.com') frappe.delete_doc_if_exists('Role', 'home-page-test') frappe.delete_doc_if_exists('Web Page', 'home-page-test') @@ -44,7 +50,6 @@ class TestWebsite(unittest.TestCase): self.assertEqual(get_home_page(), 'test-portal-home') def test_page_load(self): - frappe.set_user('Guest') set_request(method='POST', path='login') response = render.render() @@ -54,10 +59,47 @@ class TestWebsite(unittest.TestCase): self.assertTrue('// login.js' in html) self.assertTrue('' in html) + + def test_static_page(self): + set_request(method='GET', path='/_test/static-file-test.png') + response = serve.get_response() + self.assertEquals(response.status_code, 200) + + def test_error_page(self): + set_request(method='GET', path='/error') + response = serve.get_response() + self.assertEquals(response.status_code, 500) + + def test_login(self): + set_request(method='GET', path='/login') + response = serve.get_response() + self.assertEquals(response.status_code, 200) + + html = frappe.safe_decode(response.get_data()) + + self.assertTrue('// login.js' in html) + self.assertTrue('' in html) + + def test_app(self): frappe.set_user('Administrator') + set_request(method='GET', path='/app') + response = serve.get_response() + self.assertEquals(response.status_code, 200) + + html = frappe.safe_decode(response.get_data()) + self.assertTrue('window.app = true;' in html) + frappe.local.session_obj = None + + def test_not_found(self): + set_request(method='GET', path='/_test/missing') + response = serve.get_response() + self.assertEquals(response.status_code, 404) + def test_redirect(self): import frappe.hooks + frappe.set_user('Administrator') + frappe.hooks.website_redirects = [ dict(source=r'/testfrom', target=r'://testto1'), dict(source=r'/testfromregex.*', target=r'://testto2'), diff --git a/frappe/tests/test_website_new.py b/frappe/tests/test_website_new.py deleted file mode 100644 index 3d4c2a69ef..0000000000 --- a/frappe/tests/test_website_new.py +++ /dev/null @@ -1,49 +0,0 @@ -from __future__ import unicode_literals - -import unittest - -import frappe -from frappe.website import serve -from frappe.website.utils import get_home_page -from frappe.utils import set_request -class TestWebsite(unittest.TestCase): - def setUp(self): - frappe.set_user('Guest') - - def tearDown(self): - frappe.set_user('Administrator') - - def test_static_page(self): - set_request(method='GET', path='/_test/static-file-test.png') - response = serve.StaticPage().get() - self.assertEquals(response.status_code, 200) - - def test_error_page(self): - set_request(method='GET', path='/error') - response = serve.get_response() - self.assertEquals(response.status_code, 500) - - def test_login(self): - set_request(method='GET', path='/login') - response = serve.get_response() - self.assertEquals(response.status_code, 200) - - html = frappe.safe_decode(response.get_data()) - - self.assertTrue('// login.js' in html) - self.assertTrue('' in html) - - def test_app(self): - frappe.set_user('Administrator') - set_request(method='GET', path='/app') - response = serve.get_response() - self.assertEquals(response.status_code, 200) - - html = frappe.safe_decode(response.get_data()) - self.assertTrue('window.app = true;' in html) - frappe.local.session_obj = None - - def test_not_found(self): - set_request(method='GET', path='/_test/missing') - response = serve.get_response() - self.assertEquals(response.status_code, 404) diff --git a/frappe/website/render.py b/frappe/website/render.py index 21d5dda8d5..65f871b8a0 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -29,7 +29,7 @@ def render(path=None, http_status_code=None): # temp feature flag if True or frappe.conf.flag_new_website: from frappe.website.serve import get_response - return get_response() + return get_response(path, http_status_code) else: return _render(path, http_status_code) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 8f686144f1..927909e75f 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -25,26 +25,34 @@ def get_response(path=None, http_status_code=None): # there is no way to determine the type of the page based on the route # so evaluate each type of page sequentially - response = StaticPage(path).get() + response = StaticPage(path, http_status_code).get() if not response: - response = TemplatePage(path).get() + response = TemplatePage(path, http_status_code).get() if not response: - response = ListPage(path).get() + response = ListPage(path, http_status_code).get() if not response: - response = DocumentPage(path).get() + response = DocumentPage(path, http_status_code).get() if not response: - response = TemplatePage('404').get() + response = PrintPage(path, http_status_code).get() + if not response: + response = TemplatePage('404', 404).get() + except frappe.Redirect: + return build_response(path, "", 301, { + "Location": frappe.flags.redirect_location or (frappe.local.response or {}).get('location'), + "Cache-Control": "no-store, no-cache, must-revalidate" + }) except frappe.PermissionError as e: - response = TemplatePage('403').get() - except: - response = TemplatePage('error').get() + frappe.local.message = cstr(e) + response = NotPermittedPage(path, http_status_code).get() + except Exception as e: + response = TemplatePage('error', getattr(e, 'http_status_code', 500) or http_status_code).get() return response class WebPage(object): - def __init__(self, path=None): + def __init__(self, path=None, http_status_code=200): self.headers = None - self.status_code = 200 + self.http_status_code = http_status_code if not path: path = frappe.local.request.path self.path = path.strip('/ ') @@ -240,7 +248,7 @@ class TemplatePage(BaseTemplatePage): search_path + '/index.md') def render(self): - return build_response(self.path, self.get_html(), self.status_code, self.headers) + return build_response(self.path, self.get_html(), self.http_status_code, self.headers) def get_html(self): # context object should be separate from self for security @@ -304,7 +312,8 @@ class TemplatePage(BaseTemplatePage): # TODO: self.context.children = self.run_pymodule_method('get_children') self.context.developer_mode = frappe.conf.developer_mode - self.status_code = self.context.http_status_code or 200 + if self.context.http_status_code: + self.http_status_code = self.context.http_status_code def set_pymodule_properties(self): for prop in ("base_template_path", "template", "no_cache", "sitemap", @@ -385,18 +394,50 @@ class TemplatePage(BaseTemplatePage): return html + def set_standard_path(self, path): + self.app = 'frappe' + self.app_path = frappe.get_app_path('frappe') + self.path = path + self.template_path = 'www/{path}.html'.format(path=path) + + class ListPage(TemplatePage): def validate(self): if frappe.db.get_value('DocType', self.path): - self.app = 'frappe' - self.app_path = frappe.get_app_path('frappe') - self.doctype = self.path - self.path = 'list' - self.template_path = 'www/list.html' - frappe.local.form_dict.doctype = self.doctype + frappe.local.form_dict.doctype = self.path + self.set_standard_path('list') return True return False +class PrintPage(TemplatePage): + ''' + default path returns a printable object (based on permission) + /Quotation/Q-0001 + ''' + def validate(self): + parts = self.path.split('/', 1) + if len(parts)==2: + if (frappe.db.get_value('DocType', parts[0]) + and frappe.db.get_value(parts[0], parts[1])): + frappe.form_dict.doctype = parts[0] + frappe.form_dict.name = parts[1] + self.set_standard_path('printview') + return True + + return False + +class NotPermittedPage(TemplatePage): + def validate(self): + frappe.local.message_title = _("Not Permitted") + frappe.local.response['context'] = dict( + indicator_color = 'red', + primary_action = '/login', + primary_label = _('Login'), + fullpage=True + ) + self.set_standard_path('message') + return True + class DocumentPage(BaseTemplatePage): def validate(self): ''' @@ -477,8 +518,5 @@ class DocumentPage(BaseTemplatePage): return condition_field -class PrintPage(TemplatePage): - pass - class WebFormPage(WebPage): pass diff --git a/frappe/www/message.py b/frappe/www/message.py index ea45b9c4b5..d650170073 100644 --- a/frappe/www/message.py +++ b/frappe/www/message.py @@ -9,7 +9,7 @@ from frappe.utils import strip_html_tags no_cache = 1 def get_context(context): - message_context = {} + message_context = frappe._dict() if hasattr(frappe.local, "message"): message_context["header"] = frappe.local.message_title message_context["title"] = strip_html_tags(frappe.local.message_title) @@ -26,4 +26,10 @@ def get_context(context): if message.get('http_status_code'): frappe.local.response['http_status_code'] = message['http_status_code'] + if not message_context.title: + message_context.title = frappe.form_dict.title + + if not message_context.message: + message_context.message = frappe.form_dict.message + return message_context From b699d92f5ee57d54918221fb9d74c54ca4cfe24a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 15 Feb 2021 18:05:44 +0530 Subject: [PATCH 007/868] fix(minor): http_status_code --- frappe/website/serve.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 927909e75f..b635d9615b 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -12,7 +12,7 @@ from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, get_toc, get_next_link) from frappe.website.doctype.website_settings.website_settings import get_website_settings -def get_response(path=None, http_status_code=None): +def get_response(path=None, http_status_code=200): """render html page""" if not path: path = frappe.local.request.path @@ -45,14 +45,14 @@ def get_response(path=None, http_status_code=None): frappe.local.message = cstr(e) response = NotPermittedPage(path, http_status_code).get() except Exception as e: - response = TemplatePage('error', getattr(e, 'http_status_code', 500) or http_status_code).get() + response = TemplatePage('error', getattr(e, 'http_status_code', None) or http_status_code).get() return response class WebPage(object): - def __init__(self, path=None, http_status_code=200): + def __init__(self, path=None, http_status_code=None): self.headers = None - self.http_status_code = http_status_code + self.http_status_code = http_status_code or 200 if not path: path = frappe.local.request.path self.path = path.strip('/ ') @@ -488,7 +488,7 @@ class DocumentPage(BaseTemplatePage): html = frappe.get_template(self.context.template_path).render(self.context) html = self.add_csrf_token(html) - return build_response(self.path, html, self.status_code, self.headers) + return build_response(self.path, html, self.http_status_code or 200, self.headers) def update_context(self): self.context.doc = self.doc From 30659b9ee28e034c6eef7ba682eea5b302b6fb6b Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 11 Mar 2021 10:29:12 +0530 Subject: [PATCH 008/868] feat: Option to consider query string while writing website redirect - if match_with_query_string is true in a website redirect rule, system will try to match the regex with the result of route + query_string --- frappe/tests/test_website.py | 20 +++++++++++++------- frappe/website/redirect.py | 12 ++++++++---- frappe/website/serve.py | 28 ++++++++++++++++++---------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 91e08db457..ce165e36d9 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -51,7 +51,7 @@ class TestWebsite(unittest.TestCase): def test_page_load(self): set_request(method='POST', path='login') - response = render.render() + response = serve.get_response() self.assertEquals(response.status_code, 200) @@ -103,7 +103,8 @@ class TestWebsite(unittest.TestCase): frappe.hooks.website_redirects = [ dict(source=r'/testfrom', target=r'://testto1'), dict(source=r'/testfromregex.*', target=r'://testto2'), - dict(source=r'/testsub/(.*)', target=r'://testto3/\1') + dict(source=r'/testsub/(.*)', target=r'://testto3/\1'), + dict(source=r'/courses/course\?course=(.*)', target=r'/courses/\1', match_with_query_string=True), ] website_settings = frappe.get_doc('Website Settings') @@ -117,28 +118,33 @@ class TestWebsite(unittest.TestCase): frappe.cache().delete_key('website_redirects') set_request(method='GET', path='/testfrom') - response = render.render() + response = serve.get_response() self.assertEquals(response.status_code, 301) self.assertEquals(response.headers.get('Location'), r'://testto1') set_request(method='GET', path='/testfromregex/test') - response = render.render() + response = serve.get_response() self.assertEquals(response.status_code, 301) self.assertEquals(response.headers.get('Location'), r'://testto2') set_request(method='GET', path='/testsub/me') - response = render.render() + response = serve.get_response() self.assertEquals(response.status_code, 301) self.assertEquals(response.headers.get('Location'), r'://testto3/me') set_request(method='GET', path='/test404') - response = render.render() + response = serve.get_response() self.assertEquals(response.status_code, 404) set_request(method='GET', path='/testsource') - response = render.render() + response = serve.get_response() self.assertEquals(response.status_code, 301) self.assertEquals(response.headers.get('Location'), '/testtarget') + set_request(method='GET', path='/courses/course?course=data') + response = serve.get_response() + self.assertEquals(response.status_code, 301) + self.assertEquals(response.headers.get('Location'), '/courses/data') + delattr(frappe.hooks, 'website_redirects') frappe.cache().delete_key('app_hooks') diff --git a/frappe/website/redirect.py b/frappe/website/redirect.py index 73e3c21727..e66c0a3b7b 100644 --- a/frappe/website/redirect.py +++ b/frappe/website/redirect.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import re, frappe -def resolve_redirect(path): +def resolve_redirect(path, query_string=None): ''' Resolve redirects from hooks @@ -33,9 +33,13 @@ def resolve_redirect(path): for rule in redirects: pattern = rule['source'].strip('/ ') + '$' - if re.match(pattern, path): - redirect_to = re.sub(pattern, rule['target'], path) + path_to_match = path + if rule.get('match_with_query_string'): + path_to_match = path + '?' + frappe.safe_decode(query_string) + + if re.match(pattern, path_to_match): + redirect_to = re.sub(pattern, rule['target'], path_to_match) frappe.flags.redirect_location = redirect_to - frappe.cache().hset('website_redirects', path, redirect_to) + frappe.cache().hset('website_redirects', path_to_match, redirect_to) raise frappe.Redirect diff --git a/frappe/website/serve.py b/frappe/website/serve.py index b635d9615b..11e950573e 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,25 +1,33 @@ -import frappe -import os, mimetypes +import mimetypes +import os from werkzeug.wrappers import Response from werkzeug.wsgi import wrap_file -from frappe.website.render import (resolve_path, build_response) +import frappe +from frappe import _ +from frappe.utils import cint, cstr +from frappe.model.document import get_controller +from frappe.website.doctype.website_settings.website_settings import \ + get_website_settings from frappe.website.redirect import resolve_redirect -from frappe.website.router import (get_start_folders, get_doctypes_with_web_view, - get_page_info_from_web_page_with_dynamic_routes) -from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, - get_toc, get_next_link) -from frappe.website.doctype.website_settings.website_settings import get_website_settings +from frappe.website.render import build_response, resolve_path +from frappe.website.router import (get_doctypes_with_web_view, + get_page_info_from_web_page_with_dynamic_routes, get_start_folders) +from frappe.website.utils import (can_cache, delete_page_cache, get_home_page, + get_next_link, get_toc) + def get_response(path=None, http_status_code=200): """render html page""" + query_string = None if not path: path = frappe.local.request.path + query_string = frappe.local.request.query_string try: path = path.strip('/ ') - resolve_redirect(path) + resolve_redirect(path, query_string) path = resolve_path(path) data = None @@ -513,7 +521,7 @@ class DocumentPage(BaseTemplatePage): if meta.is_published_field: condition_field = meta.is_published_field elif not meta.custom: - controller = get_controller(doctype) + controller = get_controller(meta.doctype) condition_field = controller.website.condition_field return condition_field From 39da825592429ab933e65368ef30d39de7a9208e Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 12 Mar 2021 11:42:24 +0530 Subject: [PATCH 009/868] refactor: Move page controllers to separate files - Make template page work --- .../page_controllers/base_template_page.py | 128 +++++ .../website/page_controllers/document_page.py | 88 ++++ frappe/website/page_controllers/list_page.py | 10 + .../page_controllers/not_permitted_page.py | 15 + frappe/website/page_controllers/print_page.py | 19 + .../website/page_controllers/static_page.py | 40 ++ .../website/page_controllers/template_page.py | 276 ++++++++++ frappe/website/page_controllers/web_form.py | 4 + frappe/website/page_controllers/web_page.py | 21 + frappe/website/serve.py | 496 +----------------- 10 files changed, 610 insertions(+), 487 deletions(-) create mode 100644 frappe/website/page_controllers/base_template_page.py create mode 100644 frappe/website/page_controllers/document_page.py create mode 100644 frappe/website/page_controllers/list_page.py create mode 100644 frappe/website/page_controllers/not_permitted_page.py create mode 100644 frappe/website/page_controllers/print_page.py create mode 100644 frappe/website/page_controllers/static_page.py create mode 100644 frappe/website/page_controllers/template_page.py create mode 100644 frappe/website/page_controllers/web_form.py create mode 100644 frappe/website/page_controllers/web_page.py diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py new file mode 100644 index 0000000000..10e2375356 --- /dev/null +++ b/frappe/website/page_controllers/base_template_page.py @@ -0,0 +1,128 @@ +import frappe +from frappe import _ +from frappe.website.context import add_sidebar_and_breadcrumbs +from frappe.website.doctype.website_settings.website_settings import \ + get_website_settings +from frappe.website.page_controllers.web_page import WebPage + + +class BaseTemplatePage(WebPage): + def init_context(self): + self.context = frappe._dict() + self.context.update(get_website_settings(self.context)) + self.context.update(frappe.local.conf.get("website_context") or {}) + + def add_csrf_token(self, html): + if frappe.local.session: + return html.replace("", ''.format( + frappe.local.session.data.csrf_token)) + else: + return html + + def post_process_context(self): + self.set_missing_values() + self.add_metatags() + self.add_sidebar_and_breadcrumbs() + + self.set_base_template_if_missing() + self.set_title_with_prefix() + self.update_website_context() + + # set using frappe.respond_as_web_page + if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): + self.context.update(frappe.local.response.context) + + # to be able to inspect the context dict + # Use the macro "inspect" from macros.html + self.context._context_dict = self.context + + # context sends us a new template path + if self.context.template: + self.template_path = self.context.template + + + def set_base_template_if_missing(self): + if not self.context.base_template_path: + app_base = frappe.get_hooks("base_template") + self.context.base_template_path = app_base[-1] if app_base else "templates/base.html" + + def set_title_with_prefix(self): + if (self.context.title_prefix and self.context.title + and not self.context.title.startswith(self.context.title_prefix)): + self.context.title = '{0} - {1}'.format(self.context.title_prefix, self.context.title) + + def update_website_context(self): + # apply context from hooks + update_website_context = frappe.get_hooks('update_website_context') + for method in update_website_context: + values = frappe.get_attr(method)(self.context) + if values: + self.context.update(values) + + def add_metatags(self): + self.tags = frappe._dict(self.context.get("metatags") or {}) + self.init_metatags_from_context() + self.set_opengraph_tags() + self.set_twitter_tags() + self.set_meta_published_on() + self.set_metatags_from_website_route_meta() + + self.context.metatags = self.tags + + def add_sidebar_and_breadcrumbs(self): + add_sidebar_and_breadcrumbs(self.context) + + def init_metatags_from_context(self): + for key in ('title', 'description', 'image', 'author', 'url', 'published_on'): + if not key in self.tags and self.context.get(key): + self.tags[key] = self.context[key] + + if not self.tags.get('title'): self.tags['title'] = self.context.get('name') + + if self.tags.get('image'): + self.tags['image'] = frappe.utils.get_url(self.tags['image']) + + self.tags["language"] = frappe.local.lang or "en" + + def set_opengraph_tags(self): + if "og:type" not in self.tags: + self.tags["og:type"] = "article" + + for key in ('title', 'description', 'image', 'author', 'url'): + if self.tags.get(key): + self.tags['og:' + key] = self.tags.get(key) + + def set_twitter_tags(self): + for key in ('title', 'description', 'image', 'author', 'url'): + if self.tags.get(key): + self.tags['twitter:' + key] = self.tags.get(key) + + if self.tags.get('image'): + self.tags['twitter:card'] = "summary_large_image" + else: + self.tags["twitter:card"] = "summary" + + def set_meta_published_on(self): + if "published_on" in self.tags: + self.tags["datePublished"] = self.tags["published_on"] + del self.tags["published_on"] + + def set_metatags_from_website_route_meta(self): + ''' + Get meta tags from Website Route meta + they can override the defaults set above + ''' + route = self.context.path + if route == '': + # homepage + route = frappe.db.get_single_value('Website Settings', 'home_page') + + route_exists = (route + and not route.endswith(('.js', '.css')) + and frappe.db.exists('Website Route Meta', route)) + + if route_exists: + website_route_meta = frappe.get_doc('Website Route Meta', route) + for meta_tag in website_route_meta.meta_tags: + d = meta_tag.get_meta_dict() + self.tags.update(d) diff --git a/frappe/website/page_controllers/document_page.py b/frappe/website/page_controllers/document_page.py new file mode 100644 index 0000000000..bb00d78c0c --- /dev/null +++ b/frappe/website/page_controllers/document_page.py @@ -0,0 +1,88 @@ +import frappe +from frappe import _ +from frappe.model.document import get_controller +from frappe.website.page_controllers.base_template_page import BaseTemplatePage +from frappe.website.render import build_response +from frappe.website.router import (get_doctypes_with_web_view, + get_page_info_from_web_page_with_dynamic_routes) + + +class DocumentPage(BaseTemplatePage): + def validate(self): + ''' + Find a document with matching `route` from all doctypes with `has_web_view`=1 + ''' + if self.search_in_doctypes_with_web_view(): + return True + + if self.search_web_page_dynamic_routes(): + return True + + return False + + def search_in_doctypes_with_web_view(self): + for doctype in get_doctypes_with_web_view(): + filters = dict(route=self.path) + meta = frappe.get_meta(doctype) + condition_field = self.get_condition_field(meta) + + if condition_field: + filters[condition_field] = 1 + + try: + self.docname = frappe.db.get_value(doctype, filters, 'name') + if self.docname: + self.doctype = doctype + self.meta = meta + return True + except Exception as e: + if not frappe.db.is_missing_column(e): raise e + + def search_web_page_dynamic_routes(self): + d = get_page_info_from_web_page_with_dynamic_routes(self.path) + if d: + self.doctype = 'Web Page' + self.docname = d.name + self.meta = frappe.get_meta(self.doctype) + return True + else: + return False + + def render(self): + self.doc = frappe.get_doc(self.doctype, self.docname) + self.init_context() + self.update_context() + self.post_process_context() + + html = frappe.get_template(self.context.template_path).render(self.context) + html = self.add_csrf_token(html) + + return build_response(self.path, html, self.http_status_code or 200, self.headers) + + def update_context(self): + self.context.doc = self.doc + self.context.update(self.context.doc.as_dict()) + self.context.update(self.context.doc.get_website_properties()) + + if not self.context.template_path: + self.context.template_path = self.context.doc.meta.get_web_template() + + if hasattr(self.doc, "get_context"): + ret = self.doc.get_context(self.context) + + if ret: + self.context.update(ret) + + for prop in ("no_cache", "sitemap"): + if not prop in self.context: + self.context[prop] = getattr(self.doc, prop, False) + + def get_condition_field(self, meta): + condition_field = None + if meta.is_published_field: + condition_field = meta.is_published_field + elif not meta.custom: + controller = get_controller(meta.doctype) + condition_field = controller.website.condition_field + + return condition_field diff --git a/frappe/website/page_controllers/list_page.py b/frappe/website/page_controllers/list_page.py new file mode 100644 index 0000000000..2cb6ed5f26 --- /dev/null +++ b/frappe/website/page_controllers/list_page.py @@ -0,0 +1,10 @@ +import frappe +from frappe.website.page_controllers.template_page import TemplatePage + +class ListPage(TemplatePage): + def validate(self): + if frappe.db.get_value('DocType', self.path): + frappe.local.form_dict.doctype = self.path + self.set_standard_path('list') + return True + return False diff --git a/frappe/website/page_controllers/not_permitted_page.py b/frappe/website/page_controllers/not_permitted_page.py new file mode 100644 index 0000000000..e0cd6bf970 --- /dev/null +++ b/frappe/website/page_controllers/not_permitted_page.py @@ -0,0 +1,15 @@ +import frappe +from frappe import _ +from frappe.website.page_controllers.template_page import TemplatePage + +class NotPermittedPage(TemplatePage): + def validate(self): + frappe.local.message_title = _("Not Permitted") + frappe.local.response['context'] = dict( + indicator_color = 'red', + primary_action = '/login', + primary_label = _('Login'), + fullpage=True + ) + self.set_standard_path('message') + return True diff --git a/frappe/website/page_controllers/print_page.py b/frappe/website/page_controllers/print_page.py new file mode 100644 index 0000000000..6daea7fcbc --- /dev/null +++ b/frappe/website/page_controllers/print_page.py @@ -0,0 +1,19 @@ +import frappe +from frappe.website.page_controllers.template_page import TemplatePage + +class PrintPage(TemplatePage): + ''' + default path returns a printable object (based on permission) + /Quotation/Q-0001 + ''' + def validate(self): + parts = self.path.split('/', 1) + if len(parts)==2: + if (frappe.db.get_value('DocType', parts[0]) + and frappe.db.get_value(parts[0], parts[1])): + frappe.form_dict.doctype = parts[0] + frappe.form_dict.name = parts[1] + self.set_standard_path('printview') + return True + + return False diff --git a/frappe/website/page_controllers/static_page.py b/frappe/website/page_controllers/static_page.py new file mode 100644 index 0000000000..4b57c3ec42 --- /dev/null +++ b/frappe/website/page_controllers/static_page.py @@ -0,0 +1,40 @@ +import mimetypes +import os + +from werkzeug.wrappers import Response +from werkzeug.wsgi import wrap_file + +import frappe +from frappe.website.page_controllers.web_page import WebPage + + +class StaticPage(WebPage): + def validate(self): + if ('.' not in self.path): + return False + extn = self.path.rsplit('.', 1)[-1] + if extn in ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json'): + return False + + if self.find_path_in_apps(): + return True + + return False + + def find_path_in_apps(self): + for app in frappe.get_installed_apps(): + file_path = frappe.get_app_path(app, 'www') + '/' + self.path + if os.path.exists(file_path): + self.file_path = file_path + return True + return False + + def render(self): + try: + f = open(self.file_path, 'rb') + except IOError: + raise frappe.exceptions.NotFound + + response = Response(wrap_file(frappe.local.request.environ, f), direct_passthrough=True) + response.mimetype = mimetypes.guess_type(self.file_path)[0] or 'application/octet-stream' + return response diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py new file mode 100644 index 0000000000..46e6e6a57e --- /dev/null +++ b/frappe/website/page_controllers/template_page.py @@ -0,0 +1,276 @@ +import io +import os + +import frappe +from frappe import _ +from frappe.website.page_controllers.base_template_page import BaseTemplatePage +from frappe.website.render import build_response +from frappe.website.utils import (extract_comment_tag, extract_title, + get_next_link, get_toc) + + +class TemplatePage(BaseTemplatePage): + def validate(self): + for app in frappe.get_installed_apps(frappe_last=True): + if self.find_page_in_app(app): + return True + + def find_page_in_app(self, app): + ''' + Searches for file matching the path in the /www + and /templates/pages folders + ''' + app_path = frappe.get_app_path(app) + folders = get_start_folders() + + for dirname in folders: + search_path = os.path.join(app_path, dirname, self.path) + for p in self.get_index_path_options(search_path): + file_path = frappe.as_unicode(p) + if os.path.exists(file_path) and not os.path.isdir(file_path): + self.app = app + self.app_path = app_path + self.template_path = os.path.relpath(file_path, self.app_path) + return True + + def get_index_path_options(self, search_path): + return ( + search_path, + search_path + '.html', + search_path + '.md', + search_path + '/index.html', + search_path + '/index.md') + + def render(self): + return build_response(self.path, self.get_html(), self.http_status_code, self.headers) + + def get_html(self): + # context object should be separate from self for security + # because it will be accessed via the user defined template + self.init_context() + + self.set_pymodule() + self.setup_template() + self.update_context() + self.post_process_context() + html = self.render_template() + + html = self.update_toc(html) + html = self.add_csrf_token(html) + + return html + + def set_pymodule(self): + ''' + A template may have a python module with a `get_context` method along with it in the + same folder. Also the hyphens will be coverted to underscore for python module names. + This method sets the pymodule_name if it exists. + ''' + self.basepath = self.template_path.rsplit('.', 1)[0] + self.pymodule_name = None + + # replace - with _ in the internal modules names + self.pymodule_path = os.path.join(self.basepath.replace("-", "_") + ".py") + + if os.path.exists(os.path.join(self.app_path, self.pymodule_path)): + self.pymodule_name = self.app + "." + self.pymodule_path.replace(os.path.sep, ".")[:-3] + + def setup_template(self): + '''Setup template source, frontmatter and markdown conversion''' + self.source = self.get_raw_template() + + if self.template_path.endswith(('.md', '.html')): + self.extract_frontmatter() + + self.convert_from_markdown() + + if self.extends_template(): + self.context.base_template_path = self.context.base_template_path or 'templates/base.html' + + + # TODO: setup index.txt ? + + def update_context(self): + self.set_page_properties() + self.set_properties_from_source() + self.load_colocated_files() + self.context.build_version = frappe.utils.get_build_version() + + if self.pymodule_name: + self.pymodule = frappe.get_module(self.pymodule_name) + self.set_pymodule_properties() + + data = self.run_pymodule_method('get_context') + + # some methods may return a "context" object + if data: self.context.update(data) + + # TODO: self.context.children = self.run_pymodule_method('get_children') + + self.context.developer_mode = frappe.conf.developer_mode + if self.context.http_status_code: + self.http_status_code = self.context.http_status_code + + def set_pymodule_properties(self): + for prop in ("base_template_path", "template", "no_cache", "sitemap", + "condition_field"): + if hasattr(self.pymodule, prop): + self.context[prop] = getattr(self.pymodule, prop) + + def set_page_properties(self): + self.context.template = self.template_path + self.context.base_template = self.context.base_template or 'templates/web.html' + + def set_properties_from_source(self): + if not self.source: + return + context = self.context + if not context.title: + context.title = extract_title(self.source, self.path) + + base_template = extract_comment_tag(self.source, 'base_template') + if base_template: + context.base_template = base_template + + if (context.base_template + and "{%- extends" not in self.source + and "{% extends" not in self.source + and "" not in self.source): + self.source = '''{{% extends "{0}" %}} + {{% block page_content %}}{1}{{% endblock %}}'''.format(context.base_template, self.source) + + if "" in self.source: + context.no_breadcrumbs = 1 + + if "" in self.source: + context.show_sidebar = 1 + + if "" in self.source: + context.add_breadcrumbs = 1 + + if "" in self.source: + context.no_header = 1 + + if "" in self.source: + context.add_next_prev_links = 1 + + if "" in self.source: + context.no_cache = 1 + + if "" in self.source: + context.sitemap = 0 + + if "" in self.source: + context.sitemap = 1 + + def run_pymodule_method(self, method): + if hasattr(self.pymodule, method): + try: + return getattr(self.pymodule, method)(self.context) + except (frappe.PermissionError, frappe.DoesNotExistError, frappe.Redirect): + raise + except: + if not frappe.flags.in_migrate: + frappe.errprint(frappe.utils.get_traceback()) + + def render_template(self): + if self.source: + html = frappe.render_template(self.source, self.context) + elif self.template_path: + if self.path.endswith('min.js'): + html = self.get_raw_template() # static + else: + html = frappe.get_template(self.template_path).render(self.context) + + return html + + def extends_template(self): + return (self.template_path.endswith(('.html', '.md', )) + and ('{%- extends' in self.source + or '{% extends' in self.source)) + + def get_raw_template(self): + return frappe.get_jloader().get_source(frappe.get_jenv(), self.template_path)[0] + + def load_colocated_files(self): + '''load co-located css/js files with the same name''' + js_path = self.basepath + '.js' + if os.path.exists(js_path) and '{% block script %}' not in self.source: + self.context.colocated_js = self.get_colocated_file(js_path) + + css_path = self.basepath + '.css' + if os.path.exists(css_path) and '{% block style %}' not in self.source: + self.context.colocated_css = self.get_colocated_file(css_path) + + def get_colocated_file(self, path): + with io.open(path, 'r', encoding = 'utf-8') as f: + return f.read() + + def extract_frontmatter(self): + try: + # values will be used to update self + res = get_frontmatter(self.source) + if res['attributes']: + self.context.update(res['attributes']) + self.source = res['body'] + except Exception: + pass + + def convert_from_markdown(self): + if self.template_path.endswith('.md'): + self.source = frappe.utils.md_to_html(self.source) + self.page_toc_html = self.source.toc_html + + if not self.context.show_sidebar: + self.source = '
' + self.source + '
' + + def update_toc(self, html): + if '{index}' in html: + html = html.replace('{index}', get_toc(self.path)) + + if '{next}' in html: + html = html.replace('{next}', get_next_link(self.path)) + + return html + + def set_standard_path(self, path): + self.app = 'frappe' + self.app_path = frappe.get_app_path('frappe') + self.path = path + self.template_path = 'www/{path}.html'.format(path=path) + + def set_missing_values(self): + if not "url_prefix" in self.context: + self.context.url_prefix = "" + + if self.context.url_prefix and self.context.url_prefix[-1]!='/': + self.context.url_prefix += '/' + + # for backward compatibility + self.context.docs_base_url = '/docs' + self.context.path = self.path + + +def get_start_folders(): + return frappe.local.flags.web_pages_folders or ('www', 'templates/pages') + +def get_frontmatter(string): + """ + Reference: https://github.com/jonbeebe/frontmatter + """ + import re + + import yaml + + fmatter = "" + body = "" + result = re.compile(r'^\s*(?:---|\+\+\+)(.*?)(?:---|\+\+\+)\s*(.+)$', re.S | re.M).search(string) + + if result: + fmatter = result.group(1) + body = result.group(2) + + return { + "attributes": yaml.safe_load(fmatter), + "body": body, + } diff --git a/frappe/website/page_controllers/web_form.py b/frappe/website/page_controllers/web_form.py new file mode 100644 index 0000000000..030e8bb3bc --- /dev/null +++ b/frappe/website/page_controllers/web_form.py @@ -0,0 +1,4 @@ +from frappe.website.page_controllers.web_page import WebPage + +class WebFormPage(WebPage): + pass diff --git a/frappe/website/page_controllers/web_page.py b/frappe/website/page_controllers/web_page.py new file mode 100644 index 0000000000..d4af2860f8 --- /dev/null +++ b/frappe/website/page_controllers/web_page.py @@ -0,0 +1,21 @@ +import frappe +from frappe import _ + +class WebPage(object): + def __init__(self, path=None, http_status_code=None): + self.headers = None + self.http_status_code = http_status_code or 200 + if not path: + path = frappe.local.request.path + self.path = path.strip('/ ') + + def get(self): + if self.validate(): + return self.render() + + def validate(self): + pass + + def render(self): + pass + diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 11e950573e..10eddfc641 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,22 +1,16 @@ -import mimetypes -import os - -from werkzeug.wrappers import Response -from werkzeug.wsgi import wrap_file - import frappe from frappe import _ -from frappe.utils import cint, cstr -from frappe.model.document import get_controller -from frappe.website.doctype.website_settings.website_settings import \ - get_website_settings +from frappe.utils import cstr + +from frappe.website.page_controllers.document_page import DocumentPage +from frappe.website.page_controllers.list_page import ListPage +from frappe.website.page_controllers.not_permitted_page import NotPermittedPage +from frappe.website.page_controllers.print_page import PrintPage +from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_controllers.static_page import StaticPage + from frappe.website.redirect import resolve_redirect from frappe.website.render import build_response, resolve_path -from frappe.website.router import (get_doctypes_with_web_view, - get_page_info_from_web_page_with_dynamic_routes, get_start_folders) -from frappe.website.utils import (can_cache, delete_page_cache, get_home_page, - get_next_link, get_toc) - def get_response(path=None, http_status_code=200): """render html page""" @@ -56,475 +50,3 @@ def get_response(path=None, http_status_code=200): response = TemplatePage('error', getattr(e, 'http_status_code', None) or http_status_code).get() return response - -class WebPage(object): - def __init__(self, path=None, http_status_code=None): - self.headers = None - self.http_status_code = http_status_code or 200 - if not path: - path = frappe.local.request.path - self.path = path.strip('/ ') - - def get(self): - if self.validate(): - return self.render() - - def validate(self): - pass - - def render(self): - pass - -class StaticPage(WebPage): - def validate(self): - if ('.' not in self.path): - return False - extn = self.path.rsplit('.', 1)[-1] - if extn in ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json'): - return False - - if self.find_path_in_apps(): - return True - - return False - - def find_path_in_apps(self): - for app in frappe.get_installed_apps(): - file_path = frappe.get_app_path(app, 'www') + '/' + self.path - if os.path.exists(file_path): - self.file_path = file_path - return True - return False - - def render(self): - try: - f = open(self.file_path, 'rb') - except IOError: - raise NotFound - - response = Response(wrap_file(frappe.local.request.environ, f), direct_passthrough=True) - response.mimetype = mimetypes.guess_type(self.file_path)[0] or 'application/octet-stream' - return response - -class BaseTemplatePage(WebPage): - def init_context(self): - self.context = frappe._dict() - self.context.update(get_website_settings(self.context)) - self.context.update(frappe.local.conf.get("website_context") or {}) - - def add_csrf_token(self, html): - if frappe.local.session: - return html.replace("", ''.format( - frappe.local.session.data.csrf_token)) - else: - return html - - def post_process_context(self): - self.add_metatags() - # add_sidebar_and_breadcrumbs(context) - - self.set_base_template_if_missing() - self.set_title_with_prefix() - self.update_website_context() - - # set using frappe.respond_as_web_page - if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): - self.context.update(frappe.local.response.context) - - # to be able to inspect the context dict - # Use the macro "inspect" from macros.html - self.context._context_dict = self.context - - # context sends us a new template path - if self.context.template: - self.template_path = self.context.template - - - def set_base_template_if_missing(self): - if not self.context.base_template_path: - app_base = frappe.get_hooks("base_template") - self.context.base_template_path = app_base[-1] if app_base else "templates/base.html" - - def set_title_with_prefix(self): - if (self.context.title_prefix and self.context.title - and not self.context.title.startswith(self.context.title_prefix)): - self.context.title = '{0} - {1}'.format(self.context.title_prefix, self.context.title) - - def update_website_context(self): - # apply context from hooks - update_website_context = frappe.get_hooks('update_website_context') - for method in update_website_context: - values = frappe.get_attr(method)(self.context) - if values: - self.context.update(values) - - def add_metatags(self): - self.tags = frappe._dict(self.context.get("metatags") or {}) - self.init_metatags_from_context() - self.set_opengraph_tags() - self.set_twitter_tags() - self.set_meta_published_on() - self.set_metatags_from_website_route_meta() - - self.context.metatags = self.tags - - def init_metatags_from_context(self): - for key in ('title', 'description', 'image', 'author', 'url', 'published_on'): - if not key in self.tags and self.context.get(key): - self.tags[key] = self.context[key] - - if not self.tags.get('title'): self.tags['title'] = self.context.get('name') - - if self.tags.get('image'): - self.tags['image'] = frappe.utils.get_url(self.tags['image']) - - self.tags["language"] = frappe.local.lang or "en" - - def set_opengraph_tags(self): - if "og:type" not in self.tags: - self.tags["og:type"] = "article" - - for key in ('title', 'description', 'image', 'author', 'url'): - if self.tags.get(key): - self.tags['og:' + key] = self.tags.get(key) - - def set_twitter_tags(self): - for key in ('title', 'description', 'image', 'author', 'url'): - if self.tags.get(key): - self.tags['twitter:' + key] = self.tags.get(key) - - if self.tags.get('image'): - self.tags['twitter:card'] = "summary_large_image" - else: - self.tags["twitter:card"] = "summary" - - def set_meta_published_on(self): - if "published_on" in self.tags: - self.tags["datePublished"] = self.tags["published_on"] - del self.tags["published_on"] - - def set_metatags_from_website_route_meta(self): - ''' - Get meta tags from Website Route meta - they can override the defaults set above - ''' - route = self.context.path - if route == '': - # homepage - route = frappe.db.get_single_value('Website Settings', 'home_page') - - route_exists = (route - and not route.endswith(('.js', '.css')) - and frappe.db.exists('Website Route Meta', route)) - - if route_exists: - website_route_meta = frappe.get_doc('Website Route Meta', route) - for meta_tag in website_route_meta.meta_tags: - d = meta_tag.get_meta_dict() - self.tags.update(d) - -class TemplatePage(BaseTemplatePage): - def validate(self): - for app in frappe.get_installed_apps(frappe_last=True): - if self.find_page_in_app(app): - return True - - def find_page_in_app(self, app): - ''' - Searches for file matching the path in the /www - and /templates/pages folders - ''' - app_path = frappe.get_app_path(app) - folders = get_start_folders() - - for dirname in folders: - search_path = os.path.join(app_path, dirname, self.path) - for p in self.get_index_path_options(search_path): - file_path = frappe.as_unicode(p) - if os.path.exists(file_path) and not os.path.isdir(file_path): - self.app = app - self.app_path = app_path - self.template_path = os.path.relpath(file_path, self.app_path) - return True - - def get_index_path_options(self, search_path): - return ( - search_path, - search_path + '.html', - search_path + '.md', - search_path + '/index.html', - search_path + '/index.md') - - def render(self): - return build_response(self.path, self.get_html(), self.http_status_code, self.headers) - - def get_html(self): - # context object should be separate from self for security - # because it will be accessed via the user defined template - self.init_context() - - self.set_pymodule() - self.update_context() - self.post_process_context() - self.setup_template() - html = self.render_template() - - html = self.update_toc(html) - html = self.add_csrf_token(html) - - return html - - def set_pymodule(self): - ''' - A template may have a python module with a `get_context` method along with it in the - same folder. Also the hyphens will be coverted to underscore for python module names. - This method sets the pymodule_name if it exists. - ''' - self.basepath = self.template_path.rsplit('.', 1)[0] - self.pymodule_name = None - - # replace - with _ in the internal modules names - self.pymodule_path = os.path.join(self.basepath.replace("-", "_") + ".py") - - if os.path.exists(os.path.join(self.app_path, self.pymodule_path)): - self.pymodule_name = self.app + "." + self.pymodule_path.replace(os.path.sep, ".")[:-3] - - def setup_template(self): - '''Setup template source, frontmatter and markdown conversion''' - self.source = self.get_raw_template() - - if self.template_path.endswith(('.md', '.html')): - self.extract_frontmatter() - - self.convert_from_markdown() - - if self.extends_template(): - self.context.base_template_path = self.context.base_template_path or 'templates/base.html' - else: - self.source = None # clear the source - - # TODO: setup index.txt ? - - def update_context(self): - self.set_page_properties() - - if self.pymodule_name: - self.pymodule = frappe.get_module(self.pymodule_name) - self.set_pymodule_properties() - - data = self.run_pymodule_method('get_context') - - # some methods may return a "context" object - if data: self.context.update(data) - - # TODO: self.context.children = self.run_pymodule_method('get_children') - - self.context.developer_mode = frappe.conf.developer_mode - if self.context.http_status_code: - self.http_status_code = self.context.http_status_code - - def set_pymodule_properties(self): - for prop in ("base_template_path", "template", "no_cache", "sitemap", - "condition_field"): - if hasattr(self.pymodule, prop): - self.context[prop] = getattr(self.pymodule, prop) - - def set_page_properties(self): - self.context.template = self.template_path - - def run_pymodule_method(self, method): - if hasattr(self.pymodule, method): - try: - return getattr(self.pymodule, method)(self.context) - except (frappe.PermissionError, frappe.DoesNotExistError, frappe.Redirect): - raise - except: - if not frappe.flags.in_migrate: - frappe.errprint(frappe.utils.get_traceback()) - - def render_template(self): - if self.source: - html = frappe.render_template(self.source, self.context) - elif self.template_path: - if self.path.endswith('min.js'): - html = self.get_raw_template() # static - else: - html = frappe.get_template(self.template_path).render(self.context) - - return html - - def extends_template(self): - return (self.template_path.endswith(('.html', '.md', )) - and ('{%- extends' in self.source - or '{% extends' in self.source)) - - def get_raw_template(self): - return frappe.get_jloader().get_source(frappe.get_jenv(), self.template_path)[0] - - def load_colocated_files(self): - '''load co-located css/js files with the same name''' - js_path = self.basepath + '.js' - if os.path.exists(js_path) and '{% block script %}' not in self.source: - self.colocated_js = self.get_colocated_file(js_path) - - css_path = self.basepath + '.css' - if os.path.exists(css_path) and '{% block style %}' not in self.source: - self.colocated_css = self.get_colocated_file(css_path) - - def get_colocated_file(self, path): - with io.open(path, 'r', encoding = 'utf-8') as f: - return f.read() - - def extract_frontmatter(self): - try: - # values will be used to update page_info - res = get_frontmatter(self.source) - if res['attributes']: - self.context.update(res['attributes']) - self.source = res['body'] - except Exception: - pass - - def convert_from_markdown(self): - if self.template_path.endswith('.md'): - self.source = frappe.utils.md_to_html(self.source) - self.page_toc_html = self.toc_html - - if not self.show_sidebar: - self.source = '
' + self.source + '
' - - def update_toc(self, html): - if '{index}' in html: - html = html.replace('{index}', get_toc(self.path)) - - if '{next}' in html: - html = html.replace('{next}', get_next_link(self.path)) - - return html - - def set_standard_path(self, path): - self.app = 'frappe' - self.app_path = frappe.get_app_path('frappe') - self.path = path - self.template_path = 'www/{path}.html'.format(path=path) - - -class ListPage(TemplatePage): - def validate(self): - if frappe.db.get_value('DocType', self.path): - frappe.local.form_dict.doctype = self.path - self.set_standard_path('list') - return True - return False - -class PrintPage(TemplatePage): - ''' - default path returns a printable object (based on permission) - /Quotation/Q-0001 - ''' - def validate(self): - parts = self.path.split('/', 1) - if len(parts)==2: - if (frappe.db.get_value('DocType', parts[0]) - and frappe.db.get_value(parts[0], parts[1])): - frappe.form_dict.doctype = parts[0] - frappe.form_dict.name = parts[1] - self.set_standard_path('printview') - return True - - return False - -class NotPermittedPage(TemplatePage): - def validate(self): - frappe.local.message_title = _("Not Permitted") - frappe.local.response['context'] = dict( - indicator_color = 'red', - primary_action = '/login', - primary_label = _('Login'), - fullpage=True - ) - self.set_standard_path('message') - return True - -class DocumentPage(BaseTemplatePage): - def validate(self): - ''' - Find a document with matching `route` from all doctypes with `has_web_view`=1 - ''' - if self.search_in_doctypes_with_web_view(): - return True - - if self.search_web_page_dynamic_routes(): - return True - - return False - - def search_in_doctypes_with_web_view(self): - for doctype in get_doctypes_with_web_view(): - filters = dict(route=self.path) - meta = frappe.get_meta(doctype) - condition_field = self.get_condition_field(meta) - - if condition_field: - filters[condition_field] = 1 - - try: - self.docname = frappe.db.get_value(doctype, filters, 'name') - if self.docname: - self.doctype = doctype - self.meta = meta - return True - except Exception as e: - if not frappe.db.is_missing_column(e): raise e - - def search_web_page_dynamic_routes(self): - d = get_page_info_from_web_page_with_dynamic_routes(self.path) - if d: - self.doctype = 'Web Page' - self.docname = d.name - self.meta = frappe.get_meta(self.doctype) - return True - else: - return False - - def render(self): - self.doc = frappe.get_doc(self.doctype, self.docname) - self.init_context() - self.update_context() - self.post_process_context() - - html = frappe.get_template(self.context.template_path).render(self.context) - html = self.add_csrf_token(html) - - return build_response(self.path, html, self.http_status_code or 200, self.headers) - - def update_context(self): - self.context.doc = self.doc - self.context.update(self.context.doc.as_dict()) - self.context.update(self.context.doc.get_website_properties()) - - if not self.context.template_path: - self.context.template_path = self.context.doc.meta.get_web_template() - - if hasattr(self.doc, "get_context"): - ret = self.doc.get_context(self.context) - - if ret: - self.context.update(ret) - - for prop in ("no_cache", "sitemap"): - if not prop in self.context: - self.context[prop] = getattr(self.doc, prop, False) - - def get_condition_field(self, meta): - condition_field = None - if meta.is_published_field: - condition_field = meta.is_published_field - elif not meta.custom: - controller = get_controller(meta.doctype) - condition_field = controller.website.condition_field - - return condition_field - -class WebFormPage(WebPage): - pass From ce3771ab74ab739d18960c50e1dd3826f5ffb4b1 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 12 Mar 2021 13:26:38 +0530 Subject: [PATCH 010/868] refactor: Move code to appropriate file add_sidebar_and_breadcrumbs belongs to TemplatePage --- .../page_controllers/base_template_page.py | 12 +++--------- frappe/website/page_controllers/template_page.py | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py index 10e2375356..8a5ec992cc 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_controllers/base_template_page.py @@ -1,6 +1,7 @@ +import os + import frappe from frappe import _ -from frappe.website.context import add_sidebar_and_breadcrumbs from frappe.website.doctype.website_settings.website_settings import \ get_website_settings from frappe.website.page_controllers.web_page import WebPage @@ -15,15 +16,12 @@ class BaseTemplatePage(WebPage): def add_csrf_token(self, html): if frappe.local.session: return html.replace("", ''.format( - frappe.local.session.data.csrf_token)) + frappe.local.session.data.csrf_token)) else: return html def post_process_context(self): - self.set_missing_values() self.add_metatags() - self.add_sidebar_and_breadcrumbs() - self.set_base_template_if_missing() self.set_title_with_prefix() self.update_website_context() @@ -40,7 +38,6 @@ class BaseTemplatePage(WebPage): if self.context.template: self.template_path = self.context.template - def set_base_template_if_missing(self): if not self.context.base_template_path: app_base = frappe.get_hooks("base_template") @@ -69,9 +66,6 @@ class BaseTemplatePage(WebPage): self.context.metatags = self.tags - def add_sidebar_and_breadcrumbs(self): - add_sidebar_and_breadcrumbs(self.context) - def init_metatags_from_context(self): for key in ('title', 'description', 'image', 'author', 'url', 'published_on'): if not key in self.tags and self.context.get(key): diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 46e6e6a57e..cfb2d2f310 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -4,6 +4,7 @@ import os import frappe from frappe import _ from frappe.website.page_controllers.base_template_page import BaseTemplatePage +from frappe.website.context import add_sidebar_and_breadcrumbs from frappe.website.render import build_response from frappe.website.utils import (extract_comment_tag, extract_title, get_next_link, get_toc) @@ -60,6 +61,14 @@ class TemplatePage(BaseTemplatePage): return html + def post_process_context(self): + self.add_sidebar_and_breadcrumbs() + self.set_missing_values() + super(TemplatePage, self).post_process_context() + + def add_sidebar_and_breadcrumbs(self): + add_sidebar_and_breadcrumbs(self.context) + def set_pymodule(self): ''' A template may have a python module with a `get_context` method along with it in the @@ -85,7 +94,7 @@ class TemplatePage(BaseTemplatePage): self.convert_from_markdown() if self.extends_template(): - self.context.base_template_path = self.context.base_template_path or 'templates/base.html' + self.context.base_template_path = self.context.base_template_path # TODO: setup index.txt ? @@ -246,9 +255,11 @@ class TemplatePage(BaseTemplatePage): if self.context.url_prefix and self.context.url_prefix[-1]!='/': self.context.url_prefix += '/' + self.context.path = self.path + self.context.pathname = frappe.local.path + # for backward compatibility self.context.docs_base_url = '/docs' - self.context.path = self.path def get_start_folders(): From c6cc70e7dfa2dddcde55acae1ffc21c3ba169a45 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 15 Mar 2021 10:13:40 +0530 Subject: [PATCH 011/868] fix: Document Page --- frappe/website/page_controllers/document_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/website/page_controllers/document_page.py b/frappe/website/page_controllers/document_page.py index bb00d78c0c..f13ea0c724 100644 --- a/frappe/website/page_controllers/document_page.py +++ b/frappe/website/page_controllers/document_page.py @@ -82,7 +82,7 @@ class DocumentPage(BaseTemplatePage): if meta.is_published_field: condition_field = meta.is_published_field elif not meta.custom: - controller = get_controller(meta.doctype) + controller = get_controller(meta.name) condition_field = controller.website.condition_field return condition_field From a5f274b5a3dbb72e109184b7a3c56b2a1dac13b4 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 15 Mar 2021 10:15:27 +0530 Subject: [PATCH 012/868] fix: Enable WebForm page --- frappe/website/serve.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 10eddfc641..ea27b07859 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -8,6 +8,7 @@ from frappe.website.page_controllers.not_permitted_page import NotPermittedPage from frappe.website.page_controllers.print_page import PrintPage from frappe.website.page_controllers.template_page import TemplatePage from frappe.website.page_controllers.static_page import StaticPage +from frappe.website.page_controllers.web_form import WebFormPage from frappe.website.redirect import resolve_redirect from frappe.website.render import build_response, resolve_path @@ -23,7 +24,6 @@ def get_response(path=None, http_status_code=200): path = path.strip('/ ') resolve_redirect(path, query_string) path = resolve_path(path) - data = None # there is no way to determine the type of the page based on the route # so evaluate each type of page sequentially @@ -32,6 +32,8 @@ def get_response(path=None, http_status_code=200): response = TemplatePage(path, http_status_code).get() if not response: response = ListPage(path, http_status_code).get() + if not response: + response = WebFormPage(path, http_status_code).get() if not response: response = DocumentPage(path, http_status_code).get() if not response: From 25a4eb07575094766111c5cca9b46f79dd1ed59f Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 29 Mar 2021 19:25:41 +0200 Subject: [PATCH 013/868] feat: google drive picker --- .../google_settings/google_settings.json | 12 ++- .../google_settings/test_google_settings.py | 10 +++ frappe/public/icons/social/google_drive.svg | 1 + .../js/frappe/file_uploader/FileUploader.vue | 46 ++++++++++- frappe/public/js/integrations/google_drive.js | 81 +++++++++++++++++++ 5 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 frappe/integrations/doctype/google_settings/test_google_settings.py create mode 100644 frappe/public/icons/social/google_drive.svg create mode 100644 frappe/public/js/integrations/google_drive.js diff --git a/frappe/integrations/doctype/google_settings/google_settings.json b/frappe/integrations/doctype/google_settings/google_settings.json index 086c56c020..6a4f181f2d 100644 --- a/frappe/integrations/doctype/google_settings/google_settings.json +++ b/frappe/integrations/doctype/google_settings/google_settings.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2019-06-14 00:08:37.255003", "doctype": "DocType", "engine": "InnoDB", @@ -8,7 +9,8 @@ "client_id", "client_secret", "sb_01", - "api_key" + "api_key", + "app_id" ], "fields": [ { @@ -46,10 +48,16 @@ "fieldname": "sb_01", "fieldtype": "Section Break", "label": "API Key" + }, + { + "fieldname": "app_id", + "fieldtype": "Data", + "label": "App ID" } ], "issingle": 1, - "modified": "2019-08-06 22:37:41.699703", + "links": [], + "modified": "2021-03-28 22:24:05.963403", "modified_by": "Administrator", "module": "Integrations", "name": "Google Settings", diff --git a/frappe/integrations/doctype/google_settings/test_google_settings.py b/frappe/integrations/doctype/google_settings/test_google_settings.py new file mode 100644 index 0000000000..476e772b58 --- /dev/null +++ b/frappe/integrations/doctype/google_settings/test_google_settings.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestGoogleSettings(unittest.TestCase): + pass diff --git a/frappe/public/icons/social/google_drive.svg b/frappe/public/icons/social/google_drive.svg new file mode 100644 index 0000000000..d43b4d3dbd --- /dev/null +++ b/frappe/public/icons/social/google_drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frappe/public/js/frappe/file_uploader/FileUploader.vue b/frappe/public/js/frappe/file_uploader/FileUploader.vue index d0b09c7593..61b87606a5 100644 --- a/frappe/public/js/frappe/file_uploader/FileUploader.vue +++ b/frappe/public/js/frappe/file_uploader/FileUploader.vue @@ -63,6 +63,12 @@
{{ __('Camera') }}
+
{{ upload_notes }} @@ -116,6 +122,7 @@ import FilePreview from './FilePreview.vue'; import FileBrowser from './FileBrowser.vue'; import WebLink from './WebLink.vue'; +import GoogleDrive from '../../integrations/google_drive'; export default { name: 'FileUploader', @@ -173,8 +180,16 @@ export default { currently_uploading: -1, show_file_browser: false, show_web_link: false, + allow_take_photo: false, + allow_google_drive: false } }, + created() { + this.allow_take_photo = window.navigator.mediaDevices; + frappe.db.get_single_value("Google Settings", "enable").then(resp => { + this.allow_google_drive = Boolean(resp); + }); + }, watch: { files(newvalue, oldvalue) { if (!this.allow_multiple && newvalue.length > 1) { @@ -187,9 +202,6 @@ export default { return this.files.length > 0 && this.files.every( file => file.total !== 0 && file.progress === file.total); - }, - allow_take_photo() { - return window.navigator.mediaDevices; } }, methods: { @@ -408,6 +420,10 @@ export default { form_data.append('file_url', file.file_url); } + if (file.file_name) { + form_data.append('file_name', file.file_name); + } + if (this.doctype && this.docname) { form_data.append('doctype', this.doctype); form_data.append('docname', this.docname); @@ -437,6 +453,30 @@ export default { ); }); }, + show_google_drive_picker() { + frappe.db.get_value("Google Settings", "Google Settings", ["client_id", "api_key", "app_id"]).then(resp => { + let dialog = cur_dialog; + dialog.hide(); + let google_drive = new GoogleDrive({ + pickerCallback: data => this.google_drive_callback(data, dialog), + developerKey: resp.message.api_key, + clientId: resp.message.client_id, + appId: resp.message.app_id + }); + google_drive.loadPicker(); + }); + }, + google_drive_callback(data, dialog) { + if (data.action == google.picker.Action.PICKED) { + // debugger; + this.upload_file({ + file_url: data.docs[0].url, + file_name: data.docs[0].name + }); + } else if (data.action == google.picker.Action.CANCEL) { + dialog.show(); + } + }, url_to_file(url, filename, mime_type) { return fetch(url) .then(res => res.arrayBuffer()) diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive.js new file mode 100644 index 0000000000..9c6aea5375 --- /dev/null +++ b/frappe/public/js/integrations/google_drive.js @@ -0,0 +1,81 @@ +export default class GoogleDrive { + constructor({ + pickerCallback, + developerKey, + clientId, + appId + } = {}) { + console.log('GoogleDrive constructor'); + this.pickerCallback = pickerCallback; + this.pickerApiLoaded = false; + this.scope = ['https://www.googleapis.com/auth/drive.file']; + this.developerKey = developerKey; + this.clientId = clientId; + this.appId = appId; + } + + loadPicker() { + // load the google API library + $.ajax({ + method: "GET", + url: "https://apis.google.com/js/api.js", + dataType: "script", + cache: true, + context: this + }).done(function() { + this.loadGapi(); + }.bind(this)); + } + + loadGapi() { + // load auth and picker libraries + if (!frappe.boot.user.google_drive_token) { + gapi.load('auth', function() { + console.log('gapi.load("auth") callback'); + this.onAuthApiLoad(); + }.bind(this)); + } + + gapi.load('picker', function() { + console.log('gapi.load("picker") callback'); + this.onPickerApiLoad(); + }.bind(this)); + } + + onAuthApiLoad() { + gapi.auth.authorize({ + 'client_id': this.clientId, + 'scope': this.scope, + 'immediate': false + }, function(authResult) { + this.handleAuthResult(authResult); + }.bind(this)); + } + + handleAuthResult(authResult) { + if (authResult && !authResult.error) { + frappe.boot.user.google_drive_token = authResult.access_token; + this.createPicker(); + } + } + + onPickerApiLoad() { + this.pickerApiLoaded = true; + this.createPicker(); + } + + createPicker() { + // Create and render a Picker object for searching images. + if (this.pickerApiLoaded && frappe.boot.user.google_drive_token) { + var view = new google.picker.View(google.picker.ViewId.DOCS); + var picker = new google.picker.PickerBuilder() + .setAppId(this.appId) + .setOAuthToken(frappe.boot.user.google_drive_token) + .addView(view) + .setDeveloperKey(this.developerKey) + .setCallback(this.pickerCallback) + .build(); + picker.setVisible(true); + } + } +} From 7d333dbf703001c50dc80aa0a28477b741e9b51f Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 29 Mar 2021 21:09:06 +0200 Subject: [PATCH 014/868] fix: scope for google picker --- frappe/public/js/integrations/google_drive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive.js index 9c6aea5375..1c7e4dda21 100644 --- a/frappe/public/js/integrations/google_drive.js +++ b/frappe/public/js/integrations/google_drive.js @@ -8,7 +8,7 @@ export default class GoogleDrive { console.log('GoogleDrive constructor'); this.pickerCallback = pickerCallback; this.pickerApiLoaded = false; - this.scope = ['https://www.googleapis.com/auth/drive.file']; + this.scope = ['https://www.googleapis.com/auth/drive.readonly']; this.developerKey = developerKey; this.clientId = clientId; this.appId = appId; From c44cecae5db1ef7231b742ca84ade406224e17d6 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 29 Mar 2021 21:11:26 +0200 Subject: [PATCH 015/868] fix: remove log statements --- frappe/public/js/integrations/google_drive.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive.js index 1c7e4dda21..e7093fb29a 100644 --- a/frappe/public/js/integrations/google_drive.js +++ b/frappe/public/js/integrations/google_drive.js @@ -5,7 +5,6 @@ export default class GoogleDrive { clientId, appId } = {}) { - console.log('GoogleDrive constructor'); this.pickerCallback = pickerCallback; this.pickerApiLoaded = false; this.scope = ['https://www.googleapis.com/auth/drive.readonly']; @@ -31,13 +30,11 @@ export default class GoogleDrive { // load auth and picker libraries if (!frappe.boot.user.google_drive_token) { gapi.load('auth', function() { - console.log('gapi.load("auth") callback'); this.onAuthApiLoad(); }.bind(this)); } gapi.load('picker', function() { - console.log('gapi.load("picker") callback'); this.onPickerApiLoad(); }.bind(this)); } From f9dbbf69e0e89e3f36ac821994cfccb6a576f32d Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 29 Mar 2021 21:22:13 +0200 Subject: [PATCH 016/868] feat: better home view for google drive picker --- frappe/public/js/integrations/google_drive.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive.js index e7093fb29a..6b9ee9d0ff 100644 --- a/frappe/public/js/integrations/google_drive.js +++ b/frappe/public/js/integrations/google_drive.js @@ -64,7 +64,10 @@ export default class GoogleDrive { createPicker() { // Create and render a Picker object for searching images. if (this.pickerApiLoaded && frappe.boot.user.google_drive_token) { - var view = new google.picker.View(google.picker.ViewId.DOCS); + var view = new google.picker.DocsView(google.picker.ViewId.DOCS) + .setParent('root') // show the root folder by default + .setIncludeFolders(true); // also show folders, not just files + var picker = new google.picker.PickerBuilder() .setAppId(this.appId) .setOAuthToken(frappe.boot.user.google_drive_token) From 11f4edf051bf9842e58228faae2d2a349d2e763d Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 29 Mar 2021 21:22:37 +0200 Subject: [PATCH 017/868] feat: localize google drive picker --- frappe/public/js/integrations/google_drive.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive.js index 6b9ee9d0ff..076178046e 100644 --- a/frappe/public/js/integrations/google_drive.js +++ b/frappe/public/js/integrations/google_drive.js @@ -70,11 +70,13 @@ export default class GoogleDrive { var picker = new google.picker.PickerBuilder() .setAppId(this.appId) + .setDeveloperKey(this.developerKey) .setOAuthToken(frappe.boot.user.google_drive_token) .addView(view) - .setDeveloperKey(this.developerKey) + .setLocale(frappe.boot.lang) .setCallback(this.pickerCallback) .build(); + picker.setVisible(true); } } From 741011085b6ba3cccc86ba3514d9deff4eb82b54 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 30 Mar 2021 00:49:02 +0200 Subject: [PATCH 018/868] refactor: bind this --- frappe/public/js/integrations/google_drive.js | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive.js index 076178046e..06d9cbbe54 100644 --- a/frappe/public/js/integrations/google_drive.js +++ b/frappe/public/js/integrations/google_drive.js @@ -5,9 +5,9 @@ export default class GoogleDrive { clientId, appId } = {}) { - this.pickerCallback = pickerCallback; - this.pickerApiLoaded = false; this.scope = ['https://www.googleapis.com/auth/drive.readonly']; + this.pickerApiLoaded = false; + this.pickerCallback = pickerCallback; this.developerKey = developerKey; this.clientId = clientId; this.appId = appId; @@ -19,24 +19,17 @@ export default class GoogleDrive { method: "GET", url: "https://apis.google.com/js/api.js", dataType: "script", - cache: true, - context: this - }).done(function() { - this.loadGapi(); - }.bind(this)); + cache: true + }).done(this.loadGapi.bind(this)); } loadGapi() { // load auth and picker libraries if (!frappe.boot.user.google_drive_token) { - gapi.load('auth', function() { - this.onAuthApiLoad(); - }.bind(this)); + gapi.load('auth', this.onAuthApiLoad.bind(this)); } - gapi.load('picker', function() { - this.onPickerApiLoad(); - }.bind(this)); + gapi.load('picker', this.onPickerApiLoad.bind(this)); } onAuthApiLoad() { @@ -44,9 +37,7 @@ export default class GoogleDrive { 'client_id': this.clientId, 'scope': this.scope, 'immediate': false - }, function(authResult) { - this.handleAuthResult(authResult); - }.bind(this)); + }, this.handleAuthResult.bind(this)); } handleAuthResult(authResult) { From a018e7b4458c028ebed29d8e889ae72f086d0479 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 30 Mar 2021 01:28:12 +0200 Subject: [PATCH 019/868] refactor: rename GoogleDrive -> GoogleDrivePicker --- frappe/public/js/frappe/file_uploader/FileUploader.vue | 4 ++-- .../integrations/{google_drive.js => google_drive_picker.js} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename frappe/public/js/integrations/{google_drive.js => google_drive_picker.js} (98%) diff --git a/frappe/public/js/frappe/file_uploader/FileUploader.vue b/frappe/public/js/frappe/file_uploader/FileUploader.vue index 61b87606a5..154d4e0ea1 100644 --- a/frappe/public/js/frappe/file_uploader/FileUploader.vue +++ b/frappe/public/js/frappe/file_uploader/FileUploader.vue @@ -122,7 +122,7 @@ import FilePreview from './FilePreview.vue'; import FileBrowser from './FileBrowser.vue'; import WebLink from './WebLink.vue'; -import GoogleDrive from '../../integrations/google_drive'; +import GoogleDrivePicker from '../../integrations/google_drive_picker'; export default { name: 'FileUploader', @@ -457,7 +457,7 @@ export default { frappe.db.get_value("Google Settings", "Google Settings", ["client_id", "api_key", "app_id"]).then(resp => { let dialog = cur_dialog; dialog.hide(); - let google_drive = new GoogleDrive({ + let google_drive = new GoogleDrivePicker({ pickerCallback: data => this.google_drive_callback(data, dialog), developerKey: resp.message.api_key, clientId: resp.message.client_id, diff --git a/frappe/public/js/integrations/google_drive.js b/frappe/public/js/integrations/google_drive_picker.js similarity index 98% rename from frappe/public/js/integrations/google_drive.js rename to frappe/public/js/integrations/google_drive_picker.js index 06d9cbbe54..7ce9810f72 100644 --- a/frappe/public/js/integrations/google_drive.js +++ b/frappe/public/js/integrations/google_drive_picker.js @@ -1,4 +1,4 @@ -export default class GoogleDrive { +export default class GoogleDrivePicker { constructor({ pickerCallback, developerKey, From 144608241e9825af20c88b122a70f29d22aa5a41 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 30 Mar 2021 02:20:11 +0200 Subject: [PATCH 020/868] refactor: save one API call --- .../google_settings/google_settings.py | 22 +++++++++++++-- .../js/frappe/file_uploader/FileUploader.vue | 28 +++++++++---------- .../js/integrations/google_drive_picker.js | 8 ++++-- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/frappe/integrations/doctype/google_settings/google_settings.py b/frappe/integrations/doctype/google_settings/google_settings.py index ecc975235a..bd0e845977 100644 --- a/frappe/integrations/doctype/google_settings/google_settings.py +++ b/frappe/integrations/doctype/google_settings/google_settings.py @@ -3,11 +3,29 @@ # For license information, please see license.txt from __future__ import unicode_literals -# import frappe +import frappe from frappe.model.document import Document class GoogleSettings(Document): pass def get_auth_url(): - return "https://www.googleapis.com/oauth2/v4/token" \ No newline at end of file + return "https://www.googleapis.com/oauth2/v4/token" + + +@frappe.whitelist(allow_guest=True) +def get_file_picker_settings(): + """Return all the data FileUploader needs to start the Google Drive Picker.""" + if frappe.session.user == 'Guest': + return {'enabled': False} + + google_settings = frappe.get_single("Google Settings") + if not google_settings.enable: + return {'enabled': False} + + return { + 'enabled': True, + 'appId': google_settings.app_id, + 'developerKey': google_settings.api_key, + 'clientId': google_settings.client_id + } diff --git a/frappe/public/js/frappe/file_uploader/FileUploader.vue b/frappe/public/js/frappe/file_uploader/FileUploader.vue index 154d4e0ea1..64365cfc11 100644 --- a/frappe/public/js/frappe/file_uploader/FileUploader.vue +++ b/frappe/public/js/frappe/file_uploader/FileUploader.vue @@ -63,7 +63,7 @@
{{ __('Camera') }}
- \ - ')); - // add event handler for submit button - verify_token(); + $('.login-content').empty(); + $('.login-content:visible').append($('
').attr({ 'id': 'twofactor_div' }).html('{{ _("Verification") }}{{ _("Verify") }}')); + // add event handler for submit button + verify_token(); } var continue_otp_app = function (setup, qrcode) { From b018236d183dfb524afc6d6849562ef906210d4b Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 10 May 2021 11:16:47 +0530 Subject: [PATCH 044/868] fix: Grid row deletion fix --- frappe/public/js/frappe/form/grid.js | 7 ++++++- frappe/public/js/frappe/form/grid_row.js | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index 4d381c9be7..9b05809aba 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -196,7 +196,9 @@ export default class Grid { tasks.push(() => { if (dirty) { this.refresh(); - this.frm.script_manager.trigger(this.df.fieldname + "_delete", this.doctype); + if (this.frm) { + this.frm.script_manager.trigger(this.df.fieldname + "_delete", this.doctype); + } } }); @@ -345,6 +347,9 @@ export default class Grid { if (d.idx === undefined) { d.idx = ri + 1; } + if (d.name === undefined) { + d.name = "row" + d.idx + } if (this.grid_rows[ri] && !append_row) { var grid_row = this.grid_rows[ri]; grid_row.doc = d; diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index f6da88df57..bbcf0f707b 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -93,8 +93,11 @@ export default class GridRow { } else { data = this.grid.df.data; } - - const index = data.findIndex(d => d.name === me.doc.name); + let index = -1; + + if (me.doc.name) { + index = data.findIndex(d => d.name === me.doc.name); + } if (index > -1) { // mutate array directly, From 6a9b93bfa5d6b5569681c358cc0a2c66351603fa Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 10 May 2021 11:37:48 +0530 Subject: [PATCH 045/868] fix: sider fix --- frappe/public/js/frappe/form/grid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index 9b05809aba..00f9d6abca 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -348,7 +348,7 @@ export default class Grid { d.idx = ri + 1; } if (d.name === undefined) { - d.name = "row" + d.idx + d.name = "row" + d.idx; } if (this.grid_rows[ri] && !append_row) { var grid_row = this.grid_rows[ri]; From 2b51641799c60ae9b16a1d29e4306d6c35e66070 Mon Sep 17 00:00:00 2001 From: conncampbell Date: Mon, 10 May 2021 16:14:51 -0600 Subject: [PATCH 046/868] fix: changed translate entries to javascript rather than python to resolve semgrep linter translate checks --- frappe/templates/includes/login/login.js | 56 ++++++++++++++---------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/frappe/templates/includes/login/login.js b/frappe/templates/includes/login/login.js index 93bf95bdb7..4bc17cb14b 100644 --- a/frappe/templates/includes/login/login.js +++ b/frappe/templates/includes/login/login.js @@ -21,7 +21,7 @@ login.bind_events = function () { args.pwd = $("#login_password").val(); args.device = "desktop"; if (!args.usr || !args.pwd) { - frappe.msgprint('{{ _("Both login and password required") }}'); + frappe.msgprint(__("Both login and password required")); return false; } login.call(args); @@ -36,7 +36,7 @@ login.bind_events = function () { args.redirect_to = frappe.utils.sanitise_redirect(frappe.utils.get_url_arg("redirect-to")); args.full_name = frappe.utils.xss_sanitise(($("#signup_fullname").val() || "").trim()); if (!args.email || !validate_email(args.email) || !args.full_name) { - login.set_status('{{ _("Valid email and name required") }}', 'red'); + login.set_status(__("Valid email and name required"), 'red'); return false; } login.call(args); @@ -49,7 +49,7 @@ login.bind_events = function () { args.cmd = "frappe.core.doctype.user.user.reset_password"; args.user = ($("#forgot_email").val() || "").trim(); if (!args.user) { - login.set_status('{{ _("Valid Login id required.") }}', 'red'); + login.set_status(__("Valid Login id required."), 'red'); return false; } login.call(args); @@ -60,10 +60,10 @@ login.bind_events = function () { var input = $($(this).attr("toggle")); if (input.attr("type") == "password") { input.attr("type", "text"); - $(this).text('{{ _("Hide") }}') + $(this).text(__("Hide")) } else { input.attr("type", "password"); - $(this).text('{{ _("Show") }}') + $(this).text(__("Show")) } }); @@ -75,7 +75,7 @@ login.bind_events = function () { args.pwd = $("#login_password").val(); args.device = "desktop"; if (!args.usr || !args.pwd) { - login.set_status('{{ _("Both login and password required") }}', 'red'); + login.set_status(__("Both login and password required"), 'red'); return false; } login.call(args); @@ -136,7 +136,7 @@ login.signup = function () { // Login login.call = function (args, callback) { - login.set_status('{{ _("Verifying...") }}', 'blue'); + login.set_status(__("Verifying..."), 'blue'); return frappe.call({ type: "POST", @@ -194,7 +194,7 @@ login.login_handlers = (function () { var login_handlers = { 200: function (data) { if (data.message == 'Logged In') { - login.set_status('{{ _("Success") }}', 'green'); + login.set_status(__("Success"), 'green'); window.location.href = frappe.utils.sanitise_redirect(frappe.utils.get_url_arg("redirect-to")) || data.home_page; } else if (data.message == 'Password Reset') { window.location.href = frappe.utils.sanitise_redirect(data.redirect_to); @@ -218,13 +218,13 @@ login.login_handlers = (function () { } } else if (window.location.hash === '#forgot') { if (data.message === 'not found') { - login.set_status('{{ _("Not a valid user") }}', 'red'); + login.set_status(__("Not a valid user"), 'red'); } else if (data.message == 'not allowed') { - login.set_status('{{ _("Not Allowed") }}', 'red'); + login.set_status(__("Not Allowed"), 'red'); } else if (data.message == 'disabled') { - login.set_status('{{ _("Not Allowed: Disabled User") }}', 'red'); + login.set_status(__("Not Allowed: Disabled User"), 'red'); } else { - login.set_status('{{ _("Instructions Emailed") }}', 'green'); + login.set_status(__("Instructions Emailed"), 'green'); } @@ -232,7 +232,7 @@ login.login_handlers = (function () { if (cint(data.message[0]) == 0) { login.set_status(data.message[1], 'red'); } else { - login.set_status('{{ _("Success") }}', 'green'); + login.set_status(__("Success"), 'green'); frappe.msgprint(data.message[1]) } //login.set_status(__(data.message), 'green'); @@ -240,7 +240,7 @@ login.login_handlers = (function () { //OTP verification if (data.verification && data.message != 'Logged In') { - login.set_status('{{ _("Success") }}', 'green'); + login.set_status(__("Success"), 'green'); document.cookie = "tmp_id=" + data.tmp_id; @@ -253,8 +253,8 @@ login.login_handlers = (function () { } } }, - 401: get_error_handler('{{ _("Invalid Login. Try again.") }}'), - 417: get_error_handler('{{ _("Oops! Something went wrong") }}') + 401: get_error_handler(__("Invalid Login. Try again.")), + 417: get_error_handler(__("Oops! Something went wrong")) }; return login_handlers; @@ -282,7 +282,7 @@ var verify_token = function (event) { args.otp = $("#login_token").val(); args.tmp_id = frappe.get_cookie('tmp_id'); if (!args.otp) { - frappe.msgprint('{{ _("Login token required") }}'); + frappe.msgprint(__("Login token required")); return false; } login.call(args); @@ -292,9 +292,17 @@ var verify_token = function (event) { var request_otp = function (r) { $('.login-content').empty(); - $('.login-content:visible').append($('
').attr({ 'id': 'twofactor_div' }).html('{{ _("Verification") }}{{ _("Verify") }}')); - // add event handler for submit button - verify_token(); + $('.login-content:visible').append($('
').attr({ 'id': 'twofactor_div' }).html( + '
\ +
\ + {{ _("Verification") }}\ +
\ +
\ + \ + \ +
')); + // add event handler for submit button + verify_token(); } var continue_otp_app = function (setup, qrcode) { @@ -302,11 +310,11 @@ var continue_otp_app = function (setup, qrcode) { var qrcode_div = $('
'); if (setup) { - direction = $('
').attr('id', 'qr_info').text('{{ _("Enter Code displayed in OTP App.") }}'); + direction = $('
').attr('id', 'qr_info').text(__("Enter Code displayed in OTP App.")); qrcode_div.append(direction); $('#otp_div').prepend(qrcode_div); } else { - direction = $('
').attr('id', 'qr_info').text('{{ _("OTP setup using OTP App was not completed. Please contact Administrator.") }}'); + direction = $('
').attr('id', 'qr_info').text(__("OTP setup using OTP App was not completed. Please contact Administrator.")); qrcode_div.append(direction); $('#otp_div').prepend(qrcode_div); } @@ -320,7 +328,7 @@ var continue_sms = function (setup, prompt) { sms_div.append(prompt) $('#otp_div').prepend(sms_div); } else { - direction = $('
').attr('id', 'qr_info').text(prompt || '{{ _("SMS was not sent. Please contact Administrator.") }}'); + direction = $('
').attr('id', 'qr_info').text(prompt || __("SMS was not sent. Please contact Administrator.")); sms_div.append(direction); $('#otp_div').prepend(sms_div) } @@ -334,7 +342,7 @@ var continue_email = function (setup, prompt) { email_div.append(prompt) $('#otp_div').prepend(email_div); } else { - var direction = $('
').attr('id', 'qr_info').text(prompt || '{{ _("Verification code email not sent. Please contact Administrator.") }}'); + var direction = $('
').attr('id', 'qr_info').text(prompt || __("Verification code email not sent. Please contact Administrator.")); email_div.append(direction); $('#otp_div').prepend(email_div); } From e101105bce30b7eae0a4f3371566ba4e85e0606a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 11 May 2021 10:41:18 +0530 Subject: [PATCH 047/868] refactor: Import get_response instead of using serve.get_response --- frappe/tests/test_website.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 97e00b9268..5221cbe6b7 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -3,8 +3,7 @@ from __future__ import unicode_literals import unittest import frappe -from frappe.website import render -from frappe.website import serve +from frappe.website.serve import get_response from frappe.website.utils import get_home_page from frappe.utils import set_request @@ -51,7 +50,7 @@ class TestWebsite(unittest.TestCase): def test_page_load(self): set_request(method='POST', path='login') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 200) @@ -62,17 +61,17 @@ class TestWebsite(unittest.TestCase): def test_static_page(self): set_request(method='GET', path='/_test/static-file-test.png') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 200) def test_error_page(self): set_request(method='GET', path='/error') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 500) def test_login(self): set_request(method='GET', path='/login') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 200) html = frappe.safe_decode(response.get_data()) @@ -83,7 +82,7 @@ class TestWebsite(unittest.TestCase): def test_app(self): frappe.set_user('Administrator') set_request(method='GET', path='/app') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 200) html = frappe.safe_decode(response.get_data()) @@ -92,7 +91,7 @@ class TestWebsite(unittest.TestCase): def test_not_found(self): set_request(method='GET', path='/_test/missing') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 404) @@ -118,31 +117,31 @@ class TestWebsite(unittest.TestCase): frappe.cache().delete_key('website_redirects') set_request(method='GET', path='/testfrom') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 301) self.assertEqual(response.headers.get('Location'), r'://testto1') set_request(method='GET', path='/testfromregex/test') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 301) self.assertEqual(response.headers.get('Location'), r'://testto2') set_request(method='GET', path='/testsub/me') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 301) self.assertEqual(response.headers.get('Location'), r'://testto3/me') set_request(method='GET', path='/test404') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 404) set_request(method='GET', path='/testsource') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 301) self.assertEqual(response.headers.get('Location'), '/testtarget') set_request(method='GET', path='/courses/course?course=data') - response = serve.get_response() + response = get_response() self.assertEqual(response.status_code, 301) self.assertEqual(response.headers.get('Location'), '/courses/data') From 5c92e8a12962a4c8acd9037c81ae81433357b56f Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 11 May 2021 16:43:22 +0530 Subject: [PATCH 048/868] feat: Add class for standard pages (Error & NotFound) --- frappe/website/page_controllers/error_page.py | 9 +++++++++ frappe/website/page_controllers/not_found_page.py | 9 +++++++++ frappe/website/page_controllers/not_permitted_page.py | 4 ++++ 3 files changed, 22 insertions(+) create mode 100644 frappe/website/page_controllers/error_page.py create mode 100644 frappe/website/page_controllers/not_found_page.py diff --git a/frappe/website/page_controllers/error_page.py b/frappe/website/page_controllers/error_page.py new file mode 100644 index 0000000000..caa72b015d --- /dev/null +++ b/frappe/website/page_controllers/error_page.py @@ -0,0 +1,9 @@ +from frappe import _ +from frappe.website.page_controllers.not_found_page import NotFoundPage +from frappe.website.page_controllers.template_page import TemplatePage + +class ErrorPage(TemplatePage): + def __init__(self, path, http_status_code, exception): + path = 'error' + super().__init__(path=path, http_status_code=http_status_code) + self.http_status_code = getattr(exception, 'http_status_code', None) or http_status_code or 500 diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_controllers/not_found_page.py new file mode 100644 index 0000000000..d1a1797efc --- /dev/null +++ b/frappe/website/page_controllers/not_found_page.py @@ -0,0 +1,9 @@ +from frappe import _ +from frappe.website.page_controllers.template_page import TemplatePage + +class NotFoundPage(TemplatePage): + def __init__(self, path, http_status_code): + super().__init__(path=path, http_status_code=http_status_code) + self.path = '404' + self.http_status_code = 404 + self.template_path = '404' diff --git a/frappe/website/page_controllers/not_permitted_page.py b/frappe/website/page_controllers/not_permitted_page.py index e0cd6bf970..61c6b88e09 100644 --- a/frappe/website/page_controllers/not_permitted_page.py +++ b/frappe/website/page_controllers/not_permitted_page.py @@ -3,6 +3,10 @@ from frappe import _ from frappe.website.page_controllers.template_page import TemplatePage class NotPermittedPage(TemplatePage): + def __init__(self, path, http_status_code): + super().__init__(path=path, http_status_code=http_status_code) + self.http_status_code = 403 + def validate(self): frappe.local.message_title = _("Not Permitted") frappe.local.response['context'] = dict( From 9429d06a17f6cc51716ff40e51b36150d860568f Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 11 May 2021 16:44:50 +0530 Subject: [PATCH 049/868] refactor: Remove reduntant code - Use Error & NotFound page as required --- frappe/tests/test_website.py | 2 +- frappe/website/serve.py | 22 ++++++++-------------- frappe/www/_test/problematic_page.html | 1 + 3 files changed, 10 insertions(+), 15 deletions(-) create mode 100644 frappe/www/_test/problematic_page.html diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 5221cbe6b7..cc500d1c02 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -65,7 +65,7 @@ class TestWebsite(unittest.TestCase): self.assertEqual(response.status_code, 200) def test_error_page(self): - set_request(method='GET', path='/error') + set_request(method='GET', path='/_test/problematic_page') response = get_response() self.assertEqual(response.status_code, 500) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 1a5852d036..b6586dc1f3 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -2,7 +2,9 @@ import frappe from frappe.utils import cstr from frappe.website.page_controllers.document_page import DocumentPage +from frappe.website.page_controllers.error_page import ErrorPage from frappe.website.page_controllers.list_page import ListPage +from frappe.website.page_controllers.not_found_page import NotFoundPage from frappe.website.page_controllers.not_permitted_page import NotPermittedPage from frappe.website.page_controllers.print_page import PrintPage from frappe.website.page_controllers.template_page import TemplatePage @@ -26,19 +28,11 @@ def get_response(path=None, http_status_code=200): # there is no way to determine the type of the page based on the route # so evaluate each type of page sequentially - response = StaticPage(path, http_status_code).get() - if not response: - response = TemplatePage(path, http_status_code).get() - if not response: - response = ListPage(path, http_status_code).get() - if not response: - response = WebFormPage(path, http_status_code).get() - if not response: - response = DocumentPage(path, http_status_code).get() - if not response: - response = PrintPage(path, http_status_code).get() - if not response: - response = TemplatePage('404', 404).get() + renderers = [StaticPage, TemplatePage, ListPage, WebFormPage, DocumentPage, PrintPage, NotFoundPage] + for resolver in renderers: + response = resolver(path, http_status_code).get() + if response: + break except frappe.Redirect: return build_response(path, "", 301, { "Location": frappe.flags.redirect_location or (frappe.local.response or {}).get('location'), @@ -48,6 +42,6 @@ def get_response(path=None, http_status_code=200): frappe.local.message = cstr(e) response = NotPermittedPage(path, http_status_code).get() except Exception as e: - response = TemplatePage('error', getattr(e, 'http_status_code', None) or http_status_code).get() + response = ErrorPage(path, http_status_code, exception=e).get() return response diff --git a/frappe/www/_test/problematic_page.html b/frappe/www/_test/problematic_page.html new file mode 100644 index 0000000000..5e194421d2 --- /dev/null +++ b/frappe/www/_test/problematic_page.html @@ -0,0 +1 @@ +{% raise %} From 006f0a2bafb9945c8fdf6fcb41c015e45b5967a4 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 11 May 2021 17:03:00 +0530 Subject: [PATCH 050/868] fix: Rename resolver to renderer --- frappe/website/page_controllers/error_page.py | 2 -- frappe/website/page_controllers/not_found_page.py | 1 - frappe/website/serve.py | 7 ++++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/frappe/website/page_controllers/error_page.py b/frappe/website/page_controllers/error_page.py index caa72b015d..1f54a5f38c 100644 --- a/frappe/website/page_controllers/error_page.py +++ b/frappe/website/page_controllers/error_page.py @@ -1,5 +1,3 @@ -from frappe import _ -from frappe.website.page_controllers.not_found_page import NotFoundPage from frappe.website.page_controllers.template_page import TemplatePage class ErrorPage(TemplatePage): diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_controllers/not_found_page.py index d1a1797efc..1d15877e9d 100644 --- a/frappe/website/page_controllers/not_found_page.py +++ b/frappe/website/page_controllers/not_found_page.py @@ -1,4 +1,3 @@ -from frappe import _ from frappe.website.page_controllers.template_page import TemplatePage class NotFoundPage(TemplatePage): diff --git a/frappe/website/serve.py b/frappe/website/serve.py index b6586dc1f3..eacaef96e1 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -17,6 +17,8 @@ from frappe.website.render import build_response, resolve_path def get_response(path=None, http_status_code=200): """render html page""" query_string = None + response = None + if not path: path = frappe.local.request.path query_string = frappe.local.request.query_string @@ -25,12 +27,11 @@ def get_response(path=None, http_status_code=200): path = path.strip('/ ') resolve_redirect(path, query_string) path = resolve_path(path) - # there is no way to determine the type of the page based on the route # so evaluate each type of page sequentially renderers = [StaticPage, TemplatePage, ListPage, WebFormPage, DocumentPage, PrintPage, NotFoundPage] - for resolver in renderers: - response = resolver(path, http_status_code).get() + for renderer in renderers: + response = renderer(path, http_status_code).get() if response: break except frappe.Redirect: From 4b7a1488b5b465ce2a4ba9c67c9b01b461ba6342 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 11 May 2021 17:28:16 +0530 Subject: [PATCH 051/868] fix: Add New Shortcut --- frappe/desk/desktop.py | 50 ++++++++++++ frappe/public/js/frappe/views/wiki.js | 34 +++++++- .../public/js/frappe/widgets/widget_group.js | 4 - frappe/public/js/frappe/wiki_blocks/blank.js | 10 +-- frappe/public/js/frappe/wiki_blocks/card.js | 21 +++-- frappe/public/js/frappe/wiki_blocks/chart.js | 15 ++-- .../public/js/frappe/wiki_blocks/paragraph.js | 10 +-- .../public/js/frappe/wiki_blocks/shortcut.js | 77 ++++++++++++------- 8 files changed, 164 insertions(+), 57 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index d1b5e27a2f..7f054d5c1f 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -537,6 +537,56 @@ def save_customization(page, config): return True +@frappe.whitelist() +def save_new_widget(page, new_widgets): + original_page = frappe.get_doc("Workspace", page) + widgets = _dict(loads(new_widgets)) + + if widgets.chart: + original_page.charts = new_widget(widgets.chart, "Workspace Chart", "charts") + if widgets.shortcut: + original_page.shortcuts.extend(new_widget(widgets.shortcut, "Workspace Shortcut", "shortcuts")) + if widgets.card: + original_page.build_links_table_from_cards(widgets.card) + + try: + original_page.save(ignore_permissions=True) + except (ValidationError, TypeError) as e: + # Create a json string to log + json_config = dumps(widgets, sort_keys=True, indent=4) + + # Error log body + log = \ + """ + page: {0} + config: {1} + exception: {2} + """.format(page, json_config, e) + frappe.log_error(log, _("Could not save customization")) + return False + + return True + +def new_widget(config, doctype, parentfield): + if not config: + return [] + prepare_widget_list = [] + for idx, widget in enumerate(config): + # Some cleanup + widget.pop("name", None) + + # New Doc + doc = frappe.new_doc(doctype) + doc.update(widget) + + # Manually Set IDX + doc.idx = idx + 1 + + # Set Parent Field + doc.parentfield = parentfield + + prepare_widget_list.append(doc) + return prepare_widget_list def prepare_widget(config, doctype, parentfield): """Create widget child table entries with parent details diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index dcfa840997..b1fe2dbdf5 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -14,6 +14,7 @@ frappe.views.Wiki = class Wiki { this.sorted_sidebar_items = []; this.tools = {} this.isReadOnly = true; + this.new_page = null; this.prepare_container(); this.setup_wiki_pages(); } @@ -39,6 +40,10 @@ frappe.views.Wiki = class Wiki { frappe.router.route(); this.make_sidebar(root_pages); } + if (this.new_page) { + frappe.set_route(`wiki/${frappe.router.slug(this.new_page)}`) + this.new_page = null; + } }) } @@ -258,6 +263,7 @@ frappe.views.Wiki = class Wiki { this.setup_customization_buttons(); this.make_sidebar_sortable(); this.make_blocks_sortable(); + // this.customize(); }) }, ); @@ -296,7 +302,8 @@ frappe.views.Wiki = class Wiki { make_blocks_sortable() { let me = this; this.page_sortable = Sortable.create(this.page.main.find(".codex-editor__redactor").get(0), { - handle: ".ce-block", + handle: ".drag-handle", + draggable: ".ce-block", animation: 150, onEnd: function (evt){ me.editor.blocks.move(evt.newIndex, evt.oldIndex); @@ -374,6 +381,8 @@ frappe.views.Wiki = class Wiki { this.isReadOnly = false; this.editor.readOnly.toggle(); } + this.make_sidebar_sortable(); + this.make_blocks_sortable(); this.dirty = false; }) } @@ -407,6 +416,17 @@ frappe.views.Wiki = class Wiki { } let me = this; this.editor.save().then((outputData) => { + let new_widgets = {}; + outputData.blocks.forEach(item => { + if (item.data.new) { + if (!new_widgets[item.type]) { + new_widgets[item.type] = [] + } + new_widgets[item.type].push(item.data.new); + delete item.data['new']; + } + }) + frappe.call({ method: "frappe.desk.doctype.internal_wiki_page.internal_wiki_page.save_wiki_page", args: { @@ -419,10 +439,22 @@ frappe.views.Wiki = class Wiki { callback: function(res) { frappe.dom.unfreeze(); if (res.message) { + let cur_page = res.message; + if (!$.isEmptyObject(new_widgets)) { + frappe.call('frappe.desk.desktop.save_new_widget', { + page: me.title, + new_widgets: new_widgets + }).then(res => { + if(res.message) { + me.reload(); + } + }); + } frappe.show_alert({ message: __("Page Saved Successfully"), indicator: "green" }); me.title = ''; me.parent = ''; me.sorted_sidebar_items = []; + me.new_page = cur_page; me.reload(); } } diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index d1a5e3013c..3d97a8f778 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -218,13 +218,9 @@ export class SingleWidgetGroup { } customize() { - // if (!this.hidden) this.widget_area.show(); this.widgets_list.forEach((wid) => { wid.customize(this.options); }); - - // this.options.allow_create && this.setup_new_widget(); - // this.options.allow_sorting && this.setup_sortable(); } } diff --git a/frappe/public/js/frappe/wiki_blocks/blank.js b/frappe/public/js/frappe/wiki_blocks/blank.js index fa1a950280..ae8a53fc33 100644 --- a/frappe/public/js/frappe/wiki_blocks/blank.js +++ b/frappe/public/js/frappe/wiki_blocks/blank.js @@ -15,11 +15,11 @@ export default class Blank { this.api = api; this.config = config; this.readOnly = readOnly; - this.col = this.data.col ? this.data.col : "12", - this.pt = this.data.pt ? this.data.pt : "0", - this.pr = this.data.pr ? this.data.pr : "0", - this.pb = this.data.pb ? this.data.pb : "0", - this.pl = this.data.pl ? this.data.pl : "0" + this.col = this.data.col ? this.data.col : "12"; + this.pt = this.data.pt ? this.data.pt : "0"; + this.pr = this.data.pr ? this.data.pr : "0"; + this.pb = this.data.pb ? this.data.pb : "0"; + this.pl = this.data.pl ? this.data.pl : "0"; } render() { diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index 12061e2d02..a859b04439 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -16,11 +16,12 @@ export default class Card { this.config = config; this.readOnly = readOnly; this.sections = {}; - this.col = this.data.col ? this.data.col : "12", - this.pt = this.data.pt ? this.data.pt : "0", - this.pr = this.data.pr ? this.data.pr : "0", - this.pb = this.data.pb ? this.data.pb : "0", - this.pl = this.data.pl ? this.data.pl : "0" + this.col = this.data.col ? this.data.col : "12"; + this.pt = this.data.pt ? this.data.pt : "0"; + this.pr = this.data.pr ? this.data.pr : "0"; + this.pb = this.data.pb ? this.data.pb : "0"; + this.pl = this.data.pl ? this.data.pl : "0"; + this.allow_customization = !this.readOnly; } render() { @@ -135,15 +136,16 @@ export default class Card { }); this.wrapper.innerHTML = ''; this.sections = {}; + card.in_customize_mode = !this.readOnly; let cards = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "links", columns: 3, options: { allow_sorting: this.allow_customization, - allow_create: false, - allow_delete: false, - allow_hiding: this.allow_customization, + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, allow_edit: false, }, widgets: card @@ -151,5 +153,8 @@ export default class Card { this.sections["cards"] = cards; this.wrapper.setAttribute("card_name", card_name); + if (!this.readOnly) { + this.sections["cards"].customize(); + } } } \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index 054e8d1c12..f8c97852fa 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -16,11 +16,12 @@ export default class Chart { this.config = config; this.readOnly = readOnly; this.sections = {}; - this.col = this.data.col ? this.data.col : "12", - this.pt = this.data.pt ? this.data.pt : "0", - this.pr = this.data.pr ? this.data.pr : "0", - this.pb = this.data.pb ? this.data.pb : "0", - this.pl = this.data.pl ? this.data.pl : "0" + this.col = this.data.col ? this.data.col : "12"; + this.pt = this.data.pt ? this.data.pt : "0"; + this.pr = this.data.pr ? this.data.pr : "0"; + this.pb = this.data.pb ? this.data.pb : "0"; + this.pl = this.data.pl ? this.data.pl : "0"; + this.allow_customization = !this.readOnly; } render() { @@ -135,6 +136,7 @@ export default class Chart { }); this.wrapper.innerHTML = ''; this.sections = {}; + chart.in_customize_mode = !this.readOnly; this.sections["charts"] = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "chart", @@ -152,5 +154,8 @@ export default class Chart { widgets: chart }); this.wrapper.setAttribute("chart_name", chart_name) + if (!this.readOnly) { + this.sections["charts"].customize(); + } } } \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index 0cab2b9373..570a04e661 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -23,11 +23,11 @@ export default class Paragraph { this._preserveBlank = config.preserveBlank !== undefined ? config.preserveBlank : false; this.data = data; - this.col = this.data.col ? this.data.col : "12", - this.pt = this.data.pt ? this.data.pt : "0", - this.pr = this.data.pr ? this.data.pr : "0", - this.pb = this.data.pb ? this.data.pb : "0", - this.pl = this.data.pl ? this.data.pl : "0" + this.col = this.data.col ? this.data.col : "12"; + this.pt = this.data.pt ? this.data.pt : "0"; + this.pr = this.data.pr ? this.data.pr : "0"; + this.pb = this.data.pb ? this.data.pb : "0"; + this.pl = this.data.pl ? this.data.pl : "0"; } onKeyUp(e) { diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index 0cb8de6ef8..1a3d2ae970 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -1,3 +1,4 @@ +import get_dialog_constructor from "../widgets/widget_dialog.js"; export default class Shortcut { static get toolbox() { return { @@ -15,28 +16,25 @@ export default class Shortcut { this.api = api; this.config = config; this.readOnly = readOnly; - this.sections = {}; - this.col = this.data.col ? this.data.col : "12", - this.pt = this.data.pt ? this.data.pt : "0", - this.pr = this.data.pr ? this.data.pr : "0", - this.pb = this.data.pb ? this.data.pb : "0", - this.pl = this.data.pl ? this.data.pl : "0" + this.col = this.data.col ? this.data.col : "12"; + this.pt = this.data.pt ? this.data.pt : "0"; + this.pr = this.data.pr ? this.data.pr : "0"; + this.pb = this.data.pb ? this.data.pb : "0"; + this.pl = this.data.pl ? this.data.pl : "0"; + this.allow_customization = !this.readOnly; + this.options = { + allow_sorting: this.allow_customization, + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, + allow_edit: true, + } } render() { - let me = this; this.wrapper = document.createElement('div'); - this._make_fieldgroup(this.wrapper, [{ - fieldtype: "Select", - label: "Shortcut Name", - fieldname: "shortcut_name", - options: this.config.page_data.shortcuts.items.map(({ label }) => label), - change: function() { - if (this.value) { - me._make_shortcuts(this.value); - } - } - }]); + this._new_shortcut(); + if (this.data && this.data.shortcut_name) { this._make_shortcuts(this.data.shortcut_name) } @@ -50,7 +48,8 @@ export default class Shortcut { pt: this._getPadding("t"), pr: this._getPadding("r"), pb: this._getPadding("b"), - pl: this._getPadding("l") + pl: this._getPadding("l"), + new: this.new_shortcut_widget } } @@ -63,6 +62,30 @@ export default class Shortcut { e.classList.add("pl-" + this.pl) } + _new_shortcut() { + const dialog_class = get_dialog_constructor('shortcut'); + this.dialog = new dialog_class({ + label: this.label, + type: 'shortcut', + primary_action: (widget) => { + widget.in_customize_mode = 1; + let wid = frappe.widget.make_widget({ + ...widget, + widget_type: 'shortcut', + container: this.wrapper, + options: this.options, + }); + wid.customize(this.options); + this.wrapper.setAttribute("shortcut_name", wid.label); + this.new_shortcut_widget = wid.get_config(); + }, + }); + + if (!this.readOnly && this.data && !this.data.shortcut_name) { + this.dialog.make(); + } + } + _getCol() { var e = 12, t = "col-12", @@ -134,20 +157,16 @@ export default class Shortcut { return obj.label == shortcut_name }); this.wrapper.innerHTML = ''; - this.sections = {}; - this.sections["shortcuts"] = new frappe.widget.SingleWidgetGroup({ + shortcut.in_customize_mode = !this.readOnly; + let shortcut_widget = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "shortcut", - columns: 3, - options: { - allow_sorting: this.allow_customization, - allow_create: this.allow_customization, - allow_delete: this.allow_customization, - allow_hiding: false, - allow_edit: true, - }, + options: this.options, widgets: shortcut }); this.wrapper.setAttribute("shortcut_name", shortcut_name); + if (!this.readOnly) { + shortcut_widget.customize(); + } } } \ No newline at end of file From 80db1a715a8de19fdcd65a0b5b33aa178d79253f Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 12 May 2021 13:23:47 +0530 Subject: [PATCH 052/868] fix: Add New Card --- frappe/desk/desktop.py | 4 +- frappe/desk/doctype/workspace/workspace.py | 29 ++++++ .../public/js/frappe/widgets/widget_dialog.js | 93 +++++++++++++++++++ frappe/public/js/frappe/wiki_blocks/card.js | 65 +++++++------ 4 files changed, 163 insertions(+), 28 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 7f054d5c1f..c096f50b78 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -543,11 +543,11 @@ def save_new_widget(page, new_widgets): widgets = _dict(loads(new_widgets)) if widgets.chart: - original_page.charts = new_widget(widgets.chart, "Workspace Chart", "charts") + original_page.charts.extend(new_widget(widgets.chart, "Workspace Chart", "charts")) if widgets.shortcut: original_page.shortcuts.extend(new_widget(widgets.shortcut, "Workspace Shortcut", "shortcuts")) if widgets.card: - original_page.build_links_table_from_cards(widgets.card) + original_page.build_links_table_from_card(widgets.card) try: original_page.save(ignore_permissions=True) diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 0934138821..20c9240188 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -100,6 +100,35 @@ class Workspace(Document): "is_query_report": link.get('is_query_report') }) + def build_links_table_from_card(self, config): + # Empty links table + # self.links = [] + # order = config.get('order') + # widgets = config.get('widgets') + + for idx, card in enumerate(config): + # card = widgets[name].copy() + links = loads(card.get('links')) + + self.append('links', { + "label": card.get('label'), + "type": "Card Break", + "icon": card.get('icon'), + "hidden": card.get('hidden') or False + }) + + for link in links: + self.append('links', { + "label": link.get('label'), + "type": "Link", + "link_type": link.get('link_type'), + "link_to": link.get('link_to'), + "onboard": link.get('onboard'), + "only_for": link.get('only_for'), + "dependencies": link.get('dependencies'), + "is_query_report": link.get('is_query_report') + }) + def disable_saving_as_standard(): return frappe.flags.in_install or \ diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index eefb78c29a..5bcaaf9e3e 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -124,6 +124,98 @@ class ChartDialog extends WidgetDialog { } } +class CardDialog extends WidgetDialog { + constructor(opts) { + super(opts); + } + + get_fields() { + let me = this; + return [ + { + fieldtype: "Data", + fieldname: "label", + label: "Label", + }, + { + fieldname: 'links', + fieldtype: 'Table', + label: __('Card Links'), + editable_grid: 1, + data: this.data || [], + get_data: () => { + return this.data || []; + }, + fields: [ + { + fieldname: "label", + fieldtype: "Data", + in_list_view: 1, + label: "Label" + }, + { + fieldname: "icon", + fieldtype: "Data", + label: "Icon" + }, + { + fieldname: "link_type", + fieldtype: "Select", + in_list_view: 1, + label: "Link Type", + options: ["DocType", "Page", "Report"], + onchange: (e) => { + me.link_to = e.currentTarget.value; + } + }, + { + fieldname: "link_to", + fieldtype: "Dynamic Link", + in_list_view: 1, + label: "Link To", + options: "link_type", + get_options: () => { + return me.link_to; + } + }, + { + fieldname: "column_break_7", + fieldtype: "Column Break" + }, + { + fieldname: "dependencies", + fieldtype: "Data", + label: "Dependencies" + }, + { + fieldname: "only_for", + fieldtype: "Link", + label: "Only for ", + options: "Country" + }, + { + default: "0", + fieldname: "onboard", + fieldtype: "Check", + label: "Onboard" + }, + { + default: "0", + fieldname: "is_query_report", + fieldtype: "Check", + label: "Is Query Report" + } + ], + }, + ]; + } + + process_data(data) { + data.label = data.label ? data.label : data.chart_name; + return data; + } +} + class ShortcutDialog extends WidgetDialog { constructor(opts) { super(opts); @@ -437,6 +529,7 @@ export default function get_dialog_constructor(type) { chart: ChartDialog, shortcut: ShortcutDialog, number_card: NumberCardDialog, + card: CardDialog, }; return widget_map[type] || WidgetDialog; diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index a859b04439..cc79a57c3e 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -1,3 +1,4 @@ +import get_dialog_constructor from "../widgets/widget_dialog.js"; export default class Card { static get toolbox() { return { @@ -22,22 +23,19 @@ export default class Card { this.pb = this.data.pb ? this.data.pb : "0"; this.pl = this.data.pl ? this.data.pl : "0"; this.allow_customization = !this.readOnly; + this.options = { + allow_sorting: this.allow_customization, + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, + allow_edit: false, + } } render() { - let me = this; this.wrapper = document.createElement('div'); - this._make_fieldgroup(this.wrapper, [{ - fieldtype: "Select", - label: "Card Name", - fieldname: "card_name", - options: this.config.page_data.cards.items.map(({ label }) => label), - change: function() { - if (this.value) { - me._make_cards(this.value) - } - } - }]); + this._new_card(); + if (this.data && this.data.card_name) { this._make_cards(this.data.card_name) } @@ -51,7 +49,8 @@ export default class Card { pt: this._getPadding("t"), pr: this._getPadding("r"), pb: this._getPadding("b"), - pl: this._getPadding("l") + pl: this._getPadding("l"), + new: this.new_card_widget } } @@ -64,6 +63,30 @@ export default class Card { e.classList.add("pl-" + this.pl) } + _new_card() { + const dialog_class = get_dialog_constructor('card'); + this.dialog = new dialog_class({ + label: this.label, + type: 'card', + primary_action: (widget) => { + widget.in_customize_mode = 1; + let wid = frappe.widget.make_widget({ + ...widget, + widget_type: 'links', + container: this.wrapper, + options: this.options, + }); + wid.customize(this.options); + this.wrapper.setAttribute("card_name", wid.label); + this.new_card_widget = wid.get_config(); + }, + }); + + if (!this.readOnly && this.data && !this.data.card_name) { + this.dialog.make(); + } + } + _getCol() { var e = 12, t = "col-12", @@ -135,26 +158,16 @@ export default class Card { return obj.label == card_name }); this.wrapper.innerHTML = ''; - this.sections = {}; card.in_customize_mode = !this.readOnly; - let cards = new frappe.widget.SingleWidgetGroup({ + let card_widget = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "links", - columns: 3, - options: { - allow_sorting: this.allow_customization, - allow_create: this.allow_customization, - allow_delete: this.allow_customization, - allow_hiding: false, - allow_edit: false, - }, + options: this.options, widgets: card }); - - this.sections["cards"] = cards; this.wrapper.setAttribute("card_name", card_name); if (!this.readOnly) { - this.sections["cards"].customize(); + card_widget.customize(); } } } \ No newline at end of file From 2f89787fa96a8883ee056c90c0f539b7be7ab14e Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 12 May 2021 14:33:12 +0530 Subject: [PATCH 053/868] fix: sider fix --- .../internal_wiki_page/internal_wiki_page.py | 4 +- frappe/desk/page/wiki/wiki.js | 4 +- frappe/public/js/frappe/views/wiki.js | 77 ++++++++-------- frappe/public/js/frappe/wiki_blocks/blank.js | 34 +++---- frappe/public/js/frappe/wiki_blocks/blocks.js | 4 +- frappe/public/js/frappe/wiki_blocks/card.js | 40 ++++----- frappe/public/js/frappe/wiki_blocks/chart.js | 42 ++++----- .../public/js/frappe/wiki_blocks/paragraph.js | 48 +++++----- .../public/js/frappe/wiki_blocks/shortcut.js | 40 ++++----- .../js/frappe/wiki_blocks/spacing_tune.js | 88 +++++++++---------- frappe/public/scss/desk/wiki.scss | 49 +++++------ 11 files changed, 213 insertions(+), 217 deletions(-) diff --git a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py index 9e291ed265..6e695ef516 100644 --- a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py +++ b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py @@ -3,8 +3,8 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, json -from frappe import _ +import frappe +import json from frappe.model.document import Document class InternalWikiPage(Document): diff --git a/frappe/desk/page/wiki/wiki.js b/frappe/desk/page/wiki/wiki.js index 81ff2a7fa2..6ac8bc89cb 100644 --- a/frappe/desk/page/wiki/wiki.js +++ b/frappe/desk/page/wiki/wiki.js @@ -1,4 +1,4 @@ -frappe.provide('frappe.views') +frappe.provide('frappe.views'); frappe.pages['wiki'].on_page_load = function(wrapper) { frappe.ui.make_app_page({ @@ -12,4 +12,4 @@ frappe.pages['wiki'].on_page_load = function(wrapper) { $(wrapper).bind('show', function () { frappe.wiki.show(); }); -} +}; diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index b1fe2dbdf5..a7c41b66bc 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -12,7 +12,7 @@ frappe.views.Wiki = class Wiki { this.sections = {}; this.sidebar_items = {}; this.sorted_sidebar_items = []; - this.tools = {} + this.tools = {}; this.isReadOnly = true; this.new_page = null; this.prepare_container(); @@ -31,9 +31,9 @@ frappe.views.Wiki = class Wiki { setup_wiki_pages() { this.get_pages().then(() => { - if(this.all_pages) { + if (this.all_pages) { frappe.wiki_pages = {}; - let root_pages = this.all_pages.filter(page => page.parent_page == '' || page.parent_page == null) + let root_pages = this.all_pages.filter(page => page.parent_page == '' || page.parent_page == null); for (let page of this.all_pages || []) { frappe.wiki_pages[frappe.router.slug(page.name)] = page; } @@ -41,10 +41,10 @@ frappe.views.Wiki = class Wiki { this.make_sidebar(root_pages); } if (this.new_page) { - frappe.set_route(`wiki/${frappe.router.slug(this.new_page)}`) + frappe.set_route(`wiki/${frappe.router.slug(this.new_page)}`); this.new_page = null; } - }) + }); } get_pages() { @@ -55,7 +55,7 @@ frappe.views.Wiki = class Wiki { make_sidebar(items) { if (this.sidebar.find('.standard-sidebar-section')[0]) { - this.sidebar.find('.standard-sidebar-section')[0].remove() + this.sidebar.find('.standard-sidebar-section')[0].remove(); } let sidebar_section = $(`
`); @@ -95,25 +95,25 @@ frappe.views.Wiki = class Wiki {
`); - } + }; const make_sidebar_child_item = item => { let $child_item = get_child_item(item); - $child_item.appendTo(child_item_section) + $child_item.appendTo(child_item_section); this.sidebar_items[item.name] = $child_item; - } + }; let $item = get_sidebar_item(item); let drop_icon = $item.find('.drop-icon').get(0); let child_item_section = $item.find('.sidebar-child-item').get(0); - if(this.all_pages.some(e => e.parent_page == item.name)) { + if (this.all_pages.some(e => e.parent_page == item.name)) { drop_icon.classList.remove('hidden'); drop_icon.addEventListener('click', () => { child_item_section.classList.toggle("hidden"); }); } - let child_items = this.all_pages.filter(page => page.parent_page == item.name) + let child_items = this.all_pages.filter(page => page.parent_page == item.name); child_items.forEach(item => make_sidebar_child_item(item)); $item.appendTo(sidebar_section); @@ -138,7 +138,7 @@ frappe.views.Wiki = class Wiki { this.show_page(page); this.get_content(page).then(() => { this.get_data(page).then(() => { - if(this.content){ + if (this.content) { this.tools = { header: { class: Header, @@ -176,22 +176,22 @@ frappe.views.Wiki = class Wiki { }, blank: frappe.wiki_block.blocks['blank'], spacingTune: frappe.wiki_block.tunes['spacing_tune'], - } - if(this.editor) { + }; + if (this.editor) { this.editor.isReady.then(() => { this.editor.configuration.tools.chart.config.page_data = this.page_data; this.editor.configuration.tools.shortcut.config.page_data = this.page_data; this.editor.configuration.tools.card.config.page_data = this.page_data; this.editor.render({ blocks: JSON.parse(this.content) || [] - }) - }) + }); + }); } else { this.initialize_editorjs(JSON.parse(this.content)); } } - }) - }) + }); + }); } get_content(page) { @@ -257,14 +257,14 @@ frappe.views.Wiki = class Wiki { this.isReadOnly = false; this.editor.readOnly.toggle(); this.editor.isReady - .then(() => { - this.undo = new Undo({ editor: this.editor }); - this.undo.initialize({blocks: JSON.parse(this.content)}); - this.setup_customization_buttons(); - this.make_sidebar_sortable(); - this.make_blocks_sortable(); - // this.customize(); - }) + .then(() => { + this.undo = new Undo({ editor: this.editor }); + this.undo.initialize({blocks: JSON.parse(this.content)}); + this.setup_customization_buttons(); + this.make_sidebar_sortable(); + this.make_blocks_sortable(); + // this.customize(); + }); }, ); @@ -279,14 +279,14 @@ frappe.views.Wiki = class Wiki { handle: ".standard-sidebar-item-container", draggable: ".standard-sidebar-item-container", animation: 150, - onEnd: function (evt){ + onEnd: function (evt) { let new_sb_items = []; - let old_sb_items = me.all_pages.filter(page => page.parent_page == '' || page.parent_page == null) + let old_sb_items = me.all_pages.filter(page => page.parent_page == '' || page.parent_page == null); for (let page of evt.srcElement.childNodes) { new_sb_items.push({ name: page.attributes['item-name'].value, sequence_id: parseInt(page.attributes['item-sequence'].value) - }) + }); } me.sorted_sidebar_items = []; new_sb_items.forEach((old, index) => { @@ -305,7 +305,7 @@ frappe.views.Wiki = class Wiki { handle: ".drag-handle", draggable: ".ce-block", animation: 150, - onEnd: function (evt){ + onEnd: function (evt) { me.editor.blocks.move(evt.newIndex, evt.oldIndex); }, setData: function (dataTransfer, dragEl) { @@ -377,14 +377,14 @@ frappe.views.Wiki = class Wiki { } ] }).then(() => { - if(this.editor.configuration.readOnly) { + if (this.editor.configuration.readOnly) { this.isReadOnly = false; this.editor.readOnly.toggle(); } this.make_sidebar_sortable(); this.make_blocks_sortable(); this.dirty = false; - }) + }); } }); d.show(); @@ -394,7 +394,7 @@ frappe.views.Wiki = class Wiki { this.dirty = false; const data = { blocks: blocks || [] - } + }; this.editor = new EditorJS({ tools: this.tools, autofocus: false, @@ -421,11 +421,11 @@ frappe.views.Wiki = class Wiki { if (item.data.new) { if (!new_widgets[item.type]) { new_widgets[item.type] = [] - } + }; new_widgets[item.type].push(item.data.new); delete item.data['new']; } - }) + }); frappe.call({ method: "frappe.desk.doctype.internal_wiki_page.internal_wiki_page.save_wiki_page", @@ -445,7 +445,7 @@ frappe.views.Wiki = class Wiki { page: me.title, new_widgets: new_widgets }).then(res => { - if(res.message) { + if (res.message) { me.reload(); } }); @@ -460,7 +460,8 @@ frappe.views.Wiki = class Wiki { } }); }).catch((error) => { - console.log('Saving failed: ', error); + error; + // console.log('Saving failed: ', error); }); } @@ -468,4 +469,4 @@ frappe.views.Wiki = class Wiki { this.setup_wiki_pages(); this.dirty = false; } -} +}; diff --git a/frappe/public/js/frappe/wiki_blocks/blank.js b/frappe/public/js/frappe/wiki_blocks/blank.js index ae8a53fc33..f32007de6c 100644 --- a/frappe/public/js/frappe/wiki_blocks/blank.js +++ b/frappe/public/js/frappe/wiki_blocks/blank.js @@ -10,7 +10,7 @@ export default class Blank { return true; } - constructor({data, api, config, readOnly}){ + constructor({data, api, config, readOnly}) { this.data = data; this.api = api; this.config = config; @@ -39,22 +39,22 @@ export default class Blank { pr: this._getPadding("r"), pb: this._getPadding("b"), pl: this._getPadding("l") - } + }; } rendered() { var e = this.wrapper.parentNode.parentNode; - e.classList.add("col-" + this.col) - e.classList.add("pt-" + this.pt) - e.classList.add("pr-" + this.pr) - e.classList.add("pb-" + this.pb) - e.classList.add("pl-" + this.pl) + e.classList.add("col-" + this.col); + e.classList.add("pt-" + this.pt); + e.classList.add("pr-" + this.pr); + e.classList.add("pb-" + this.pb); + e.classList.add("pl-" + this.pl); } _getCol() { - var e = 12, - t = "col-12", - n = this.wrapper.parentNode.parentNode, + var e = 12; + t = "col-12"; + n = this.wrapper.parentNode.parentNode; r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { @@ -67,13 +67,13 @@ export default class Blank { } _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l", - t = 0, - n = "p" + e + "-0", - r = this.wrapper.parentNode.parentNode, - a = new RegExp(/\pl-.+?\b/, "g"), - i = new RegExp(/\pr-.+?\b/, "g"), - o = new RegExp(/\pt-.+?\b/, "g"), + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; + t = 0; + n = "p" + e + "-0"; + r = this.wrapper.parentNode.parentNode; + a = new RegExp(/\pl-.+?\b/, "g"); + i = new RegExp(/\pr-.+?\b/, "g"); + o = new RegExp(/\pt-.+?\b/, "g"); c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { diff --git a/frappe/public/js/frappe/wiki_blocks/blocks.js b/frappe/public/js/frappe/wiki_blocks/blocks.js index 1b556eeaee..239127a674 100644 --- a/frappe/public/js/frappe/wiki_blocks/blocks.js +++ b/frappe/public/js/frappe/wiki_blocks/blocks.js @@ -19,5 +19,5 @@ frappe.wiki_block.blocks = { }; frappe.wiki_block.tunes = { - spacing_tune : SpacingTune -} \ No newline at end of file + spacing_tune: SpacingTune +}; \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index cc79a57c3e..dd457fea4c 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -11,7 +11,7 @@ export default class Card { return true; } - constructor({data, api, config, readOnly, block}){ + constructor({data, api, config, readOnly}) { this.data = data; this.api = api; this.config = config; @@ -29,7 +29,7 @@ export default class Card { allow_delete: this.allow_customization, allow_hiding: false, allow_edit: false, - } + }; } render() { @@ -37,7 +37,7 @@ export default class Card { this._new_card(); if (this.data && this.data.card_name) { - this._make_cards(this.data.card_name) + this._make_cards(this.data.card_name); } return this.wrapper; } @@ -51,16 +51,16 @@ export default class Card { pb: this._getPadding("b"), pl: this._getPadding("l"), new: this.new_card_widget - } + }; } rendered() { var e = this.wrapper.parentNode.parentNode; - e.classList.add("col-" + this.col) - e.classList.add("pt-" + this.pt) - e.classList.add("pr-" + this.pr) - e.classList.add("pb-" + this.pb) - e.classList.add("pl-" + this.pl) + e.classList.add("col-" + this.col); + e.classList.add("pt-" + this.pt); + e.classList.add("pr-" + this.pr); + e.classList.add("pb-" + this.pb); + e.classList.add("pl-" + this.pl); } _new_card() { @@ -88,9 +88,9 @@ export default class Card { } _getCol() { - var e = 12, - t = "col-12", - n = this.wrapper.parentNode.parentNode, + var e = 12; + t = "col-12"; + n = this.wrapper.parentNode.parentNode; r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { @@ -103,13 +103,13 @@ export default class Card { } _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l", - t = 0, - n = "p" + e + "-0", - r = this.wrapper.parentNode.parentNode, - a = new RegExp(/\pl-.+?\b/, "g"), - i = new RegExp(/\pr-.+?\b/, "g"), - o = new RegExp(/\pt-.+?\b/, "g"), + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; + t = 0; + n = "p" + e + "-0"; + r = this.wrapper.parentNode.parentNode; + a = new RegExp(/\pl-.+?\b/, "g"); + i = new RegExp(/\pr-.+?\b/, "g"); + o = new RegExp(/\pt-.+?\b/, "g"); c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { @@ -155,7 +155,7 @@ export default class Card { _make_cards(card_name) { let card = this.config.page_data.cards.items.find(obj => { - return obj.label == card_name + return obj.label == card_name; }); this.wrapper.innerHTML = ''; card.in_customize_mode = !this.readOnly; diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index f8c97852fa..5acaa81627 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -10,7 +10,7 @@ export default class Chart { return true; } - constructor({data, api, config, readOnly}){ + constructor({data, api, config, readOnly}) { this.data = data; this.api = api; this.config = config; @@ -34,12 +34,12 @@ export default class Chart { options: this.config.page_data.charts.items.map(({ chart_name }) => chart_name), change: function() { if (this.value) { - me._make_charts(this.value) + me._make_charts(this.value); } } }]); if (this.data && this.data.chart_name) { - this._make_charts(this.data.chart_name) + this._make_charts(this.data.chart_name); } return this.wrapper; } @@ -52,22 +52,22 @@ export default class Chart { pr: this._getPadding("r"), pb: this._getPadding("b"), pl: this._getPadding("l") - } + }; } rendered() { var e = this.wrapper.parentNode.parentNode; - e.classList.add("col-" + this.col) - e.classList.add("pt-" + this.pt) - e.classList.add("pr-" + this.pr) - e.classList.add("pb-" + this.pb) - e.classList.add("pl-" + this.pl) + e.classList.add("col-" + this.col); + e.classList.add("pt-" + this.pt); + e.classList.add("pr-" + this.pr); + e.classList.add("pb-" + this.pb); + e.classList.add("pl-" + this.pl); } _getCol() { - var e = 12, - t = "col-12", - n = this.wrapper.parentNode.parentNode, + var e = 12; + t = "col-12"; + n = this.wrapper.parentNode.parentNode; r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { @@ -80,13 +80,13 @@ export default class Chart { } _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l", - t = 0, - n = "p" + e + "-0", - r = this.wrapper.parentNode.parentNode, - a = new RegExp(/\pl-.+?\b/, "g"), - i = new RegExp(/\pr-.+?\b/, "g"), - o = new RegExp(/\pt-.+?\b/, "g"), + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; + t = 0; + n = "p" + e + "-0"; + r = this.wrapper.parentNode.parentNode; + a = new RegExp(/\pl-.+?\b/, "g"); + i = new RegExp(/\pr-.+?\b/, "g"); + o = new RegExp(/\pt-.+?\b/, "g"); c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { @@ -132,7 +132,7 @@ export default class Chart { _make_charts(chart_name) { let chart = this.config.page_data.charts.items.find(obj => { - return obj.chart_name == chart_name + return obj.chart_name == chart_name; }); this.wrapper.innerHTML = ''; this.sections = {}; @@ -153,7 +153,7 @@ export default class Chart { }, widgets: chart }); - this.wrapper.setAttribute("chart_name", chart_name) + this.wrapper.setAttribute("chart_name", chart_name); if (!this.readOnly) { this.sections["charts"].customize(); } diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index 570a04e661..affc2b436d 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -62,7 +62,7 @@ export default class Paragraph { merge(data) { let newData = { - text : this.data.text + data.text + text: this.data.text + data.text }; this.data = newData; @@ -70,7 +70,7 @@ export default class Paragraph { validate(savedData) { if (savedData.text.trim() === '' && !this._preserveBlank) { - return false; + return false; } return true; @@ -89,17 +89,17 @@ export default class Paragraph { rendered() { var e = this._element.parentNode.parentNode; - e.classList.add("col-" + this.col) - e.classList.add("pt-" + this.pt) - e.classList.add("pr-" + this.pr) - e.classList.add("pb-" + this.pb) - e.classList.add("pl-" + this.pl) + e.classList.add("col-" + this.col); + e.classList.add("pt-" + this.pt); + e.classList.add("pr-" + this.pr); + e.classList.add("pb-" + this.pb); + e.classList.add("pl-" + this.pl); } _getCol() { - var e = 12, - t = "col-12", - n = this._element.parentNode.parentNode, + var e = 12; + t = "col-12"; + n = this._element.parentNode.parentNode; r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { @@ -112,13 +112,13 @@ export default class Paragraph { } _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l", - t = 0, - n = "p" + e + "-0", - r = this._element.parentNode.parentNode, - a = new RegExp(/\pl-.+?\b/, "g"), - i = new RegExp(/\pr-.+?\b/, "g"), - o = new RegExp(/\pt-.+?\b/, "g"), + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; + t = 0; + n = "p" + e + "-0"; + r = this._element.parentNode.parentNode; + a = new RegExp(/\pl-.+?\b/, "g"); + i = new RegExp(/\pr-.+?\b/, "g"); + o = new RegExp(/\pt-.+?\b/, "g"); c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { @@ -156,7 +156,7 @@ export default class Paragraph { onPaste(event) { const data = { - text: event.detail.data.innerHTML + text: event.detail.data.innerHTML }; this.data = data; @@ -164,16 +164,16 @@ export default class Paragraph { static get conversionConfig() { return { - export: 'text', // to convert Paragraph to other block, use 'text' property of saved data - import: 'text' // to covert other block's exported string to Paragraph, fill 'text' property of tool data + export: 'text', // to convert Paragraph to other block, use 'text' property of saved data + import: 'text' // to covert other block's exported string to Paragraph, fill 'text' property of tool data }; } static get sanitize() { return { - text: { - br: true, - } + text: { + br: true, + } }; } @@ -197,7 +197,7 @@ export default class Paragraph { static get pasteConfig() { return { - tags: [ 'P' ] + tags: [ 'P' ] }; } diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index 1a3d2ae970..7bcebb478a 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -11,7 +11,7 @@ export default class Shortcut { return true; } - constructor({data, api, config, readOnly}){ + constructor({data, api, config, readOnly}) { this.data = data; this.api = api; this.config = config; @@ -28,7 +28,7 @@ export default class Shortcut { allow_delete: this.allow_customization, allow_hiding: false, allow_edit: true, - } + }; } render() { @@ -36,7 +36,7 @@ export default class Shortcut { this._new_shortcut(); if (this.data && this.data.shortcut_name) { - this._make_shortcuts(this.data.shortcut_name) + this._make_shortcuts(this.data.shortcut_name); } return this.wrapper; } @@ -50,16 +50,16 @@ export default class Shortcut { pb: this._getPadding("b"), pl: this._getPadding("l"), new: this.new_shortcut_widget - } + }; } rendered() { var e = this.wrapper.parentNode.parentNode; - e.classList.add("col-" + this.col) - e.classList.add("pt-" + this.pt) - e.classList.add("pr-" + this.pr) - e.classList.add("pb-" + this.pb) - e.classList.add("pl-" + this.pl) + e.classList.add("col-" + this.col); + e.classList.add("pt-" + this.pt); + e.classList.add("pr-" + this.pr); + e.classList.add("pb-" + this.pb); + e.classList.add("pl-" + this.pl); } _new_shortcut() { @@ -87,9 +87,9 @@ export default class Shortcut { } _getCol() { - var e = 12, - t = "col-12", - n = this.wrapper.parentNode.parentNode, + var e = 12; + t = "col-12"; + n = this.wrapper.parentNode.parentNode; r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { @@ -102,13 +102,13 @@ export default class Shortcut { } _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l", - t = 0, - n = "p" + e + "-0", - r = this.wrapper.parentNode.parentNode, - a = new RegExp(/\pl-.+?\b/, "g"), - i = new RegExp(/\pr-.+?\b/, "g"), - o = new RegExp(/\pt-.+?\b/, "g"), + var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; + t = 0; + n = "p" + e + "-0"; + r = this.wrapper.parentNode.parentNode; + a = new RegExp(/\pl-.+?\b/, "g"); + i = new RegExp(/\pr-.+?\b/, "g"); + o = new RegExp(/\pt-.+?\b/, "g"); c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { @@ -154,7 +154,7 @@ export default class Shortcut { _make_shortcuts(shortcut_name) { let shortcut = this.config.page_data.shortcuts.items.find(obj => { - return obj.label == shortcut_name + return obj.label == shortcut_name; }); this.wrapper.innerHTML = ''; shortcut.in_customize_mode = !this.readOnly; diff --git a/frappe/public/js/frappe/wiki_blocks/spacing_tune.js b/frappe/public/js/frappe/wiki_blocks/spacing_tune.js index 494ba2e97a..ee76503097 100644 --- a/frappe/public/js/frappe/wiki_blocks/spacing_tune.js +++ b/frappe/public/js/frappe/wiki_blocks/spacing_tune.js @@ -71,7 +71,7 @@ export default class SpacingTune { } let currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -82,13 +82,13 @@ export default class SpacingTune { let colClass = new RegExp(/\bcol-.+?\b/, 'g'); if (currentBlockElement.className.match(colClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(colClass)){ + if (cn.match(colClass)) { className = cn; } }); let parts = className.split('-'); let width = parseInt(parts[1]); - if(width >= 2){ + if (width >= 2) { currentBlockElement.classList.remove('col-'+width); width = width - 1; currentBlockElement.classList.add('col-'+width); @@ -104,7 +104,7 @@ export default class SpacingTune { } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -115,23 +115,23 @@ export default class SpacingTune { const colClass = new RegExp(/\bcol-.+?\b/, 'g'); if (currentBlockElement.className.match(colClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(colClass)){ - className = cn; - } + if (cn.match(colClass)) { + className = cn; + } }); let parts = className.split('-'); let width = parseInt(parts[1]); - if(width <= 11){ - currentBlockElement.classList.remove('col-'+width); - width = width + 1; + if (width <= 11) { + currentBlockElement.classList.remove('col-'+width); + width = width + 1; currentBlockElement.classList.add('col-'+width); - } + } } } showPadding(event, button) { let me = this; - if(button.classList.contains('cdx-settings-button--active')){ + if (button.classList.contains('cdx-settings-button--active')) { this.sidebar.remove(); button.classList.remove('cdx-settings-button--active'); } else { @@ -290,12 +290,12 @@ export default class SpacingTune { increasePaddingLeft(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -306,13 +306,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pl-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding <= 4){ + if (padding <= 4) { currentBlockElement.classList.remove('pl-'+padding); padding = padding + 1; currentBlockElement.classList.add('pl-'+padding); @@ -324,12 +324,12 @@ export default class SpacingTune { decreasePaddingLeft(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -340,13 +340,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pl-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding >= 1){ + if (padding >= 1) { currentBlockElement.classList.remove('pl-'+padding); padding = padding - 1; currentBlockElement.classList.add('pl-'+padding); @@ -357,12 +357,12 @@ export default class SpacingTune { increasePaddingRight(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -373,13 +373,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pr-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding <= 4){ + if (padding <= 4) { currentBlockElement.classList.remove('pr-'+padding); padding = padding + 1; currentBlockElement.classList.add('pr-'+padding); @@ -390,12 +390,12 @@ export default class SpacingTune { decreasePaddingRight(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -406,13 +406,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pr-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding >= 1){ + if (padding >= 1) { currentBlockElement.classList.remove('pr-'+padding); padding = padding - 1; currentBlockElement.classList.add('pr-'+padding); @@ -423,12 +423,12 @@ export default class SpacingTune { increasePaddingTop(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -439,13 +439,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pt-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding <= 4){ + if (padding <= 4) { currentBlockElement.classList.remove('pt-'+padding); padding = padding + 1; currentBlockElement.classList.add('pt-'+padding); @@ -456,12 +456,12 @@ export default class SpacingTune { decreasePaddingTop(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -472,13 +472,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pt-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding >= 1){ + if (padding >= 1) { currentBlockElement.classList.remove('pt-'+padding); padding = padding - 1; currentBlockElement.classList.add('pt-'+padding); @@ -489,12 +489,12 @@ export default class SpacingTune { increasePaddingBottom(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -505,13 +505,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pb-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding <= 4){ + if (padding <= 4) { currentBlockElement.classList.remove('pb-'+padding); padding = padding + 1; currentBlockElement.classList.add('pb-'+padding); @@ -522,12 +522,12 @@ export default class SpacingTune { decreasePaddingBottom(event, button) { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); - if(currentBlockIndex < 0){ + if (currentBlockIndex < 0) { return; } const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex); - if (!currentBlock){ + if (!currentBlock) { return; } @@ -538,13 +538,13 @@ export default class SpacingTune { const paddingClass = new RegExp(/\pb-.+?\b/, 'g'); if (currentBlockElement.className.match(paddingClass)) { currentBlockElement.classList.forEach( cn => { - if(cn.match(paddingClass)){ + if (cn.match(paddingClass)) { className = cn; } }); let parts = className.split('-'); let padding = parseInt(parts[1]); - if(padding >= 1){ + if (padding >= 1) { currentBlockElement.classList.remove('pb-'+padding); padding = padding - 1; currentBlockElement.classList.add('pb-'+padding); diff --git a/frappe/public/scss/desk/wiki.scss b/frappe/public/scss/desk/wiki.scss index a04fb1e501..8c464a7a48 100644 --- a/frappe/public/scss/desk/wiki.scss +++ b/frappe/public/scss/desk/wiki.scss @@ -11,6 +11,28 @@ } } } + + .standard-sidebar-item { + justify-content: space-between; + } + + .sidebar-child-item-container { + margin-left: 10px; + + .standard-sidebar-item { + justify-content: start; + } + } + + .sidebar-item-label { + flex: 1; + } + + .item-anchor { + display: flex; + overflow: hidden; + flex: 1; + } } .ce-header { @@ -124,31 +146,4 @@ height: 145px; box-shadow: 0 3px 15px -3px rgba(13,20,33,.13); border-radius: 0 4px 4px 0;z-index: 0; -} - - -[data-page-route="wiki"] { - - .standard-sidebar-item { - justify-content: space-between; - } - - .sidebar-child-item-container { - margin-left: 10px; - - .standard-sidebar-item { - justify-content: start; - } - } - - .sidebar-item-label { - flex: 1; - } - - .item-anchor { - display: flex; - overflow: hidden; - flex: 1; - } - } \ No newline at end of file From 85f849d3e9d7303815a760a2296bf2374098e738 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 12 May 2021 14:39:11 +0530 Subject: [PATCH 054/868] fix: sider fix --- frappe/public/js/frappe/wiki_blocks/blank.js | 20 +++++++++---------- frappe/public/js/frappe/wiki_blocks/card.js | 20 +++++++++---------- frappe/public/js/frappe/wiki_blocks/chart.js | 20 +++++++++---------- .../public/js/frappe/wiki_blocks/paragraph.js | 20 +++++++++---------- .../public/js/frappe/wiki_blocks/shortcut.js | 20 +++++++++---------- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/frappe/public/js/frappe/wiki_blocks/blank.js b/frappe/public/js/frappe/wiki_blocks/blank.js index f32007de6c..f23f2f6225 100644 --- a/frappe/public/js/frappe/wiki_blocks/blank.js +++ b/frappe/public/js/frappe/wiki_blocks/blank.js @@ -53,9 +53,9 @@ export default class Blank { _getCol() { var e = 12; - t = "col-12"; - n = this.wrapper.parentNode.parentNode; - r = new RegExp(/\bcol-.+?\b/, "g"); + var t = "col-12"; + var n = this.wrapper.parentNode.parentNode; + var r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { e.match(r) && (t = e); @@ -68,13 +68,13 @@ export default class Blank { _getPadding() { var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - t = 0; - n = "p" + e + "-0"; - r = this.wrapper.parentNode.parentNode; - a = new RegExp(/\pl-.+?\b/, "g"); - i = new RegExp(/\pr-.+?\b/, "g"); - o = new RegExp(/\pt-.+?\b/, "g"); - c = new RegExp(/\pb-.+?\b/, "g"); + var t = 0; + var n = "p" + e + "-0"; + var r = this.wrapper.parentNode.parentNode; + var a = new RegExp(/\pl-.+?\b/, "g"); + var i = new RegExp(/\pr-.+?\b/, "g"); + var o = new RegExp(/\pt-.+?\b/, "g"); + var c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { r.classList.forEach(function (e) { diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index dd457fea4c..3e7fd54dfd 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -89,9 +89,9 @@ export default class Card { _getCol() { var e = 12; - t = "col-12"; - n = this.wrapper.parentNode.parentNode; - r = new RegExp(/\bcol-.+?\b/, "g"); + var t = "col-12"; + var n = this.wrapper.parentNode.parentNode; + var r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { e.match(r) && (t = e); @@ -104,13 +104,13 @@ export default class Card { _getPadding() { var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - t = 0; - n = "p" + e + "-0"; - r = this.wrapper.parentNode.parentNode; - a = new RegExp(/\pl-.+?\b/, "g"); - i = new RegExp(/\pr-.+?\b/, "g"); - o = new RegExp(/\pt-.+?\b/, "g"); - c = new RegExp(/\pb-.+?\b/, "g"); + var t = 0; + var n = "p" + e + "-0"; + var r = this.wrapper.parentNode.parentNode; + var a = new RegExp(/\pl-.+?\b/, "g"); + var i = new RegExp(/\pr-.+?\b/, "g"); + var o = new RegExp(/\pt-.+?\b/, "g"); + var c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { r.classList.forEach(function (e) { diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index 5acaa81627..1d637ef5b6 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -66,9 +66,9 @@ export default class Chart { _getCol() { var e = 12; - t = "col-12"; - n = this.wrapper.parentNode.parentNode; - r = new RegExp(/\bcol-.+?\b/, "g"); + var t = "col-12"; + var n = this.wrapper.parentNode.parentNode; + var r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { e.match(r) && (t = e); @@ -81,13 +81,13 @@ export default class Chart { _getPadding() { var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - t = 0; - n = "p" + e + "-0"; - r = this.wrapper.parentNode.parentNode; - a = new RegExp(/\pl-.+?\b/, "g"); - i = new RegExp(/\pr-.+?\b/, "g"); - o = new RegExp(/\pt-.+?\b/, "g"); - c = new RegExp(/\pb-.+?\b/, "g"); + var t = 0; + var n = "p" + e + "-0"; + var r = this.wrapper.parentNode.parentNode; + var a = new RegExp(/\pl-.+?\b/, "g"); + var i = new RegExp(/\pr-.+?\b/, "g"); + var o = new RegExp(/\pt-.+?\b/, "g"); + var c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { r.classList.forEach(function (e) { diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index affc2b436d..e80d300ec3 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -98,9 +98,9 @@ export default class Paragraph { _getCol() { var e = 12; - t = "col-12"; - n = this._element.parentNode.parentNode; - r = new RegExp(/\bcol-.+?\b/, "g"); + var t = "col-12"; + var n = this._element.parentNode.parentNode; + var r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { e.match(r) && (t = e); @@ -113,13 +113,13 @@ export default class Paragraph { _getPadding() { var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - t = 0; - n = "p" + e + "-0"; - r = this._element.parentNode.parentNode; - a = new RegExp(/\pl-.+?\b/, "g"); - i = new RegExp(/\pr-.+?\b/, "g"); - o = new RegExp(/\pt-.+?\b/, "g"); - c = new RegExp(/\pb-.+?\b/, "g"); + var t = 0; + var n = "p" + e + "-0"; + var r = this._element.parentNode.parentNode; + var a = new RegExp(/\pl-.+?\b/, "g"); + var i = new RegExp(/\pr-.+?\b/, "g"); + var o = new RegExp(/\pt-.+?\b/, "g"); + var c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { r.classList.forEach(function (e) { diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index 7bcebb478a..53b5a5eed5 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -88,9 +88,9 @@ export default class Shortcut { _getCol() { var e = 12; - t = "col-12"; - n = this.wrapper.parentNode.parentNode; - r = new RegExp(/\bcol-.+?\b/, "g"); + var t = "col-12"; + var n = this.wrapper.parentNode.parentNode; + var r = new RegExp(/\bcol-.+?\b/, "g"); if (n.className.match(r)) { n.classList.forEach(function (e) { e.match(r) && (t = e); @@ -103,13 +103,13 @@ export default class Shortcut { _getPadding() { var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - t = 0; - n = "p" + e + "-0"; - r = this.wrapper.parentNode.parentNode; - a = new RegExp(/\pl-.+?\b/, "g"); - i = new RegExp(/\pr-.+?\b/, "g"); - o = new RegExp(/\pt-.+?\b/, "g"); - c = new RegExp(/\pb-.+?\b/, "g"); + var t = 0; + var n = "p" + e + "-0"; + var r = this.wrapper.parentNode.parentNode; + var a = new RegExp(/\pl-.+?\b/, "g"); + var i = new RegExp(/\pr-.+?\b/, "g"); + var o = new RegExp(/\pt-.+?\b/, "g"); + var c = new RegExp(/\pb-.+?\b/, "g"); if ("l" == e) { if (r.className.match(a)) { r.classList.forEach(function (e) { From 31e087d1a9b1f90a5bb9b737ca51f078e8dc3f58 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 12 May 2021 14:58:41 +0530 Subject: [PATCH 055/868] fix: sider fix --- frappe/public/js/frappe/views/wiki.js | 6 +-- frappe/public/js/frappe/wiki_blocks/blank.js | 2 +- .../js/frappe/wiki_blocks/spacing_tune.js | 44 +++++++++---------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index a7c41b66bc..ec4f2a49e8 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -308,7 +308,7 @@ frappe.views.Wiki = class Wiki { onEnd: function (evt) { me.editor.blocks.move(evt.newIndex, evt.oldIndex); }, - setData: function (dataTransfer, dragEl) { + setData: function () { //Do Nothing } }); @@ -420,8 +420,8 @@ frappe.views.Wiki = class Wiki { outputData.blocks.forEach(item => { if (item.data.new) { if (!new_widgets[item.type]) { - new_widgets[item.type] = [] - }; + new_widgets[item.type] = []; + } new_widgets[item.type].push(item.data.new); delete item.data['new']; } diff --git a/frappe/public/js/frappe/wiki_blocks/blank.js b/frappe/public/js/frappe/wiki_blocks/blank.js index f23f2f6225..761bd2d9e9 100644 --- a/frappe/public/js/frappe/wiki_blocks/blank.js +++ b/frappe/public/js/frappe/wiki_blocks/blank.js @@ -32,7 +32,7 @@ export default class Blank { return this.wrapper; } - save(blockContent) { + save() { return { col: this._getCol(), pt: this._getPadding("t"), diff --git a/frappe/public/js/frappe/wiki_blocks/spacing_tune.js b/frappe/public/js/frappe/wiki_blocks/spacing_tune.js index ee76503097..1cf6891071 100644 --- a/frappe/public/js/frappe/wiki_blocks/spacing_tune.js +++ b/frappe/public/js/frappe/wiki_blocks/spacing_tune.js @@ -37,7 +37,7 @@ export default class SpacingTune { this.api.listeners.on( paddingButton, 'click', - (event) => me.showPadding(event, paddingButton), + () => me.showPadding(paddingButton), false ); @@ -46,7 +46,7 @@ export default class SpacingTune { this.api.listeners.on( decreaseWidthButton, 'click', - (event) => me.decreaseWidth(event, decreaseWidthButton), + () => me.decreaseWidth(), false ); @@ -55,7 +55,7 @@ export default class SpacingTune { this.api.listeners.on( increaseWidthButton, 'click', - (event) => me.increaseWidth(event, increaseWidthButton), + () => me.increaseWidth(), false ); @@ -63,7 +63,7 @@ export default class SpacingTune { return layoutWrapper; } - decreaseWidth(event, button) { + decreaseWidth() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -96,7 +96,7 @@ export default class SpacingTune { } } - increaseWidth(event, button) { + increaseWidth() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -129,7 +129,7 @@ export default class SpacingTune { } } - showPadding(event, button) { + showPadding(button) { let me = this; if (button.classList.contains('cdx-settings-button--active')) { this.sidebar.remove(); @@ -195,7 +195,7 @@ export default class SpacingTune { this.api.listeners.on( increasePaddingLeft, 'click', - (event) => me.increasePaddingLeft(event, increasePaddingLeft), + () => me.increasePaddingLeft(), false ); sidebarWrapper.appendChild(increasePaddingLeft); @@ -206,7 +206,7 @@ export default class SpacingTune { this.api.listeners.on( decreasePaddingLeft, 'click', - (event) => me.decreasePaddingLeft(event, decreasePaddingLeft), + () => me.decreasePaddingLeft(), false ); sidebarWrapper.appendChild(decreasePaddingLeft); @@ -219,7 +219,7 @@ export default class SpacingTune { this.api.listeners.on( increasePaddingRight, 'click', - (event) => me.increasePaddingRight(event, increasePaddingRight), + () => me.increasePaddingRight(), false ); sidebarWrapper.appendChild(increasePaddingRight); @@ -230,7 +230,7 @@ export default class SpacingTune { this.api.listeners.on( decreasePaddingRight, 'click', - (event) => me.decreasePaddingRight(event, decreasePaddingRight), + () => me.decreasePaddingRight(), false ); sidebarWrapper.appendChild(decreasePaddingRight); @@ -243,7 +243,7 @@ export default class SpacingTune { this.api.listeners.on( increasePaddingTop, 'click', - (event) => me.increasePaddingTop(event, increasePaddingTop), + () => me.increasePaddingTop(), false ); sidebarWrapper.appendChild(increasePaddingTop); @@ -254,7 +254,7 @@ export default class SpacingTune { this.api.listeners.on( decreasePaddingTop, 'click', - (event) => me.decreasePaddingTop(event, decreasePaddingTop), + () => me.decreasePaddingTop(), false ); sidebarWrapper.appendChild(decreasePaddingTop); @@ -267,7 +267,7 @@ export default class SpacingTune { this.api.listeners.on( increasePaddingBottom, 'click', - (event) => me.increasePaddingBottom(event, increasePaddingBottom), + () => me.increasePaddingBottom(), false ); sidebarWrapper.appendChild(increasePaddingBottom); @@ -278,7 +278,7 @@ export default class SpacingTune { this.api.listeners.on( decreasePaddingBottom, 'click', - (event) => me.decreasePaddingBottom(event, decreasePaddingBottom), + () => me.decreasePaddingBottom(), false ); sidebarWrapper.appendChild(decreasePaddingBottom); @@ -287,7 +287,7 @@ export default class SpacingTune { } } - increasePaddingLeft(event, button) { + increasePaddingLeft() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -321,7 +321,7 @@ export default class SpacingTune { } - decreasePaddingLeft(event, button) { + decreasePaddingLeft() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -354,7 +354,7 @@ export default class SpacingTune { } } - increasePaddingRight(event, button) { + increasePaddingRight() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -387,7 +387,7 @@ export default class SpacingTune { } } - decreasePaddingRight(event, button) { + decreasePaddingRight() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -420,7 +420,7 @@ export default class SpacingTune { } } - increasePaddingTop(event, button) { + increasePaddingTop() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -453,7 +453,7 @@ export default class SpacingTune { } } - decreasePaddingTop(event, button) { + decreasePaddingTop() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -486,7 +486,7 @@ export default class SpacingTune { } } - increasePaddingBottom(event, button) { + increasePaddingBottom() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { @@ -519,7 +519,7 @@ export default class SpacingTune { } } - decreasePaddingBottom(event, button) { + decreasePaddingBottom() { const currentBlockIndex = this.api.blocks.getCurrentBlockIndex(); if (currentBlockIndex < 0) { From c822c54f558383f2f7c92a688d3db8b198aa2bb8 Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Wed, 12 May 2021 17:03:25 +0530 Subject: [PATCH 056/868] fix: allow updating naming series --- .../document_naming_rule.js | 41 +++++++++++++++++++ .../document_naming_rule.py | 5 +++ 2 files changed, 46 insertions(+) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 56b5c2fdf4..dcb60cd7d5 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -4,6 +4,7 @@ frappe.ui.form.on('Document Naming Rule', { refresh: function(frm) { frm.trigger('document_type'); + frm.trigger("add_button") }, document_type: (frm) => { // update the select field options with fieldnames @@ -20,5 +21,45 @@ frappe.ui.form.on('Document Naming Rule', { ); }); } + }, + add_button: (frm) => { + frm.add_custom_button(__('Update Counter'), function() { + + const fields = [{ + fieldtype: 'Data', + fieldname: 'new_counter', + label: __('New Counter'), + default: frm.doc.counter, + reqd: 1, + description: __('This will update the counter and will affect all documents that will be created') + }] + + let primary_action_label = __('Save'); + + let primary_action = (fields) => { + debugger + frappe.call({ + method: 'frappe.core.doctype.document_naming_rule.document_naming_rule.update_current', + args: { + name: frm.doc.name, + new_counter: fields.new_counter + }, + callback: function() { + frm.set_value("counter", fields.new_counter) + dialog.hide() + } + }) + }; + + var dialog = new frappe.ui.Dialog({ + title: __('Update Counter Value for Prefix: ' + frm.doc.prefix), + fields, + primary_action_label, + primary_action + }); + + dialog.show() + + }); } }); diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.py b/frappe/core/doctype/document_naming_rule/document_naming_rule.py index 4b34293af6..13d54dffdd 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.py @@ -30,3 +30,8 @@ class DocumentNamingRule(Document): counter = frappe.db.get_value(self.doctype, self.name, 'counter', for_update=True) or 0 doc.name = self.prefix + ('%0'+str(self.prefix_digits)+'d') % (counter + 1) frappe.db.set_value(self.doctype, self.name, 'counter', counter + 1) + +@frappe.whitelist() +def update_current(name, new_counter): + frappe.db.set_value('Document Naming Rule', name, 'counter', new_counter) + frappe.db.commit() From c246c82a85d8a83fc71193905bf75febef89634a Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Wed, 12 May 2021 17:10:35 +0530 Subject: [PATCH 057/868] fix: remove debugger --- frappe/core/doctype/document_naming_rule/document_naming_rule.js | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index dcb60cd7d5..5d1540588d 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -37,7 +37,6 @@ frappe.ui.form.on('Document Naming Rule', { let primary_action_label = __('Save'); let primary_action = (fields) => { - debugger frappe.call({ method: 'frappe.core.doctype.document_naming_rule.document_naming_rule.update_current', args: { From bb4be327511eb7f736282fee6eaf5ee6d88ebc7a Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Wed, 12 May 2021 17:15:18 +0530 Subject: [PATCH 058/868] chore: add semicolons --- .../document_naming_rule/document_naming_rule.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 5d1540588d..e837ca2d6c 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Document Naming Rule', { refresh: function(frm) { frm.trigger('document_type'); - frm.trigger("add_button") + frm.trigger("add_button"); }, document_type: (frm) => { // update the select field options with fieldnames @@ -32,7 +32,7 @@ frappe.ui.form.on('Document Naming Rule', { default: frm.doc.counter, reqd: 1, description: __('This will update the counter and will affect all documents that will be created') - }] + }]; let primary_action_label = __('Save'); @@ -44,10 +44,10 @@ frappe.ui.form.on('Document Naming Rule', { new_counter: fields.new_counter }, callback: function() { - frm.set_value("counter", fields.new_counter) - dialog.hide() + frm.set_value("counter", fields.new_counter); + dialog.hide(); } - }) + }); }; var dialog = new frappe.ui.Dialog({ @@ -57,7 +57,7 @@ frappe.ui.form.on('Document Naming Rule', { primary_action }); - dialog.show() + dialog.show(); }); } From 788c511274eda1e9ac452e739a83ecc16f4cdf98 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 12 May 2021 17:47:55 +0530 Subject: [PATCH 059/868] fix: Delete Card and Shortcut --- frappe/public/js/frappe/widgets/widget_group.js | 13 ++++++++----- frappe/public/js/frappe/wiki_blocks/card.js | 10 +++++++--- frappe/public/js/frappe/wiki_blocks/shortcut.js | 12 ++++++++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 3d97a8f778..2b85359330 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -205,18 +205,21 @@ export class SingleWidgetGroup { widget_type: this.type, container: this.container, height: this.height || null, - options: { - ...this.options, - on_delete: (name) => this.on_delete(name), - }, }); - + widget_object.options = { + ...this.options, + on_delete: (name) => this.on_delete(name) + }; this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; return widget_object; } + on_delete(name, setup_new) { + this.api.blocks.delete(); + } + customize() { this.widgets_list.forEach((wid) => { wid.customize(this.options); diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index 3e7fd54dfd..f06e4754e0 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -73,9 +73,12 @@ export default class Card { let wid = frappe.widget.make_widget({ ...widget, widget_type: 'links', - container: this.wrapper, - options: this.options, + container: this.wrapper }); + wid.options = { + ...this.options, + on_delete: () => this.api.blocks.delete() + } wid.customize(this.options); this.wrapper.setAttribute("card_name", wid.label); this.new_card_widget = wid.get_config(); @@ -163,7 +166,8 @@ export default class Card { container: this.wrapper, type: "links", options: this.options, - widgets: card + widgets: card, + api: this.api }); this.wrapper.setAttribute("card_name", card_name); if (!this.readOnly) { diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index 53b5a5eed5..138ff8eac7 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -27,7 +27,7 @@ export default class Shortcut { allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, - allow_edit: true, + allow_edit: true }; } @@ -72,9 +72,12 @@ export default class Shortcut { let wid = frappe.widget.make_widget({ ...widget, widget_type: 'shortcut', - container: this.wrapper, - options: this.options, + container: this.wrapper }); + wid.options = { + ...this.options, + on_delete: () => this.api.blocks.delete(), + } wid.customize(this.options); this.wrapper.setAttribute("shortcut_name", wid.label); this.new_shortcut_widget = wid.get_config(); @@ -162,7 +165,8 @@ export default class Shortcut { container: this.wrapper, type: "shortcut", options: this.options, - widgets: shortcut + widgets: shortcut, + api: this.api }); this.wrapper.setAttribute("shortcut_name", shortcut_name); if (!this.readOnly) { From 4754ab71d1cf3099b66b63bf77a770a16c64736f Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sun, 9 May 2021 19:44:58 +0530 Subject: [PATCH 060/868] perf(minor): remove unnecessary comprehensions - remove several unnecessary comprehensions from functions that accept a generator. - Using `[x for x in iter]` causes a list to be built first then passed to the outer function. - `any` and `all` can take generator instead. This makes memory usage O(1) and actually makes these functions short-circuiting. E.g. if the first condition fails then `all` will immediately return false instead of evaluating all the entries. - `sum`, `min`, `max` => memory usage become O(1) - `list`, `set`, `.join()` => roughly halves memory usage, as list is not required to be built. - lastly, it's two fewer characters to read/think about. --- frappe/automation/doctype/auto_repeat/auto_repeat.py | 2 +- frappe/contacts/address_and_contact.py | 2 +- frappe/contacts/doctype/address/address.py | 2 +- frappe/core/doctype/data_import/importer.py | 12 ++++++------ frappe/core/doctype/data_import_legacy/importer.py | 4 ++-- frappe/core/doctype/doctype/doctype.py | 6 +++--- frappe/core/doctype/domain/domain.py | 4 ++-- frappe/core/doctype/user/user.py | 2 +- frappe/core/doctype/user_type/user_type.py | 2 +- .../custom/doctype/customize_form/customize_form.py | 2 +- frappe/database/database.py | 4 ++-- .../global_search_settings/global_search_settings.py | 4 ++-- frappe/desk/doctype/tag/tag.py | 2 +- frappe/email/doctype/email_account/email_account.py | 6 +++--- frappe/email/doctype/newsletter/test_newsletter.py | 2 +- frappe/email/inbox.py | 2 +- frappe/installer.py | 2 +- .../doctype/ldap_settings/ldap_settings.py | 2 +- frappe/model/__init__.py | 4 ++-- frappe/model/base_document.py | 4 ++-- frappe/model/db_query.py | 10 +++++----- frappe/model/meta.py | 2 +- frappe/model/rename_doc.py | 2 +- frappe/permissions.py | 2 +- frappe/tests/test_commands.py | 8 ++++---- frappe/translate.py | 4 ++-- frappe/utils/__init__.py | 4 ++-- frappe/utils/backups.py | 6 +++--- frappe/utils/bot.py | 8 ++++---- frappe/utils/jinja_globals.py | 4 ++-- frappe/website/doctype/web_form/web_form.py | 2 +- .../doctype/website_slideshow/website_slideshow.py | 2 +- 32 files changed, 62 insertions(+), 62 deletions(-) diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py index bf05baf5b6..37285ad571 100644 --- a/frappe/automation/doctype/auto_repeat/auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py @@ -334,7 +334,7 @@ class AutoRepeat(Document): if self.reference_doctype and self.reference_document: res = get_contacts_linking_to(self.reference_doctype, self.reference_document, fields=['email_id']) res += get_contacts_linked_from(self.reference_doctype, self.reference_document, fields=['email_id']) - email_ids = list(set([d.email_id for d in res])) + email_ids = set(d.email_id for d in res) if not email_ids: frappe.msgprint(_('No contacts linked to document'), alert=True) else: diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 3ca9547188..43aa39f678 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -154,7 +154,7 @@ def filter_dynamic_link_doctypes(doctype, txt, searchfield, start, page_len, fil doctypes = frappe.db.get_all("DocField", filters=filters, fields=["parent"], distinct=True, as_list=True) - doctypes = tuple([d for d in doctypes if re.search(txt+".*", _(d[0]), re.IGNORECASE)]) + doctypes = tuple(d for d in doctypes if re.search(txt+".*", _(d[0]), re.IGNORECASE)) filters.update({ "dt": ("not in", [d[0] for d in doctypes]) diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index 84b925d50e..a6fd7b1755 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -263,7 +263,7 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): def get_condensed_address(doc): fields = ["address_title", "address_line1", "address_line2", "city", "county", "state", "country"] - return ", ".join([doc.get(d) for d in fields if doc.get(d)]) + return ", ".join(doc.get(d) for d in fields if doc.get(d)) def update_preferred_address(address, field): frappe.db.set_value('Address', address, field, 0) diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 720fe1dda7..841319dd60 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -450,7 +450,7 @@ class ImportFile: for row in data_without_first_row: row_values = row.get_values(parent_column_indexes) # if the row is blank, it's a child row doc - if all([v in INVALID_VALUES for v in row_values]): + if all(v in INVALID_VALUES for v in row_values): rows.append(row) continue # if we encounter a row which has values in parent columns, @@ -607,7 +607,7 @@ class Row: if df.fieldtype == "Select": select_options = get_select_options(df) if select_options and value not in select_options: - options_string = ", ".join([frappe.bold(d) for d in select_options]) + options_string = ", ".join(frappe.bold(d) for d in select_options) msg = _("Value must be one of {0}").format(options_string) self.warnings.append( {"row": self.row_number, "field": df_as_json(df), "message": msg,} @@ -903,7 +903,7 @@ class Column: if self.df.fieldtype == "Link": # find all values that dont exist - values = list(set([cstr(v) for v in self.column_values[1:] if v])) + values = list(set(cstr(v) for v in self.column_values[1:] if v)) exists = [ d.name for d in frappe.db.get_all(self.df.options, filters={"name": ("in", values)}) ] @@ -939,11 +939,11 @@ class Column: elif self.df.fieldtype == "Select": options = get_select_options(self.df) if options: - values = list(set([cstr(v) for v in self.column_values[1:] if v])) + values = list(set(cstr(v) for v in self.column_values[1:] if v)) invalid = list(set(values) - set(options)) if invalid: - valid_values = ", ".join([frappe.bold(o) for o in options]) - invalid_values = ", ".join([frappe.bold(i) for i in invalid]) + valid_values = ", ".join(frappe.bold(o) for o in options) + invalid_values = ", ".join(frappe.bold(i) for i in invalid) self.warnings.append( { "col": self.column_number, diff --git a/frappe/core/doctype/data_import_legacy/importer.py b/frappe/core/doctype/data_import_legacy/importer.py index 35569c7186..b4be57be4f 100644 --- a/frappe/core/doctype/data_import_legacy/importer.py +++ b/frappe/core/doctype/data_import_legacy/importer.py @@ -181,7 +181,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, if d.get("name") and d["name"].startswith('"'): d["name"] = d["name"][1:-1] - if sum([0 if not val else 1 for val in d.values()]): + if sum(0 if not val else 1 for val in d.values()): d['doctype'] = dt if dt == doctype: doc.update(d) @@ -537,6 +537,6 @@ def get_parent_field(doctype, parenttype): def delete_child_rows(rows, doctype): """delete child rows for all parents""" - for p in list(set([r[1] for r in rows])): + for p in list(set(r[1] for r in rows)): if p: frappe.db.sql("""delete from `tab{0}` where parent=%s""".format(doctype), p) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index aff07836c0..582c5d3d89 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -196,7 +196,7 @@ class DocType(Document): self.flags.update_fields_to_fetch_queries = [] - if set(old_fields_to_fetch) != set([df.fieldname for df in new_meta.get_fields_to_fetch()]): + if set(old_fields_to_fetch) != set(df.fieldname for df in new_meta.get_fields_to_fetch()): for df in new_meta.get_fields_to_fetch(): if df.fieldname not in old_fields_to_fetch: link_fieldname, source_fieldname = df.fetch_from.split('.', 1) @@ -765,7 +765,7 @@ def validate_fields(meta): invalid_fields = ('doctype',) if fieldname in invalid_fields: frappe.throw(_("{0}: Fieldname cannot be one of {1}") - .format(docname, ", ".join([frappe.bold(d) for d in invalid_fields]))) + .format(docname, ", ".join(frappe.bold(d) for d in invalid_fields))) def check_unique_fieldname(docname, fieldname): duplicates = list(filter(None, map(lambda df: df.fieldname==fieldname and str(df.idx) or None, fields))) @@ -999,7 +999,7 @@ def validate_fields(meta): if docfield.options and (docfield.options not in data_field_options): df_str = frappe.bold(_(docfield.label)) text_str = _("{0} is an invalid Data field.").format(df_str) + "
" * 2 + _("Only Options allowed for Data field are:") + "
" - df_options_str = "
  • " + "
  • ".join([_(x) for x in data_field_options]) + "
" + df_options_str = "
  • " + "
  • ".join(_(x) for x in data_field_options) + "
" frappe.msgprint(text_str + df_options_str, title="Invalid Data Field", raise_exception=True) diff --git a/frappe/core/doctype/domain/domain.py b/frappe/core/doctype/domain/domain.py index a4e9f503ab..4f320578fb 100644 --- a/frappe/core/doctype/domain/domain.py +++ b/frappe/core/doctype/domain/domain.py @@ -111,7 +111,7 @@ class Domain(Document): # enable frappe.db.sql('''update `tabPortal Menu Item` set enabled=1 - where route in ({0})'''.format(', '.join(['"{0}"'.format(d) for d in self.data.allow_sidebar_items]))) + where route in ({0})'''.format(', '.join('"{0}"'.format(d) for d in self.data.allow_sidebar_items))) if self.data.remove_sidebar_items: # disable all @@ -119,4 +119,4 @@ class Domain(Document): # enable frappe.db.sql('''update `tabPortal Menu Item` set enabled=0 - where route in ({0})'''.format(', '.join(['"{0}"'.format(d) for d in self.data.remove_sidebar_items]))) + where route in ({0})'''.format(', '.join('"{0}"'.format(d) for d in self.data.remove_sidebar_items))) diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index a4d13a57e0..979a300a4d 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -935,7 +935,7 @@ def user_query(doctype, txt, searchfield, start, page_len, filters): LIMIT %(page_len)s OFFSET %(start)s """.format( user_type_condition = user_type_condition, - standard_users=", ".join([frappe.db.escape(u) for u in STANDARD_USERS]), + standard_users=", ".join(frappe.db.escape(u) for u in STANDARD_USERS), key=searchfield, fcond=get_filters_cond(doctype, filters, conditions), mcond=get_match_cond(doctype) diff --git a/frappe/core/doctype/user_type/user_type.py b/frappe/core/doctype/user_type/user_type.py index 0e8b692416..b3965d9b84 100644 --- a/frappe/core/doctype/user_type/user_type.py +++ b/frappe/core/doctype/user_type/user_type.py @@ -114,7 +114,7 @@ class UserType(Document): self.select_doctypes = [] select_doctypes = [] - user_doctypes = tuple([row.document_type for row in self.user_doctypes]) + user_doctypes = tuple(row.document_type for row in self.user_doctypes) for doctype in user_doctypes: doc = frappe.get_meta(doctype) diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index be0dded99c..17fd8ada05 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -356,7 +356,7 @@ class CustomizeForm(Document): def delete_custom_fields(self): meta = frappe.get_meta(self.doc_type) - fields_to_remove = (set([df.fieldname for df in meta.get("fields")]) + fields_to_remove = (set(df.fieldname for df in meta.get("fields")) - set(df.fieldname for df in self.get("fields"))) for fieldname in fields_to_remove: diff --git a/frappe/database/database.py b/frappe/database/database.py index c9c1ec3909..9ff3d25320 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -344,7 +344,7 @@ class Database(object): values[key] = value[1] if isinstance(value[1], (tuple, list)): # value is a list in tuple ("in", ("A", "B")) - _rhs = " ({0})".format(", ".join([self.escape(v) for v in value[1]])) + _rhs = " ({0})".format(", ".join(self.escape(v) for v in value[1])) del values[key] if _operator not in ["=", "!=", ">", ">=", "<", "<=", "like", "in", "not in", "not like"]: @@ -1019,7 +1019,7 @@ class Database(object): :params values: list of list of values """ insert_list = [] - fields = ", ".join(["`"+field+"`" for field in fields]) + fields = ", ".join("`"+field+"`" for field in fields) for idx, value in enumerate(values): insert_list.append(tuple(value)) diff --git a/frappe/desk/doctype/global_search_settings/global_search_settings.py b/frappe/desk/doctype/global_search_settings/global_search_settings.py index 85c9687ab3..f483376ed0 100644 --- a/frappe/desk/doctype/global_search_settings/global_search_settings.py +++ b/frappe/desk/doctype/global_search_settings/global_search_settings.py @@ -22,7 +22,7 @@ class GlobalSearchSettings(Document): dts.append(dt.document_type) if core_dts: - core_dts = (", ".join([frappe.bold(dt) for dt in core_dts])) + core_dts = (", ".join(frappe.bold(dt) for dt in core_dts)) frappe.throw(_("Core Modules {0} cannot be searched in Global Search.").format(core_dts)) if repeated_dts: @@ -61,7 +61,7 @@ def update_global_search_doctypes(): if search_doctypes.get(domain): global_search_doctypes.extend(search_doctypes.get(domain)) - doctype_list = set([dt.name for dt in frappe.get_all("DocType")]) + doctype_list = set(dt.name for dt in frappe.get_all("DocType")) allowed_in_global_search = [] for dt in global_search_doctypes: diff --git a/frappe/desk/doctype/tag/tag.py b/frappe/desk/doctype/tag/tag.py index 7e016ee91b..3ec3f05ac0 100644 --- a/frappe/desk/doctype/tag/tag.py +++ b/frappe/desk/doctype/tag/tag.py @@ -132,7 +132,7 @@ def update_tags(doc, tags): :param doc: Document to be added to global tags """ - new_tags = list(set([tag.strip() for tag in tags.split(",") if tag])) + new_tags = list(set(tag.strip() for tag in tags.split(",") if tag)) for tag in new_tags: if not frappe.db.exists("Tag Link", {"parenttype": doc.doctype, "parent": doc.name, "tag": tag}): diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 36b662bb39..769dd57481 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -594,7 +594,7 @@ class EmailAccount(Document): # get email account user and set communication as seen users = frappe.get_all("User Email", filters={ "email_account": self.name }, fields=["parent"]) - users = list(set([ user.get("parent") for user in users ])) + users = list(set(user.get("parent") for user in users)) communication._seen = json.dumps(users) communication.flags.in_receive = True @@ -851,8 +851,8 @@ class EmailAccount(Document): email_server.update_flag(uid_list=uid_list) # mark communication as read - docnames = ",".join([ "'%s'"%flag.get("communication") for flag in flags \ - if flag.get("action") == "Read" ]) + docnames = ",".join("'%s'"%flag.get("communication") for flag in flags \ + if flag.get("action") == "Read") self.set_communication_seen_status(docnames, seen=1) # mark communication as unread diff --git a/frappe/email/doctype/newsletter/test_newsletter.py b/frappe/email/doctype/newsletter/test_newsletter.py index bd8fadc29c..073b46af44 100644 --- a/frappe/email/doctype/newsletter/test_newsletter.py +++ b/frappe/email/doctype/newsletter/test_newsletter.py @@ -44,7 +44,7 @@ class TestNewsletter(unittest.TestCase): email_queue_list = [frappe.get_doc("Email Queue", e.name) for e in frappe.get_all("Email Queue")] self.assertEqual(len(email_queue_list), 4) - recipients = set([e.recipients[0].recipient for e in email_queue_list]) + recipients = set(e.recipients[0].recipient for e in email_queue_list) self.assertTrue(set(emails).issubset(recipients)) def test_unsubscribe(self): diff --git a/frappe/email/inbox.py b/frappe/email/inbox.py index 395a2d3e2d..08eef5f7bf 100644 --- a/frappe/email/inbox.py +++ b/frappe/email/inbox.py @@ -18,7 +18,7 @@ def get_email_accounts(user=None): "all_accounts": "" } - all_accounts = ",".join([ account.get("email_account") for account in accounts ]) + all_accounts = ",".join(account.get("email_account") for account in accounts) if len(accounts) > 1: email_accounts.append({ "email_account": all_accounts, diff --git a/frappe/installer.py b/frappe/installer.py index 0cd5b136ae..cc5a6a6734 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -540,7 +540,7 @@ def is_downgrade(sql_file_path, verbose=False): def is_partial(sql_file_path): with open(sql_file_path) as f: - header = " ".join([f.readline() for _ in range(5)]) + header = " ".join(f.readline() for _ in range(5)) if "Partial Backup" in header: return True return False diff --git a/frappe/integrations/doctype/ldap_settings/ldap_settings.py b/frappe/integrations/doctype/ldap_settings/ldap_settings.py index 80dfef2693..ef72d03cde 100644 --- a/frappe/integrations/doctype/ldap_settings/ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/ldap_settings.py @@ -80,7 +80,7 @@ class LDAPSettings(Document): def sync_roles(self, user, additional_groups=None): - current_roles = set([d.role for d in user.get("roles")]) + current_roles = set(d.role for d in user.get("roles")) needed_roles = set() needed_roles.add(self.default_role) diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index 205b451336..d9cbe7313e 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -166,7 +166,7 @@ def delete_fields(args_dict, delete=0): frappe.db.sql(""" DELETE FROM `tabSingles` WHERE doctype='%s' AND field IN (%s) - """ % (dt, ", ".join(["'{}'".format(f) for f in fields]))) + """ % (dt, ", ".join("'{}'".format(f) for f in fields))) else: existing_fields = frappe.db.multisql({ "mariadb": "DESC `tab%s`" % dt, @@ -189,7 +189,7 @@ def delete_fields(args_dict, delete=0): frappe.db.commit() query = "ALTER TABLE `tab%s` " % dt + \ - ", ".join(["DROP COLUMN `%s`" % f for f in fields_need_to_delete]) + ", ".join("DROP COLUMN `%s`" % f for f in fields_need_to_delete) frappe.db.sql(query) if frappe.db.db_type == 'postgres': diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 154a091b8a..34c329175a 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -358,7 +358,7 @@ class BaseDocument(object): frappe.db.sql("""INSERT INTO `tab{doctype}` ({columns}) VALUES ({values})""".format( doctype = self.doctype, - columns = ", ".join(["`"+c+"`" for c in columns]), + columns = ", ".join("`"+c+"`" for c in columns), values = ", ".join(["%s"] * len(columns)) ), list(d.values())) except Exception as e: @@ -401,7 +401,7 @@ class BaseDocument(object): frappe.db.sql("""UPDATE `tab{doctype}` SET {values} WHERE `name`=%s""".format( doctype = self.doctype, - values = ", ".join(["`"+c+"`=%s" for c in columns]) + values = ", ".join("`"+c+"`=%s" for c in columns) ), list(d.values()) + [name]) except Exception as e: if frappe.db.is_unique_key_violation(e): diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index e0c3406c46..8460880794 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -620,7 +620,7 @@ class DatabaseQuery(object): def get_share_condition(self): return """`tab{0}`.name in ({1})""".format(self.doctype, ", ".join(["%s"] * len(self.shared))) % \ - tuple([frappe.db.escape(s, percent=False) for s in self.shared]) + tuple(frappe.db.escape(s, percent=False) for s in self.shared) def add_user_permissions(self, user_permissions): meta = frappe.get_meta(self.doctype) @@ -726,8 +726,8 @@ class DatabaseQuery(object): # `idx desc, modified desc` # will covert to # `tabItem`.`idx` desc, `tabItem`.`modified` desc - args.order_by = ', '.join(['`tab{0}`.`{1}` {2}'.format(self.doctype, - f.split()[0].strip(), f.split()[1].strip()) for f in meta.sort_field.split(',')]) + args.order_by = ', '.join('`tab{0}`.`{1}` {2}'.format(self.doctype, + f.split()[0].strip(), f.split()[1].strip()) for f in meta.sort_field.split(',')) else: sort_field = meta.sort_field or 'modified' sort_order = (meta.sort_field and meta.sort_order) or 'desc' @@ -807,8 +807,8 @@ def get_order_by(doctype, meta): # `idx desc, modified desc` # will covert to # `tabItem`.`idx` desc, `tabItem`.`modified` desc - order_by = ', '.join(['`tab{0}`.`{1}` {2}'.format(doctype, - f.split()[0].strip(), f.split()[1].strip()) for f in meta.sort_field.split(',')]) + order_by = ', '.join('`tab{0}`.`{1}` {2}'.format(doctype, + f.split()[0].strip(), f.split()[1].strip()) for f in meta.sort_field.split(',')) else: sort_field = meta.sort_field or 'modified' sort_order = (meta.sort_field and meta.sort_order) or 'desc' diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 66e8b08d92..1c3e7f60fb 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -667,7 +667,7 @@ def trim_tables(doctype=None): and not f.startswith("_")] if columns_to_remove: print(doctype, "columns removed:", columns_to_remove) - columns_to_remove = ", ".join(["drop `{0}`".format(c) for c in columns_to_remove]) + columns_to_remove = ", ".join("drop `{0}`".format(c) for c in columns_to_remove) query = """alter table `tab{doctype}` {columns}""".format( doctype=doctype, columns=columns_to_remove) frappe.db.sql_ddl(query) diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 2c9dc5d823..1567ac544b 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -144,7 +144,7 @@ def update_user_settings(old, new, link_fields): if not link_fields: return # find the user settings for the linked doctypes - linked_doctypes = set([d.parent for d in link_fields if not d.issingle]) + linked_doctypes = set(d.parent for d in link_fields if not d.issingle) user_settings_details = frappe.db.sql('''SELECT `user`, `doctype`, `data` FROM `__UserSettings` WHERE `data` like %s diff --git a/frappe/permissions.py b/frappe/permissions.py index 19f101aab5..c0ff7fc590 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -312,7 +312,7 @@ def has_controller_permissions(doc, ptype, user=None): return None def get_doctypes_with_read(): - return list(set([p.parent if type(p.parent) == str else p.parent.encode('UTF8') for p in get_valid_perms()])) + return list(set(p.parent if type(p.parent) == str else p.parent.encode('UTF8') for p in get_valid_perms())) def get_valid_perms(doctype=None, user=None): '''Get valid permissions for the current user from DocPerm and Custom DocPerm''' diff --git a/frappe/tests/test_commands.py b/frappe/tests/test_commands.py index b6cd0b575c..07bdf8791e 100644 --- a/frappe/tests/test_commands.py +++ b/frappe/tests/test_commands.py @@ -80,7 +80,7 @@ def exists_in_backup(doctypes, file): ) with gzip.open(file, "rb") as f: content = f.read().decode("utf8") - return all([predicate.format(doctype).lower() in content.lower() for doctype in doctypes]) + return all(predicate.format(doctype).lower() in content.lower() for doctype in doctypes) class BaseTestCommands(unittest.TestCase): @@ -355,12 +355,12 @@ class TestCommands(BaseTestCommands): # test 2: bare functionality for single site self.execute("bench --site {site} list-apps") self.assertEqual(self.returncode, 0) - list_apps = set([ + list_apps = set( _x.split()[0] for _x in self.stdout.split("\n") - ]) + ) doctype = frappe.get_single("Installed Applications").installed_applications if doctype: - installed_apps = set([x.app_name for x in doctype]) + installed_apps = set(x.app_name for x in doctype) else: installed_apps = set(frappe.get_installed_apps()) self.assertSetEqual(list_apps, installed_apps) diff --git a/frappe/translate.py b/frappe/translate.py index 1d8b1234c7..caa7bcfea6 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -283,8 +283,8 @@ def clear_cache(): def get_messages_for_app(app, deduplicate=True): """Returns all messages (list) for a specified `app`""" messages = [] - modules = ", ".join(['"{}"'.format(m.title().replace("_", " ")) \ - for m in frappe.local.app_modules[app]]) + modules = ", ".join('"{}"'.format(m.title().replace("_", " ")) \ + for m in frappe.local.app_modules[app]) # doctypes if modules: diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 1da4cd3bae..db0f39b3f5 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -186,7 +186,7 @@ def random_string(length): """generate a random string""" import string from random import choice - return ''.join([choice(string.ascii_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,7 +305,7 @@ def make_esc(esc_chars): """ Function generator for Escaping special characters """ - return lambda s: ''.join(['\\' + c if c in esc_chars else c for c in s]) + return lambda s: ''.join('\\' + c if c in esc_chars else c for c in s) # esc / unescape characters -- used for command line def esc(s, esc_chars): diff --git a/frappe/utils/backups.py b/frappe/utils/backups.py index b21efc5e89..908be52452 100644 --- a/frappe/utils/backups.py +++ b/frappe/utils/backups.py @@ -307,8 +307,8 @@ class BackupGenerator: backup_summary = self.get_summary() print("Backup Summary for {0} at {1}".format(frappe.local.site, now())) - title = max([len(x) for x in backup_summary]) - path = max([len(x["path"]) for x in backup_summary.values()]) + title = max(len(x) for x in backup_summary) + path = max(len(x["path"]) for x in backup_summary.values()) for _type, info in backup_summary.items(): template = "{{0:{0}}}: {{1:{1}}} {{2}}".format(title, path) @@ -381,7 +381,7 @@ class BackupGenerator: "", ]) - generated_header = "\n".join([f"-- {x}" for x in database_header_content]) + "\n" + generated_header = "\n".join(f"-- {x}" for x in database_header_content) + "\n" with gzip.open(args.backup_path_db, "wt") as f: f.write(generated_header) diff --git a/frappe/utils/bot.py b/frappe/utils/bot.py index 45e1bd5a4e..68f49c47ed 100644 --- a/frappe/utils/bot.py +++ b/frappe/utils/bot.py @@ -40,10 +40,10 @@ class BotParser(object): def format_list(self, data): '''Format list as markdown''' - return _('I found these: ') + ', '.join([' [{title}](/app/Form/{doctype}/{name})'.format( + return _('I found these: ') + ', '.join(' [{title}](/app/Form/{doctype}/{name})'.format( title = d.title or d.name, doctype=self.get_doctype(), - name=d.name) for d in data]) + name=d.name) for d in data) def get_doctype(self): '''returns the doctype name from self.tables''' @@ -58,8 +58,8 @@ class ShowNotificationBot(BotParser): if open_items: return ("Following items need your attention:\n\n" - + "\n\n".join(["{0} [{1}](/app/List/{1})".format(d[1], d[0]) - for d in open_items if d[1] > 0])) + + "\n\n".join("{0} [{1}](/app/List/{1})".format(d[1], d[0]) + for d in open_items if d[1] > 0)) else: return 'Take it easy, nothing urgent needs your attention' diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py index d8c5cb79f1..8eedca5335 100644 --- a/frappe/utils/jinja_globals.py +++ b/frappe/utils/jinja_globals.py @@ -14,10 +14,10 @@ def resolve_class(classes): return classes if isinstance(classes, (list, tuple)): - return " ".join([resolve_class(c) for c in classes]).strip() + return " ".join(resolve_class(c) for c in classes).strip() if isinstance(classes, dict): - return " ".join([classname for classname in classes if classes[classname]]).strip() + return " ".join(classname for classname in classes if classes[classname]).strip() return classes diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index f78aaac934..5ff2165527 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -346,7 +346,7 @@ def get_context(context): if missing: frappe.throw(_('Mandatory Information missing:') + '

' - + '
'.join(['{0} ({1})'.format(d.label, d.fieldtype) for d in missing])) + + '
'.join('{0} ({1})'.format(d.label, d.fieldtype) for d in missing)) def allow_website_search_indexing(self): return False diff --git a/frappe/website/doctype/website_slideshow/website_slideshow.py b/frappe/website/doctype/website_slideshow/website_slideshow.py index 90f62d1bb1..03e26bdcfd 100644 --- a/frappe/website/doctype/website_slideshow/website_slideshow.py +++ b/frappe/website/doctype/website_slideshow/website_slideshow.py @@ -23,7 +23,7 @@ class WebsiteSlideshow(Document): files = map(lambda row: row.image, self.slideshow_items) if files: result = frappe.get_all("File", filters={ "file_url":("in", list(files)) }, fields="is_private") - if any([file.is_private for file in result]): + if any(file.is_private for file in result): frappe.throw(_("All Images attached to Website Slideshow should be public")) def get_slideshow(doc): From cbbc85424bd1ce715f813f4349b6a63211b74b96 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 12 May 2021 16:46:58 +0530 Subject: [PATCH 061/868] fix: use set instead of list for new_ags No dependent functionalities expect a list. Co-authored-by: gavin --- frappe/desk/doctype/tag/tag.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/desk/doctype/tag/tag.py b/frappe/desk/doctype/tag/tag.py index 3ec3f05ac0..a85b264cee 100644 --- a/frappe/desk/doctype/tag/tag.py +++ b/frappe/desk/doctype/tag/tag.py @@ -132,7 +132,7 @@ def update_tags(doc, tags): :param doc: Document to be added to global tags """ - new_tags = list(set(tag.strip() for tag in tags.split(",") if tag)) + new_tags = {tag.strip() for tag in tags.split(",") if tag} for tag in new_tags: if not frappe.db.exists("Tag Link", {"parenttype": doc.doctype, "parent": doc.name, "tag": tag}): @@ -187,4 +187,4 @@ def get_documents_for_tag(tag): @frappe.whitelist() def get_tags_list_for_awesomebar(): - return [t.name for t in frappe.get_list("Tag")] \ No newline at end of file + return [t.name for t in frappe.get_list("Tag")] From d8a4cf896b3eca5132d1e23d6da40491005a9f1b Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 12 May 2021 16:56:16 +0530 Subject: [PATCH 062/868] perf: prefer set builder notation over constructor --- frappe/automation/doctype/auto_repeat/auto_repeat.py | 2 +- frappe/core/doctype/data_import/importer.py | 4 ++-- .../doctype/global_search_settings/global_search_settings.py | 2 +- frappe/email/doctype/email_account/email_account.py | 2 +- frappe/email/doctype/newsletter/test_newsletter.py | 2 +- frappe/model/rename_doc.py | 2 +- frappe/permissions.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py index 37285ad571..dfad85d0dd 100644 --- a/frappe/automation/doctype/auto_repeat/auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py @@ -334,7 +334,7 @@ class AutoRepeat(Document): if self.reference_doctype and self.reference_document: res = get_contacts_linking_to(self.reference_doctype, self.reference_document, fields=['email_id']) res += get_contacts_linked_from(self.reference_doctype, self.reference_document, fields=['email_id']) - email_ids = set(d.email_id for d in res) + email_ids = {d.email_id for d in res} if not email_ids: frappe.msgprint(_('No contacts linked to document'), alert=True) else: diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 841319dd60..fed6d2cb06 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -903,7 +903,7 @@ class Column: if self.df.fieldtype == "Link": # find all values that dont exist - values = list(set(cstr(v) for v in self.column_values[1:] if v)) + values = list({cstr(v) for v in self.column_values[1:] if v}) exists = [ d.name for d in frappe.db.get_all(self.df.options, filters={"name": ("in", values)}) ] @@ -939,7 +939,7 @@ class Column: elif self.df.fieldtype == "Select": options = get_select_options(self.df) if options: - values = list(set(cstr(v) for v in self.column_values[1:] if v)) + values = list({cstr(v) for v in self.column_values[1:] if v}) invalid = list(set(values) - set(options)) if invalid: valid_values = ", ".join(frappe.bold(o) for o in options) diff --git a/frappe/desk/doctype/global_search_settings/global_search_settings.py b/frappe/desk/doctype/global_search_settings/global_search_settings.py index f483376ed0..fead118e75 100644 --- a/frappe/desk/doctype/global_search_settings/global_search_settings.py +++ b/frappe/desk/doctype/global_search_settings/global_search_settings.py @@ -61,7 +61,7 @@ def update_global_search_doctypes(): if search_doctypes.get(domain): global_search_doctypes.extend(search_doctypes.get(domain)) - doctype_list = set(dt.name for dt in frappe.get_all("DocType")) + doctype_list = {dt.name for dt in frappe.get_all("DocType")} allowed_in_global_search = [] for dt in global_search_doctypes: diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 769dd57481..786a185585 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -594,7 +594,7 @@ class EmailAccount(Document): # get email account user and set communication as seen users = frappe.get_all("User Email", filters={ "email_account": self.name }, fields=["parent"]) - users = list(set(user.get("parent") for user in users)) + users = list({user.get("parent") for user in users}) communication._seen = json.dumps(users) communication.flags.in_receive = True diff --git a/frappe/email/doctype/newsletter/test_newsletter.py b/frappe/email/doctype/newsletter/test_newsletter.py index 073b46af44..4b9a0749d5 100644 --- a/frappe/email/doctype/newsletter/test_newsletter.py +++ b/frappe/email/doctype/newsletter/test_newsletter.py @@ -44,7 +44,7 @@ class TestNewsletter(unittest.TestCase): email_queue_list = [frappe.get_doc("Email Queue", e.name) for e in frappe.get_all("Email Queue")] self.assertEqual(len(email_queue_list), 4) - recipients = set(e.recipients[0].recipient for e in email_queue_list) + recipients = {e.recipients[0].recipient for e in email_queue_list} self.assertTrue(set(emails).issubset(recipients)) def test_unsubscribe(self): diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 1567ac544b..2c2550f39d 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -144,7 +144,7 @@ def update_user_settings(old, new, link_fields): if not link_fields: return # find the user settings for the linked doctypes - linked_doctypes = set(d.parent for d in link_fields if not d.issingle) + linked_doctypes = {d.parent for d in link_fields if not d.issingle} user_settings_details = frappe.db.sql('''SELECT `user`, `doctype`, `data` FROM `__UserSettings` WHERE `data` like %s diff --git a/frappe/permissions.py b/frappe/permissions.py index c0ff7fc590..c17f4b6bf1 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -312,7 +312,7 @@ def has_controller_permissions(doc, ptype, user=None): return None def get_doctypes_with_read(): - return list(set(p.parent if type(p.parent) == str else p.parent.encode('UTF8') for p in get_valid_perms())) + return list({p.parent if type(p.parent) == str else p.parent.encode('UTF8') for p in get_valid_perms()}) def get_valid_perms(doctype=None, user=None): '''Get valid permissions for the current user from DocPerm and Custom DocPerm''' From 6d8c691dddc502baf160b28d05c1d5baa8da8e35 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 12 May 2021 19:22:31 +0530 Subject: [PATCH 063/868] refactor: use list instead of tuple constructor --- frappe/core/doctype/user_type/user_type.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/user_type/user_type.py b/frappe/core/doctype/user_type/user_type.py index b3965d9b84..b3e61610cc 100644 --- a/frappe/core/doctype/user_type/user_type.py +++ b/frappe/core/doctype/user_type/user_type.py @@ -114,7 +114,7 @@ class UserType(Document): self.select_doctypes = [] select_doctypes = [] - user_doctypes = tuple(row.document_type for row in self.user_doctypes) + user_doctypes = [row.document_type for row in self.user_doctypes] for doctype in user_doctypes: doc = frappe.get_meta(doctype) @@ -267,4 +267,4 @@ def apply_permissions_for_non_standard_user_type(doc, method=None): user_doc.update_children() add_user_permission(doc.doctype, doc.name, doc.get(data[1])) else: - frappe.db.set_value('User Permission', perm_data[0], 'user', doc.get(data[1])) \ No newline at end of file + frappe.db.set_value('User Permission', perm_data[0], 'user', doc.get(data[1])) From d7eea226094145a4d45e4fbc6a7ef8bdfe2fad55 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 12 May 2021 19:25:21 +0530 Subject: [PATCH 064/868] chore: misc translation/semgrep fixes --- frappe/core/doctype/data_import/importer.py | 5 +---- frappe/utils/bot.py | 2 +- frappe/utils/jinja_globals.py | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index fed6d2cb06..6337d919eb 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -929,10 +929,7 @@ class Column: self.warnings.append( { "col": self.column_number, - "message": _( - "Date format could not be determined from the values in" - " this column. Defaulting to yyyy-mm-dd." - ), + "message": _("Date format could not be determined from the values in this column. Defaulting to yyyy-mm-dd."), "type": "info", } ) diff --git a/frappe/utils/bot.py b/frappe/utils/bot.py index 68f49c47ed..33ec139b64 100644 --- a/frappe/utils/bot.py +++ b/frappe/utils/bot.py @@ -40,7 +40,7 @@ class BotParser(object): def format_list(self, data): '''Format list as markdown''' - return _('I found these: ') + ', '.join(' [{title}](/app/Form/{doctype}/{name})'.format( + return _('I found these:') + ' ' + ', '.join(' [{title}](/app/Form/{doctype}/{name})'.format( title = d.title or d.name, doctype=self.get_doctype(), name=d.name) for d in data) diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py index 8eedca5335..906d557326 100644 --- a/frappe/utils/jinja_globals.py +++ b/frappe/utils/jinja_globals.py @@ -38,13 +38,13 @@ def web_block(template, values=None, **kwargs): def web_blocks(blocks): - from frappe import throw, _dict + from frappe import throw, _dict, _ from frappe.website.doctype.web_page.web_page import get_web_blocks_html web_blocks = [] for block in blocks: if not block.get("template"): - throw("Web Template is not specified") + throw(_("Web Template is not specified")) doc = _dict( { From ed1a9e15591b7e8d4e1053fd97e528bbfb9cc43d Mon Sep 17 00:00:00 2001 From: hasnain2808 Date: Thu, 13 May 2021 09:55:27 +0530 Subject: [PATCH 065/868] fix: do not show counter on unsaved forms --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index e837ca2d6c..23a22ee33c 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Document Naming Rule', { refresh: function(frm) { frm.trigger('document_type'); - frm.trigger("add_button"); + if(!frm.doc.__islocal) frm.trigger("add_button"); }, document_type: (frm) => { // update the select field options with fieldnames From 90f786b0e5641f8c03b7e7e33988c82412aa4d4b Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 13 May 2021 09:57:10 +0530 Subject: [PATCH 066/868] chore: spaces --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 23a22ee33c..7dbf533975 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Document Naming Rule', { refresh: function(frm) { frm.trigger('document_type'); - if(!frm.doc.__islocal) frm.trigger("add_button"); + if (!frm.doc.__islocal) frm.trigger("add_button"); }, document_type: (frm) => { // update the select field options with fieldnames From fed99bffac29ff4cb99866d6a3e3246170525916 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 13 May 2021 13:34:56 +0530 Subject: [PATCH 067/868] fix: Set basepath and toc data to show sidebar --- frappe/website/page_controllers/template_page.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index b050a62bad..49a811b587 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -5,6 +5,7 @@ import frappe from frappe.website.page_controllers.base_template_page import BaseTemplatePage from frappe.website.context import add_sidebar_and_breadcrumbs from frappe.website.render import build_response +from frappe.website.router import get_base_template from frappe.website.utils import (extract_comment_tag, extract_title, get_next_link, get_toc) @@ -31,6 +32,7 @@ class TemplatePage(BaseTemplatePage): self.app = app self.app_path = app_path self.template_path = os.path.relpath(file_path, self.app_path) + self.basepath = os.path.dirname(file_path) return True def get_index_path_options(self, search_path): @@ -74,7 +76,6 @@ class TemplatePage(BaseTemplatePage): same folder. Also the hyphens will be coverted to underscore for python module names. This method sets the pymodule_name if it exists. ''' - self.basepath = self.template_path.rsplit('.', 1)[0] self.pymodule_name = None # replace - with _ in the internal modules names @@ -90,6 +91,9 @@ class TemplatePage(BaseTemplatePage): self.convert_from_markdown() def update_context(self): + self.context.base_template = self.context.base_template or get_base_template(self.path) + self.context.basepath = self.basepath + self.context.path = self.path self.set_page_properties() self.set_properties_from_source() self.load_colocated_files() @@ -196,7 +200,7 @@ class TemplatePage(BaseTemplatePage): def convert_from_markdown(self): if self.template_path.endswith('.md'): self.source = frappe.utils.md_to_html(self.source) - self.page_toc_html = self.source.toc_html + self.context.page_toc_html = self.source.toc_html if not self.context.show_sidebar: self.source = '
' + self.source + '
' From dbd8b66d815c8d255fb493c97eadb68671dcb844 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 13 May 2021 14:22:26 +0530 Subject: [PATCH 068/868] fix: Template basepath --- frappe/website/page_controllers/template_page.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 49a811b587..4db6d17541 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -76,10 +76,11 @@ class TemplatePage(BaseTemplatePage): same folder. Also the hyphens will be coverted to underscore for python module names. This method sets the pymodule_name if it exists. ''' + template_basepath = os.path.splitext(self.template_path)[0] self.pymodule_name = None # replace - with _ in the internal modules names - self.pymodule_path = os.path.join(self.basepath.replace("-", "_") + ".py") + self.pymodule_path = os.path.join(template_basepath.replace("-", "_") + ".py") if os.path.exists(os.path.join(self.app_path, self.pymodule_path)): self.pymodule_name = self.app + "." + self.pymodule_path.replace(os.path.sep, ".")[:-3] From 8b1b5c707b11f150d85d791354a7ebadccd27f43 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 13 May 2021 16:41:20 +0530 Subject: [PATCH 069/868] fix: remove unnecessary casting from set to list --- frappe/core/doctype/data_import/importer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 6337d919eb..6856fde4d0 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -936,8 +936,8 @@ class Column: elif self.df.fieldtype == "Select": options = get_select_options(self.df) if options: - values = list({cstr(v) for v in self.column_values[1:] if v}) - invalid = list(set(values) - set(options)) + values = {cstr(v) for v in self.column_values[1:] if v} + invalid = values - set(options) if invalid: valid_values = ", ".join(frappe.bold(o) for o in options) invalid_values = ", ".join(frappe.bold(i) for i in invalid) From 2e1c4650baf004c2a0e756d388bd4389c9335853 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 13 May 2021 19:54:56 +0530 Subject: [PATCH 070/868] Update frappe/core/doctype/document_naming_rule/document_naming_rule.js Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 7dbf533975..5e77e71820 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -51,7 +51,7 @@ frappe.ui.form.on('Document Naming Rule', { }; var dialog = new frappe.ui.Dialog({ - title: __('Update Counter Value for Prefix: ' + frm.doc.prefix), + title: __('Update Counter Value for Prefix: {0}', [frm.doc.prefix]), fields, primary_action_label, primary_action From 24434ed9dee018f4910898979f90d596f3f64dc3 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 13:26:45 +0530 Subject: [PATCH 071/868] refactor: Delete unused code from render.py --- frappe/website/render.py | 174 +-------------------------------------- 1 file changed, 2 insertions(+), 172 deletions(-) diff --git a/frappe/website/render.py b/frappe/website/render.py index b7221e364c..ee80fa3b9f 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -22,112 +22,11 @@ from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, from frappe.website.router import clear_sitemap, evaluate_dynamic_routes from frappe.translate import guess_language +from frappe.website.serve import get_response class PageNotFoundError(Exception): pass def render(path=None, http_status_code=None): - # temp feature flag - if True or frappe.conf.flag_new_website: - from frappe.website.serve import get_response - return get_response(path, http_status_code) - else: - return _render(path, http_status_code) - -def _render(path=None, http_status_code=None): - """render html page""" - if not path: - path = frappe.local.request.path - - try: - path = path.strip('/ ') - raise_if_disabled(path) - resolve_redirect(path) - path = resolve_path(path) - data = None - - # if in list of already known 404s, send it - if can_cache() and frappe.cache().hget('website_404', frappe.request.url): - data = render_page('404') - http_status_code = 404 - elif is_static_file(path): - return get_static_file_response() - elif is_web_form(path): - data = render_web_form(path) - else: - try: - data = render_page_by_language(path) - except frappe.PageDoesNotExistError: - doctype, name = get_doctype_from_path(path) - if doctype and name: - path = "printview" - frappe.local.form_dict.doctype = doctype - frappe.local.form_dict.name = name - elif doctype: - path = "list" - frappe.local.form_dict.doctype = doctype - else: - # 404s are expensive, cache them! - frappe.cache().hset('website_404', frappe.request.url, True) - data = render_page('404') - http_status_code = 404 - - if not data: - try: - data = render_page(path) - except frappe.PermissionError as e: - data, http_status_code = render_403(e, path) - - except frappe.PermissionError as e: - data, http_status_code = render_403(e, path) - - except frappe.Redirect as e: - raise e - - except Exception: - path = "error" - data = render_page(path) - http_status_code = 500 - - data = add_csrf_token(data) - - except frappe.Redirect: - return build_response(path, "", 301, { - "Location": frappe.flags.redirect_location or (frappe.local.response or {}).get('location'), - "Cache-Control": "no-store, no-cache, must-revalidate" - }) - - return build_response(path, data, http_status_code or 200) - -def is_static_file(path): - if ('.' not in path): - return False - extn = path.rsplit('.', 1)[-1] - if extn in ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json'): - return False - - for app in frappe.get_installed_apps(): - file_path = frappe.get_app_path(app, 'www') + '/' + path - if os.path.exists(file_path): - frappe.flags.file_path = file_path - return True - - return False - -def is_web_form(path): - return bool(frappe.get_all("Web Form", filters={'route': path})) - -def render_web_form(path): - data = render_page(path) - return data - -def get_static_file_response(): - try: - f = open(frappe.flags.file_path, 'rb') - except IOError: - raise NotFound - - response = Response(wrap_file(frappe.local.request.environ, f), direct_passthrough=True) - response.mimetype = mimetypes.guess_type(frappe.flags.file_path)[0] or 'application/octet-stream' - return response + return get_response(path, http_status_code) def build_response(path, data, http_status_code, headers=None): # build response @@ -168,23 +67,6 @@ def add_preload_headers(response): traceback.print_exc() -def render_page_by_language(path): - translated_languages = frappe.get_hooks("translated_languages_for_website") - user_lang = guess_language(translated_languages) - if translated_languages and user_lang in translated_languages: - try: - if path and path != "index": - lang_path = '{0}/{1}'.format(user_lang, path) - else: - lang_path = user_lang # index - - return render_page(lang_path) - except frappe.DoesNotExistError: - return render_page(path) - - else: - return render_page(path) - def render_page(path): """get page html""" out = None @@ -307,7 +189,6 @@ def set_content_type(response, data, path): def clear_cache(path=None): '''Clear website caches - :param path: (optional) for the given path''' for key in ('website_generator_routes', 'website_pages', 'website_full_index', 'sitemap_routes'): @@ -327,54 +208,3 @@ def clear_cache(path=None): for method in frappe.get_hooks("website_clear_cache"): frappe.get_attr(method)(path) - -def render_403(e, pathname): - frappe.local.message = cstr(e.message if six.PY2 else e) - frappe.local.message_title = _("Not Permitted") - frappe.local.response['context'] = dict( - indicator_color = 'red', - primary_action = '/login', - primary_label = _('Login'), - fullpage=True - ) - return render_page("message"), e.http_status_code - -def get_doctype_from_path(path): - doctypes = frappe.db.sql_list("select name from tabDocType") - - parts = path.split("/") - - doctype = parts[0] - name = parts[1] if len(parts) > 1 else None - - if doctype in doctypes: - return doctype, name - - # try scrubbed - doctype = doctype.replace("_", " ").title() - if doctype in doctypes: - return doctype, name - - return None, None - -def add_csrf_token(data): - if frappe.local.session: - return data.replace("", ''.format( - frappe.local.session.data.csrf_token)) - else: - return data - -def raise_if_disabled(path): - routes = frappe.db.get_all('Portal Menu Item', - fields=['route', 'enabled'], - filters={ - 'enabled': 0, - 'route': ['like', '%{0}'.format(path)] - } - ) - - for r in routes: - _path = r.route.lstrip('/') - if path == _path and not r.enabled: - raise frappe.PermissionError - From 4219ef98d18e1b9caf00558bf1adca96c76e3154 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 13:31:13 +0530 Subject: [PATCH 072/868] fix: Update renderer sequence --- frappe/website/serve.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index eacaef96e1..f11ba1c4fc 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -29,7 +29,7 @@ def get_response(path=None, http_status_code=200): path = resolve_path(path) # there is no way to determine the type of the page based on the route # so evaluate each type of page sequentially - renderers = [StaticPage, TemplatePage, ListPage, WebFormPage, DocumentPage, PrintPage, NotFoundPage] + renderers = [StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage] for renderer in renderers: response = renderer(path, http_status_code).get() if response: From 39c1a94f896fff0e1781b8df6b60047cb8b7e286 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 13:53:04 +0530 Subject: [PATCH 073/868] fix: Circular import --- frappe/website/page_controllers/web_page.py | 1 + frappe/website/render.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/website/page_controllers/web_page.py b/frappe/website/page_controllers/web_page.py index 2020d491e4..4d9e642b4b 100644 --- a/frappe/website/page_controllers/web_page.py +++ b/frappe/website/page_controllers/web_page.py @@ -7,6 +7,7 @@ class WebPage(object): if not path: path = frappe.local.request.path self.path = path.strip('/ ') + self.basepath = '' def get(self): if self.validate(): diff --git a/frappe/website/render.py b/frappe/website/render.py index ee80fa3b9f..3868a91232 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -22,10 +22,10 @@ from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, from frappe.website.router import clear_sitemap, evaluate_dynamic_routes from frappe.translate import guess_language -from frappe.website.serve import get_response class PageNotFoundError(Exception): pass def render(path=None, http_status_code=None): + from frappe.website.serve import get_response return get_response(path, http_status_code) def build_response(path, data, http_status_code, headers=None): From 56ee6e449cedd64856bc9af9539006d5149266c8 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 14:17:52 +0530 Subject: [PATCH 074/868] refactor: Remove render method - also, move clear cache to utils.py --- frappe/utils/response.py | 3 ++- frappe/website/render.py | 33 +++++---------------------------- frappe/website/router.py | 3 --- frappe/website/utils.py | 27 ++++++++++++++++++++++++++- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/frappe/utils/response.py b/frappe/utils/response.py index 44b037f3cc..97097ab280 100644 --- a/frappe/utils/response.py +++ b/frappe/utils/response.py @@ -217,7 +217,8 @@ def send_private_file(path): return response def handle_session_stopped(): + from frappe.website.serve import get_response frappe.respond_as_web_page(_("Updating"), _("Your system is being updated. Please refresh again after a few moments."), http_status_code=503, indicator_color='orange', fullpage = True, primary_action=None) - return frappe.website.render.render("message", http_status_code=503) + return get_response("message", http_status_code=503) diff --git a/frappe/website/render.py b/frappe/website/render.py index 3868a91232..895faa5b5f 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -6,27 +6,21 @@ import frappe from frappe import _ import frappe.sessions from frappe.utils import cstr -import os, mimetypes, json +import mimetypes, json import re -import six from six import iteritems from werkzeug.wrappers import Response from werkzeug.routing import Rule from werkzeug.wsgi import wrap_file from frappe.website.context import get_context -from frappe.website.redirect import resolve_redirect from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, get_toc, get_next_link) -from frappe.website.router import clear_sitemap, evaluate_dynamic_routes -from frappe.translate import guess_language +from frappe.website.router import evaluate_dynamic_routes class PageNotFoundError(Exception): pass -def render(path=None, http_status_code=None): - from frappe.website.serve import get_response - return get_response(path, http_status_code) def build_response(path, data, http_status_code, headers=None): # build response @@ -188,23 +182,6 @@ def set_content_type(response, data, path): return data def clear_cache(path=None): - '''Clear website caches - :param path: (optional) for the given path''' - for key in ('website_generator_routes', 'website_pages', - 'website_full_index', 'sitemap_routes'): - frappe.cache().delete_value(key) - - frappe.cache().delete_value("website_404") - if path: - frappe.cache().hdel('website_redirects', path) - delete_page_cache(path) - else: - clear_sitemap() - frappe.clear_cache("Guest") - for key in ('portal_menu_items', 'home_page', 'website_route_rules', - 'doctypes_with_web_view', 'website_redirects', 'page_context', - 'website_page'): - frappe.cache().delete_value(key) - - for method in frappe.get_hooks("website_clear_cache"): - frappe.get_attr(method)(path) + # TODO: Remove this + from frappe.website.utils import clear_cache + return clear_cache(path) diff --git a/frappe/website/router.py b/frappe/website/router.py index 1e61f6dcc3..36779923b5 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -85,9 +85,6 @@ def get_page_context_from_doctype(path): return frappe.get_doc(page_info.get("doctype"), page_info.get("name")).get_page_info() -def clear_sitemap(): - delete_page_cache("*") - def get_all_page_context_from_doctypes(): ''' Get all doctype generated routes (for sitemap.xml) diff --git a/frappe/website/utils.py b/frappe/website/utils.py index efa15bdb14..8c75508d07 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -11,7 +11,6 @@ from six import iteritems from past.builtins import cmp from frappe.utils import md_to_html - def delete_page_cache(path): cache = frappe.cache() cache.delete_value('full_index') @@ -399,3 +398,29 @@ def get_html_content_based_on_type(doc, fieldname, content_type): content = '' return content + + +def clear_cache(path=None): + '''Clear website caches + :param path: (optional) for the given path''' + for key in ('website_generator_routes', 'website_pages', + 'website_full_index', 'sitemap_routes'): + frappe.cache().delete_value(key) + + frappe.cache().delete_value("website_404") + if path: + frappe.cache().hdel('website_redirects', path) + delete_page_cache(path) + else: + clear_sitemap() + frappe.clear_cache("Guest") + for key in ('portal_menu_items', 'home_page', 'website_route_rules', + 'doctypes_with_web_view', 'website_redirects', 'page_context', + 'website_page'): + frappe.cache().delete_value(key) + + for method in frappe.get_hooks("website_clear_cache"): + frappe.get_attr(method)(path) + +def clear_sitemap(): + delete_page_cache("*") From 9ba5bf1133b05d2435e74099227609970501c87c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 18:42:41 +0530 Subject: [PATCH 075/868] refactor: Move metatags related code into a separate file --- .../page_controllers/base_template_page.py | 75 ++----------------- frappe/website/website_components/metatags.py | 68 +++++++++++++++++ 2 files changed, 73 insertions(+), 70 deletions(-) create mode 100644 frappe/website/website_components/metatags.py diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py index 74ca400372..c40afb7b1c 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_controllers/base_template_page.py @@ -1,13 +1,13 @@ import frappe -from frappe.website.doctype.website_settings.website_settings import \ - get_website_settings +from frappe.website.doctype.website_settings.website_settings import get_website_settings from frappe.website.page_controllers.web_page import WebPage +from frappe.website.website_components.metatags import MetaTags class BaseTemplatePage(WebPage): def init_context(self): self.context = frappe._dict() - self.context.update(get_website_settings(self.context)) + self.context.update(get_website_settings()) self.context.update(frappe.local.conf.get("website_context") or {}) def add_csrf_token(self, html): @@ -19,7 +19,8 @@ class BaseTemplatePage(WebPage): return html def post_process_context(self): - self.add_metatags() + self.tags = MetaTags(self.path, self.context).tags + self.context.metatags = self.tags self.set_base_template_if_missing() self.set_title_with_prefix() self.update_website_context() @@ -53,69 +54,3 @@ class BaseTemplatePage(WebPage): values = frappe.get_attr(method)(self.context) if values: self.context.update(values) - - def add_metatags(self): - self.tags = frappe._dict(self.context.get("metatags") or {}) - self.init_metatags_from_context() - self.set_opengraph_tags() - self.set_twitter_tags() - self.set_meta_published_on() - self.set_metatags_from_website_route_meta() - - self.context.metatags = self.tags - - def init_metatags_from_context(self): - for key in ('title', 'description', 'image', 'author', 'url', 'published_on'): - if key not in self.tags and self.context.get(key): - self.tags[key] = self.context[key] - - if not self.tags.get('title'): - self.tags['title'] = self.context.get('name') - - if self.tags.get('image'): - self.tags['image'] = frappe.utils.get_url(self.tags['image']) - - self.tags["language"] = frappe.local.lang or "en" - - def set_opengraph_tags(self): - if "og:type" not in self.tags: - self.tags["og:type"] = "article" - - for key in ('title', 'description', 'image', 'author', 'url'): - if self.tags.get(key): - self.tags['og:' + key] = self.tags.get(key) - - def set_twitter_tags(self): - for key in ('title', 'description', 'image', 'author', 'url'): - if self.tags.get(key): - self.tags['twitter:' + key] = self.tags.get(key) - - if self.tags.get('image'): - self.tags['twitter:card'] = "summary_large_image" - else: - self.tags["twitter:card"] = "summary" - - def set_meta_published_on(self): - if "published_on" in self.tags: - self.tags["datePublished"] = self.tags["published_on"] - del self.tags["published_on"] - - def set_metatags_from_website_route_meta(self): - ''' - Get meta tags from Website Route meta - they can override the defaults set above - ''' - route = self.path - if route == '': - # homepage - route = frappe.db.get_single_value('Website Settings', 'home_page') - - route_exists = (route - and not route.endswith(('.js', '.css')) - and frappe.db.exists('Website Route Meta', route)) - - if route_exists: - website_route_meta = frappe.get_doc('Website Route Meta', route) - for meta_tag in website_route_meta.meta_tags: - d = meta_tag.get_meta_dict() - self.tags.update(d) diff --git a/frappe/website/website_components/metatags.py b/frappe/website/website_components/metatags.py new file mode 100644 index 0000000000..045bef8fe1 --- /dev/null +++ b/frappe/website/website_components/metatags.py @@ -0,0 +1,68 @@ +import frappe + +class MetaTags(): + def __init__(self, path, context): + self.path = path + self.context = context + self.tags = frappe._dict(self.context.get("metatags") or {}) + self.init_metatags_from_context() + self.set_opengraph_tags() + self.set_twitter_tags() + self.set_meta_published_on() + self.set_metatags_from_website_route_meta() + + def init_metatags_from_context(self): + for key in ('title', 'description', 'image', 'author', 'url', 'published_on'): + if key not in self.tags and self.context.get(key): + self.tags[key] = self.context[key] + + if not self.tags.get('title'): + self.tags['title'] = self.context.get('name') + + if self.tags.get('image'): + self.tags['image'] = frappe.utils.get_url(self.tags['image']) + + self.tags["language"] = frappe.local.lang or "en" + + def set_opengraph_tags(self): + if "og:type" not in self.tags: + self.tags["og:type"] = "article" + + for key in ('title', 'description', 'image', 'author', 'url'): + if self.tags.get(key): + self.tags['og:' + key] = self.tags.get(key) + + def set_twitter_tags(self): + for key in ('title', 'description', 'image', 'author', 'url'): + if self.tags.get(key): + self.tags['twitter:' + key] = self.tags.get(key) + + if self.tags.get('image'): + self.tags['twitter:card'] = "summary_large_image" + else: + self.tags["twitter:card"] = "summary" + + def set_meta_published_on(self): + if "published_on" in self.tags: + self.tags["datePublished"] = self.tags["published_on"] + del self.tags["published_on"] + + def set_metatags_from_website_route_meta(self): + ''' + Get meta tags from Website Route meta + they can override the defaults set above + ''' + route = self.path + if route == '': + # homepage + route = frappe.db.get_single_value('Website Settings', 'home_page') + + route_exists = (route + and not route.endswith(('.js', '.css')) + and frappe.db.exists('Website Route Meta', route)) + + if route_exists: + website_route_meta = frappe.get_doc('Website Route Meta', route) + for meta_tag in website_route_meta.meta_tags: + d = meta_tag.get_meta_dict() + self.tags.update(d) From 20bab0f631acd5dfbf3ddda250472568f057fc6a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 18:58:04 +0530 Subject: [PATCH 076/868] refactor: Move code to appropriate places --- frappe/utils/__init__.py | 4 +-- .../website/page_controllers/template_page.py | 36 +++---------------- frappe/website/router.py | 2 +- frappe/website/utils.py | 16 +++++++++ 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 43a7b82c16..845cb9be4a 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -770,9 +770,9 @@ def set_request(**kwargs): frappe.local.request = Request(builder.get_environ()) def get_html_for_route(route): - from frappe.website import render + from frappe.website.serve import get_response set_request(method='GET', path=route) - response = render.render() + response = get_response() html = frappe.safe_decode(response.get_data()) return html diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 4db6d17541..f2664fb928 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -6,9 +6,10 @@ from frappe.website.page_controllers.base_template_page import BaseTemplatePage from frappe.website.context import add_sidebar_and_breadcrumbs from frappe.website.render import build_response from frappe.website.router import get_base_template -from frappe.website.utils import (extract_comment_tag, extract_title, - get_next_link, get_toc) +from frappe.website.utils import (extract_comment_tag, + extract_title, get_next_link, get_toc, get_frontmatter) +WEBPAGE_PY_MODULE_PROPERTIES = ("base_template_path", "template", "no_cache", "sitemap", "condition_field") class TemplatePage(BaseTemplatePage): def validate(self): @@ -36,12 +37,7 @@ class TemplatePage(BaseTemplatePage): return True def get_index_path_options(self, search_path): - return ( - search_path, - search_path + '.html', - search_path + '.md', - search_path + '/index.html', - search_path + '/index.md') + return (f'{search_path}{d}' for d in ('', '.html', '.md', '/index.html', '/index.md')) def render(self): return build_response(self.path, self.get_html(), self.http_status_code, self.headers) @@ -115,8 +111,7 @@ class TemplatePage(BaseTemplatePage): self.http_status_code = self.context.http_status_code def set_pymodule_properties(self): - for prop in ("base_template_path", "template", "no_cache", "sitemap", - "condition_field"): + for prop in WEBPAGE_PY_MODULE_PROPERTIES: if hasattr(self.pymodule, prop): self.context[prop] = getattr(self.pymodule, prop) @@ -237,24 +232,3 @@ class TemplatePage(BaseTemplatePage): def get_start_folders(): return frappe.local.flags.web_pages_folders or ('www', 'templates/pages') - -def get_frontmatter(string): - """ - Reference: https://github.com/jonbeebe/frontmatter - """ - import re - - import yaml - - fmatter = "" - body = "" - result = re.compile(r'^\s*(?:---|\+\+\+)(.*?)(?:---|\+\+\+)\s*(.+)$', re.S | re.M).search(string) - - if result: - fmatter = result.group(1) - body = result.group(2) - - return { - "attributes": yaml.safe_load(fmatter), - "body": body, - } diff --git a/frappe/website/router.py b/frappe/website/router.py index 36779923b5..b048fa55c0 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -9,7 +9,7 @@ import re import frappe from frappe.model.document import get_controller -from frappe.website.utils import can_cache, delete_page_cache, extract_comment_tag, extract_title +from frappe.website.utils import can_cache, extract_comment_tag, extract_title from werkzeug.routing import Map, Rule, NotFound def resolve_route(path): diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 8c75508d07..87e47571fb 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -6,6 +6,8 @@ import functools import re import os import frappe +import re +import yaml from six import iteritems from past.builtins import cmp @@ -424,3 +426,17 @@ def clear_cache(path=None): def clear_sitemap(): delete_page_cache("*") + +def get_frontmatter(string): + "Reference: https://github.com/jonbeebe/frontmatter" + frontmatter = "" + body = "" + result = re.compile(r'^\s*(?:---|\+\+\+)(.*?)(?:---|\+\+\+)\s*(.+)$', re.S | re.M).search(string) + if result: + frontmatter = result.group(1) + body = result.group(2) + + return { + "attributes": yaml.safe_load(frontmatter), + "body": body, + } From 18497989dc71d24c3e7662382fb58cc2d84c1e0a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 21:30:28 +0530 Subject: [PATCH 077/868] refactor: Remove render_page from render.py & replace all usages of render_page with get_response --- frappe/__init__.py | 4 +- frappe/search/website_search.py | 4 +- frappe/tests/test_recorder.py | 4 +- frappe/utils/global_search.py | 4 +- .../website/doctype/web_form/test_web_form.py | 1 - frappe/website/render.py | 50 +++---------------- frappe/website/router.py | 6 +-- 7 files changed, 19 insertions(+), 54 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 02b8d71e40..bd46f0f874 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1485,7 +1485,7 @@ def get_print(doctype=None, name=None, print_format=None, style=None, :param style: Print Format style. :param as_pdf: Return as PDF. Default False. :param password: Password to encrypt the pdf with. Default None""" - from frappe.website.render import build_page + from frappe.website.serve import get_response from frappe.utils.pdf import get_pdf local.form_dict.doctype = doctype @@ -1500,7 +1500,7 @@ def get_print(doctype=None, name=None, print_format=None, style=None, options = {'password': password} if not html: - html = build_page("printview") + html = get_response("printview") if as_pdf: return get_pdf(html, output = output, options = options) diff --git a/frappe/search/website_search.py b/frappe/search/website_search.py index 452ea2a427..ad2ebb504d 100644 --- a/frappe/search/website_search.py +++ b/frappe/search/website_search.py @@ -9,7 +9,7 @@ from whoosh.fields import ID, TEXT, Schema import frappe from frappe.search.full_text_search import FullTextSearch from frappe.utils import set_request, update_progress_bar -from frappe.website.render import render_page +from frappe.website.serve import get_response INDEX_NAME = "web_routes" @@ -61,7 +61,7 @@ class WebsiteSearch(FullTextSearch): try: set_request(method="GET", path=route) - content = render_page(route) + content = get_response(route) soup = BeautifulSoup(content, "html.parser") page_content = soup.find(class_="page_content") text_content = page_content.text if page_content else "" diff --git a/frappe/tests/test_recorder.py b/frappe/tests/test_recorder.py index 64d3c52f63..7dcccd1d71 100644 --- a/frappe/tests/test_recorder.py +++ b/frappe/tests/test_recorder.py @@ -8,7 +8,7 @@ import unittest import frappe import frappe.recorder from frappe.utils import set_request -from frappe.website.render import render_page +from frappe.website.serve import get_response import sqlparse @@ -122,5 +122,5 @@ class TestRecorder(unittest.TestCase): self.assertEqual(call['exact_copies'], query[1]) def test_error_page_rendering(self): - content = render_page("error") + content = get_response("error") self.assertIn("Error", content) diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py index c20f3b29d4..7541e8b31d 100644 --- a/frappe/utils/global_search.py +++ b/frappe/utils/global_search.py @@ -310,14 +310,14 @@ def get_routes_to_index(): def add_route_to_global_search(route): from bs4 import BeautifulSoup - from frappe.website.render import render_page + from frappe.website.serve import get_response from frappe.utils import set_request frappe.set_user('Guest') frappe.local.no_cache = True try: set_request(method='GET', path=route) - content = render_page(route) + content = get_response(route) soup = BeautifulSoup(content, 'html.parser') page_content = soup.find(class_='page_content') text_content = page_content.text if page_content else '' diff --git a/frappe/website/doctype/web_form/test_web_form.py b/frappe/website/doctype/web_form/test_web_form.py index 78f7fd6337..0e9ce7c660 100644 --- a/frappe/website/doctype/web_form/test_web_form.py +++ b/frappe/website/doctype/web_form/test_web_form.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import frappe import unittest, json -from frappe.website.render import build_page from frappe.website.doctype.web_form.web_form import accept test_dependencies = ['Web Form'] diff --git a/frappe/website/render.py b/frappe/website/render.py index 895faa5b5f..77c1af1e87 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -1,23 +1,21 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals -import frappe -from frappe import _ -import frappe.sessions -from frappe.utils import cstr -import mimetypes, json +import json +import mimetypes import re from six import iteritems -from werkzeug.wrappers import Response from werkzeug.routing import Rule -from werkzeug.wsgi import wrap_file +from werkzeug.wrappers import Response +import frappe +import frappe.sessions +from frappe import _ from frappe.website.context import get_context -from frappe.website.utils import (get_home_page, can_cache, delete_page_cache, - get_toc, get_next_link) from frappe.website.router import evaluate_dynamic_routes +from frappe.website.utils import (can_cache, get_home_page, get_next_link, get_toc) + class PageNotFoundError(Exception): pass @@ -61,38 +59,6 @@ def add_preload_headers(response): traceback.print_exc() -def render_page(path): - """get page html""" - out = None - - if can_cache(): - # return rendered page - page_cache = frappe.cache().hget("website_page", path) - if page_cache and frappe.local.lang in page_cache: - out = page_cache[frappe.local.lang] - - if out: - frappe.local.response.from_cache = True - return out - - return build(path) - -def build(path): - if not frappe.db: - frappe.connect() - - try: - return build_page(path) - except frappe.DoesNotExistError: - hooks = frappe.get_hooks() - if hooks.website_catch_all: - path = hooks.website_catch_all[0] - return build_page(path) - else: - raise - except Exception: - raise - def build_page(path): if not getattr(frappe.local, "path", None): frappe.local.path = path diff --git a/frappe/website/router.py b/frappe/website/router.py index b048fa55c0..2e27b4c690 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -1,16 +1,16 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import io import os import re +from werkzeug.routing import Map, NotFound, Rule + import frappe from frappe.model.document import get_controller from frappe.website.utils import can_cache, extract_comment_tag, extract_title -from werkzeug.routing import Map, Rule, NotFound + def resolve_route(path): """Returns the page route object based on searching in pages and generators. From 080a5b3c6a1395fe085d6d7d7218449139353da9 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 21:33:39 +0530 Subject: [PATCH 078/868] chore: Delete an unnecessary file - purifycss is no longer used. --- frappe/website/purifycss.py | 43 ------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 frappe/website/purifycss.py diff --git a/frappe/website/purifycss.py b/frappe/website/purifycss.py deleted file mode 100644 index 39e989db6e..0000000000 --- a/frappe/website/purifycss.py +++ /dev/null @@ -1,43 +0,0 @@ -from __future__ import print_function, unicode_literals -''' -Check for unused CSS Classes - -sUpdate source and target apps below and run from CLI - - bench --site [sitename] execute frappe.website.purifycss.purify.css - -''' - -import frappe, re, os - -source = frappe.get_app_path('frappe_theme', 'public', 'less', 'frappe_theme.less') -target_apps = ['erpnext_com', 'frappe_io', 'translator', 'chart_of_accounts_builder', 'frappe_theme'] - -def purifycss(): - with open(source, 'r') as f: - src = f.read() - - classes = [] - for line in src.splitlines(): - line = line.strip() - if not line: - continue - if line[0]=='@': - continue - classes.extend(re.findall('\.([^0-9][^ :&.{,(]*)', line)) - - classes = list(set(classes)) - - for app in target_apps: - for basepath, folders, files in os.walk(frappe.get_app_path(app)): - for fname in files: - if fname.endswith('.html') or fname.endswith('.md'): - #print 'checking {0}...'.format(fname) - with open(os.path.join(basepath, fname), 'r') as f: - src = f.read() - for c in classes: - if c in src: - classes.remove(c) - - for c in sorted(classes): - print(c) From c964217106538a8950961cb2a1df4445c3fb0291 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 21:40:44 +0530 Subject: [PATCH 079/868] style: Fix import issues --- frappe/website/render.py | 4 ---- frappe/website/utils.py | 1 - 2 files changed, 5 deletions(-) diff --git a/frappe/website/render.py b/frappe/website/render.py index 77c1af1e87..87eddf3463 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -11,15 +11,11 @@ from werkzeug.wrappers import Response import frappe import frappe.sessions -from frappe import _ from frappe.website.context import get_context from frappe.website.router import evaluate_dynamic_routes from frappe.website.utils import (can_cache, get_home_page, get_next_link, get_toc) -class PageNotFoundError(Exception): pass - - def build_response(path, data, http_status_code, headers=None): # build response response = Response() diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 87e47571fb..a5fe9c3986 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -6,7 +6,6 @@ import functools import re import os import frappe -import re import yaml from six import iteritems From c5b981524868141f2dee58fa7fc5c24e6584bc70 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 14 May 2021 23:43:36 +0530 Subject: [PATCH 080/868] fix: Add get_response_content to get page content --- frappe/__init__.py | 4 ++-- frappe/search/website_search.py | 4 ++-- frappe/utils/global_search.py | 8 ++++---- frappe/website/serve.py | 4 ++++ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index bd46f0f874..a90fd24d7b 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1485,7 +1485,7 @@ def get_print(doctype=None, name=None, print_format=None, style=None, :param style: Print Format style. :param as_pdf: Return as PDF. Default False. :param password: Password to encrypt the pdf with. Default None""" - from frappe.website.serve import get_response + from frappe.website.serve import get_response_content from frappe.utils.pdf import get_pdf local.form_dict.doctype = doctype @@ -1500,7 +1500,7 @@ def get_print(doctype=None, name=None, print_format=None, style=None, options = {'password': password} if not html: - html = get_response("printview") + html = get_response_content("printview") if as_pdf: return get_pdf(html, output = output, options = options) diff --git a/frappe/search/website_search.py b/frappe/search/website_search.py index ad2ebb504d..49bdade936 100644 --- a/frappe/search/website_search.py +++ b/frappe/search/website_search.py @@ -9,7 +9,7 @@ from whoosh.fields import ID, TEXT, Schema import frappe from frappe.search.full_text_search import FullTextSearch from frappe.utils import set_request, update_progress_bar -from frappe.website.serve import get_response +from frappe.website.serve import get_response_content INDEX_NAME = "web_routes" @@ -61,7 +61,7 @@ class WebsiteSearch(FullTextSearch): try: set_request(method="GET", path=route) - content = get_response(route) + content = get_response_content(route) soup = BeautifulSoup(content, "html.parser") page_content = soup.find(class_="page_content") text_content = page_content.text if page_content else "" diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py index 7541e8b31d..4c78d63918 100644 --- a/frappe/utils/global_search.py +++ b/frappe/utils/global_search.py @@ -310,14 +310,14 @@ def get_routes_to_index(): def add_route_to_global_search(route): from bs4 import BeautifulSoup - from frappe.website.serve import get_response + from frappe.website.serve import get_response_content from frappe.utils import set_request frappe.set_user('Guest') frappe.local.no_cache = True try: set_request(method='GET', path=route) - content = get_response(route) + content = get_response_content(route) soup = BeautifulSoup(content, 'html.parser') page_content = soup.find(class_='page_content') text_content = page_content.text if page_content else '' @@ -332,8 +332,8 @@ def add_route_to_global_search(route): route=route ) sync_value_in_queue(value) - except (frappe.PermissionError, frappe.DoesNotExistError, frappe.ValidationError, Exception): - pass + except (frappe.PermissionError, frappe.DoesNotExistError, frappe.ValidationError, Exception) as e: + raise e frappe.set_user('Administrator') diff --git a/frappe/website/serve.py b/frappe/website/serve.py index f11ba1c4fc..47ca0aa1d2 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -46,3 +46,7 @@ def get_response(path=None, http_status_code=200): response = ErrorPage(path, http_status_code, exception=e).get() return response + +def get_response_content(path=None, http_status_code=200): + response = get_response(path, http_status_code) + return response.data From 9b26307fe5e2210a6c36645e220d077c1e997090 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 17 May 2021 12:23:50 +0530 Subject: [PATCH 081/868] test: Use get_response_content to get content --- frappe/tests/test_recorder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/tests/test_recorder.py b/frappe/tests/test_recorder.py index 7dcccd1d71..8a1ae36ad9 100644 --- a/frappe/tests/test_recorder.py +++ b/frappe/tests/test_recorder.py @@ -8,7 +8,7 @@ import unittest import frappe import frappe.recorder from frappe.utils import set_request -from frappe.website.serve import get_response +from frappe.website.serve import get_response_content import sqlparse @@ -122,5 +122,5 @@ class TestRecorder(unittest.TestCase): self.assertEqual(call['exact_copies'], query[1]) def test_error_page_rendering(self): - content = get_response("error") + content = get_response_content("error") self.assertIn("Error", content) From e07fb1f736e459af0668fa83e8a5c23e5793a4d4 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 17 May 2021 15:50:39 +0530 Subject: [PATCH 082/868] fix: Edit Shortcut --- frappe/desk/desktop.py | 6 ++++ frappe/desk/doctype/workspace/workspace.py | 5 ---- frappe/public/js/frappe/views/wiki.js | 30 +++++++++---------- .../public/js/frappe/widgets/base_widget.js | 1 + .../public/js/frappe/widgets/widget_group.js | 9 ++++-- frappe/public/js/frappe/wiki_blocks/card.js | 2 +- .../public/js/frappe/wiki_blocks/shortcut.js | 30 ++++++++++++------- 7 files changed, 49 insertions(+), 34 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index c096f50b78..2a09978744 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +import json from json import loads, dumps from frappe import _, DoesNotExistError, ValidationError, _dict from frappe.boot import get_allowed_pages, get_allowed_reports @@ -549,6 +550,11 @@ def save_new_widget(page, new_widgets): if widgets.card: original_page.build_links_table_from_card(widgets.card) + content = frappe.db.get_value("Internal Wiki Page", page, "content") + for wid in ['shortcut']: + widd = [x['data'][ wid + '_name'] for x in json.loads(content) if x['type'] == wid] + original_page.set(wid+'s', [ele for ele in original_page.get(wid+'s') if ele.label in widd]) + try: original_page.save(ignore_permissions=True) except (ValidationError, TypeError) as e: diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 20c9240188..18aa383455 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -101,13 +101,8 @@ class Workspace(Document): }) def build_links_table_from_card(self, config): - # Empty links table - # self.links = [] - # order = config.get('order') - # widgets = config.get('widgets') for idx, card in enumerate(config): - # card = widgets[name].copy() links = loads(card.get('links')) self.append('links', { diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index ec4f2a49e8..057ae25902 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -404,6 +404,7 @@ frappe.views.Wiki = class Wiki { this.dirty = true; }, readOnly: true, + logLevel: 'ERROR' }); } @@ -440,22 +441,19 @@ frappe.views.Wiki = class Wiki { frappe.dom.unfreeze(); if (res.message) { let cur_page = res.message; - if (!$.isEmptyObject(new_widgets)) { - frappe.call('frappe.desk.desktop.save_new_widget', { - page: me.title, - new_widgets: new_widgets - }).then(res => { - if (res.message) { - me.reload(); - } - }); - } - frappe.show_alert({ message: __("Page Saved Successfully"), indicator: "green" }); - me.title = ''; - me.parent = ''; - me.sorted_sidebar_items = []; - me.new_page = cur_page; - me.reload(); + frappe.call('frappe.desk.desktop.save_new_widget', { + page: me.title, + new_widgets: new_widgets + }).then(res => { + if (res.message) { + frappe.show_alert({ message: __("Page Saved Successfully"), indicator: "green" }); + me.title = ''; + me.parent = ''; + me.sorted_sidebar_items = []; + me.new_page = cur_page; + me.reload(); + } + }); } } }); diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 9bbfb916e5..821df609ef 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -170,6 +170,7 @@ export default class Widget { data.name = this.name; this.refresh(); + this.options.on_edit && this.options.on_edit(data); }, primary_action_label: __("Save") }); diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 2b85359330..913a362932 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -208,7 +208,8 @@ export class SingleWidgetGroup { }); widget_object.options = { ...this.options, - on_delete: (name) => this.on_delete(name) + on_delete: () => this.on_delete(), + on_edit: () => this.on_edit(widget_object) }; this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; @@ -216,10 +217,14 @@ export class SingleWidgetGroup { return widget_object; } - on_delete(name, setup_new) { + on_delete() { this.api.blocks.delete(); } + on_edit(widget_object) { + this.block.call("on_edit", widget_object); + } + customize() { this.widgets_list.forEach((wid) => { wid.customize(this.options); diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index f06e4754e0..89821129e0 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -78,7 +78,7 @@ export default class Card { wid.options = { ...this.options, on_delete: () => this.api.blocks.delete() - } + }; wid.customize(this.options); this.wrapper.setAttribute("card_name", wid.label); this.new_card_widget = wid.get_config(); diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index 138ff8eac7..f57c9ef7f1 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -11,9 +11,10 @@ export default class Shortcut { return true; } - constructor({data, api, config, readOnly}) { + constructor({data, api, config, readOnly, block}) { this.data = data; this.api = api; + this.block = block; this.config = config; this.readOnly = readOnly; this.col = this.data.col ? this.data.col : "12"; @@ -69,18 +70,19 @@ export default class Shortcut { type: 'shortcut', primary_action: (widget) => { widget.in_customize_mode = 1; - let wid = frappe.widget.make_widget({ + this.shortcut_widget = frappe.widget.make_widget({ ...widget, widget_type: 'shortcut', container: this.wrapper }); - wid.options = { + this.shortcut_widget.options = { ...this.options, on_delete: () => this.api.blocks.delete(), - } - wid.customize(this.options); - this.wrapper.setAttribute("shortcut_name", wid.label); - this.new_shortcut_widget = wid.get_config(); + on_edit: () => this.on_edit(this.shortcut_widget) + }; + this.shortcut_widget.customize(this.options); + this.wrapper.setAttribute("shortcut_name", this.shortcut_widget.label); + this.new_shortcut_widget = this.shortcut_widget.get_config(); }, }); @@ -155,22 +157,30 @@ export default class Shortcut { this.shortcut_field.make(); } + on_edit(shortcut_obj) { + let shortcut = shortcut_obj.get_config(); + this.shortcut_widget.widgets = shortcut; + this.wrapper.setAttribute("shortcut_name", shortcut.label); + this.new_shortcut_widget = shortcut_obj.get_config(); + } + _make_shortcuts(shortcut_name) { let shortcut = this.config.page_data.shortcuts.items.find(obj => { return obj.label == shortcut_name; }); this.wrapper.innerHTML = ''; shortcut.in_customize_mode = !this.readOnly; - let shortcut_widget = new frappe.widget.SingleWidgetGroup({ + this.shortcut_widget = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "shortcut", options: this.options, widgets: shortcut, - api: this.api + api: this.api, + block: this.block }); this.wrapper.setAttribute("shortcut_name", shortcut_name); if (!this.readOnly) { - shortcut_widget.customize(); + this.shortcut_widget.customize(); } } } \ No newline at end of file From 1c4e1bc1df7e0788e235b4f735194d8567de6e58 Mon Sep 17 00:00:00 2001 From: prssanna Date: Wed, 14 Apr 2021 14:48:15 +0530 Subject: [PATCH 083/868] refactor: set amended docname to original docname --- frappe/core/doctype/doctype/doctype.py | 16 ++++++ frappe/model/document.py | 10 +++- frappe/model/naming.py | 53 +++++++++++++++++-- frappe/patches.txt | 1 + ...l_name_docfield_to_submittable_doctypes.py | 11 ++++ frappe/public/js/frappe/form/form.js | 24 +++++---- frappe/public/js/frappe/router.js | 6 +++ 7 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 84673f990a..3890ab3a32 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -74,6 +74,7 @@ class DocType(Document): if not self.istable: validate_permissions(self) + self.make_cancellable() self.make_amendable() self.make_repeatable() self.validate_nestedset() @@ -589,6 +590,21 @@ class DocType(Document): "no_copy": 1 }) + def make_cancellable(self): + """If is_submittable is set, add original_name docfield.""" + if self.is_submittable: + if not frappe.db.sql("""select name from tabDocField + where fieldname = 'original_name' and parent = %s""", self.name): + self.append("fields", { + "label": "Original Name", + "fieldtype": "Text", + "fieldname": "original_name", + "read_only": 1, + "hidden": 1, + "print_hide": 1, + "no_copy": 1 + }) + def make_repeatable(self): """If allow_auto_repeat is set, add auto_repeat custom field.""" if self.allow_auto_repeat: diff --git a/frappe/model/document.py b/frappe/model/document.py index 623916597e..2bb4f1f3c0 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -7,7 +7,7 @@ import time from frappe import _, msgprint, is_whitelisted from frappe.utils import flt, cstr, now, get_datetime_str, file_lock, date_diff from frappe.model.base_document import BaseDocument, get_controller -from frappe.model.naming import set_new_name +from frappe.model.naming import set_new_name, rename_cancelled_doc from six import iteritems, string_types from werkzeug.exceptions import NotFound, Forbidden import hashlib, json @@ -919,6 +919,14 @@ class Document(BaseDocument): @whitelist.__func__ def _cancel(self): """Cancel the document. Sets `docstatus` = 2, then saves.""" + + # for backward compatibility + if self.amended_from and not self.original_name: + self.original_name = None + else: + self.original_name = self.name + + self.name = rename_cancelled_doc(self) self.docstatus = 2 self.save() diff --git a/frappe/model/naming.py b/frappe/model/naming.py index b8d6a6f8d7..33a09c659a 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -223,7 +223,16 @@ def revert_series_if_last(key, name, doc=None): * prefix = #### and hashes = 2021 (hash doesn't exist) * will search hash in key then accordingly get prefix = "" """ - if ".#" in key: + + # do not revert if doc is amended, since cancelled docs still exist + if doc.docstatus != 2 and doc.amended_from: + return + + # for first cancelled doc + if doc.docstatus == 2 and not doc.amended_from and doc.original_name: + name = doc.original_name + + if ".#" in key: prefix, hashes = key.rsplit(".", 1) if "#" not in hashes: # get the hash part from the key @@ -306,14 +315,48 @@ def append_number_if_name_exists(doctype, value, fieldname="name", separator="-" def _set_amended_name(doc): + if doc.original_name: + doc.name = doc.original_name + else: + original_name = get_original_name(doc) + doc.name = doc.amended_from + + # rename original doc to next name in series, and set amended doc name as original name + next_name_in_series = get_new_name_from_amended_from(doc) + frappe.rename_doc(doc.doctype, original_name, next_name_in_series, force=True, show_alert=False) + doc.name = original_name + doc.amended_from = next_name_in_series + doc.original_name = original_name + + return doc.name + +def get_original_name(doc): + # get original doc name from chain of amended docs + amended_from = original_name = doc.amended_from + while amended_from: + original_name = amended_from + amended_from = frappe.db.get_value(doc.doctype, amended_from, "amended_from") + + return original_name + +def get_new_name_from_amended_from(doc): am_id = 1 - am_prefix = doc.amended_from - if frappe.db.get_value(doc.doctype, doc.amended_from, "amended_from"): + am_prefix = doc.name + if frappe.db.get_value(doc.doctype, doc.name, "amended_from"): am_id = cint(doc.amended_from.split("-")[-1]) + 1 am_prefix = "-".join(doc.amended_from.split("-")[:-1]) # except the last hyphen - doc.name = am_prefix + "-" + str(am_id) - return doc.name + new_name = am_prefix + "-" + str(am_id) + if new_name == doc.name: + am_id += 1 + new_name = am_prefix + "-" + str(am_id) + return new_name + +def rename_cancelled_doc(doc): + doc = frappe.parse_json(doc) + new_name = get_new_name_from_amended_from(doc) + frappe.rename_doc(doc.doctype, doc.name, new_name, force=True, show_alert=False) + return new_name def _field_autoname(autoname, doc, skip_slicing=None): diff --git a/frappe/patches.txt b/frappe/patches.txt index e70be0a37b..a722bb39fa 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -337,3 +337,4 @@ frappe.patches.v12_0.rename_uploaded_files_with_proper_name frappe.patches.v13_0.queryreport_columns frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty +frappe.patches.v13_0.add_original_name_docfield_to_submittable_doctypes ####### diff --git a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py new file mode 100644 index 0000000000..725d37fd4a --- /dev/null +++ b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py @@ -0,0 +1,11 @@ +import frappe +from frappe.database.schema import add_column + +def execute(): + for doctype in frappe.db.get_all('DocType'): + doctype = frappe.get_doc("DocType", doctype.name) + if doctype.is_submittable and frappe.db.table_exists(doctype.name): + doctype.make_cancellable() + if not frappe.db.has_column(doctype.name, 'original_name'): + add_column(doctype.name, 'original_name', 'Text') + doctype.db_update_all() diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 6d8a6b1cb4..f9d9de967e 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -764,32 +764,36 @@ frappe.ui.form.Form = class FrappeForm { } _cancel(btn, callback, on_error, skip_confirm) { - const me = this; const cancel_doc = () => { frappe.validated = true; - me.script_manager.trigger("before_cancel").then(() => { + this.script_manager.trigger("before_cancel").then(() => { if (!frappe.validated) { - return me.handle_save_fail(btn, on_error); + return this.handle_save_fail(btn, on_error); } - var after_cancel = function(r) { + const original_name = this.docname; + const after_cancel = (r) => { if (r.exc) { - me.handle_save_fail(btn, on_error); + this.handle_save_fail(btn, on_error); } else { frappe.utils.play_sound("cancel"); - me.refresh(); callback && callback(); - me.script_manager.trigger("after_cancel"); + this.script_manager.trigger("after_cancel"); + frappe.run_serially([ + () => this.rename_notify(this.doctype, original_name, r.docs[0].name), + () => frappe.router.clear_re_route(this.doctype, original_name), + () => this.refresh(), + ]); } }; - frappe.ui.form.save(me, "cancel", after_cancel, btn); + frappe.ui.form.save(this, "cancel", after_cancel, btn); }); } if (skip_confirm) { cancel_doc(); } else { - frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), cancel_doc, me.handle_save_fail(btn, on_error)); + frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), cancel_doc, this.handle_save_fail(btn, on_error)); } }; @@ -811,7 +815,7 @@ frappe.ui.form.Form = class FrappeForm { 'docname': this.doc.name }).then(is_amended => { if (is_amended) { - frappe.throw(__('This document is already amended, you cannot ammend it again')); + frappe.throw(__('This document is already amended, you cannot amend it again')); } this.validate_form_action("Amend"); var me = this; diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index 5378294855..0d5231260c 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -235,6 +235,12 @@ frappe.router = { } }, + clear_re_route(doctype, docname) { + delete frappe.re_route[ + `${encodeURIComponent(frappe.router.slug(doctype))}/${encodeURIComponent(docname)}` + ]; + }, + set_title(sub_path) { if (frappe.route_titles[sub_path]) { frappe.utils.set_title(frappe.route_titles[sub_path]); From 251f878009f8f0e5574307ffd4275cd6ff36e3bc Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 15 Apr 2021 11:20:16 +0530 Subject: [PATCH 084/868] test: test naming for cancelled and amended docs --- frappe/tests/test_naming.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 66d48e3612..765ead275f 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -117,3 +117,36 @@ class TestNaming(unittest.TestCase): self.assertEqual(current_index.get('current'), 2) frappe.db.sql("""delete from `tabSeries` where name = %s""", series) + + def test_naming_for_cancelled_and_amended_doc(self): + if not frappe.db.exists('DocType', 'Submittable Doctype'): + frappe.get_doc({ + "doctype": "DocType", + "module": "Core", + "custom": 1, + "is_submittable": 1, + "permissions": [{ + "role": "System Manager", + "read": 1 + }], + "name": 'Submittable Doctype' + }).insert() + + doc = frappe.new_doc('Submittable DocType') + doc.save() + original_name = doc.name + + doc.submit() + doc.cancel() + cancelled_name = doc.name + self.assertEqual(cancelled_name, "{}-1".format(original_name)) + + amended_doc = frappe.copy_doc(doc) + amended_doc.docstatus = 0 + amended_doc.amended_from = doc.name + amended_doc.save() + self.assertEqual(amended_doc.name, original_name) + + amended_doc.submit() + amended_doc.cancel() + self.assertEqual(amended_doc.name, "{}-2".format(original_name)) From 304a771ba2221aa15cb9f186799a0603cb5ee425 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 15 Apr 2021 11:21:48 +0530 Subject: [PATCH 085/868] fix: check if doc has attribute amended_from --- frappe/model/naming.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 33a09c659a..b685886c58 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -224,13 +224,14 @@ def revert_series_if_last(key, name, doc=None): * will search hash in key then accordingly get prefix = "" """ - # do not revert if doc is amended, since cancelled docs still exist - if doc.docstatus != 2 and doc.amended_from: - return + if hasattr(doc, 'amended_from'): + # do not revert if doc is amended, since cancelled docs still exist + if doc.docstatus != 2 and doc.amended_from: + return - # for first cancelled doc - if doc.docstatus == 2 and not doc.amended_from and doc.original_name: - name = doc.original_name + # for first cancelled doc + if doc.docstatus == 2 and not doc.amended_from and doc.original_name: + name = doc.original_name if ".#" in key: prefix, hashes = key.rsplit(".", 1) From 3614ca2a4d9ed0831cd3bd7080e977a5c2622149 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 15 Apr 2021 12:17:53 +0530 Subject: [PATCH 086/868] style: fix indent --- frappe/core/doctype/doctype/doctype.py | 18 +++++++++--------- frappe/tests/test_naming.py | 23 +++++++++++------------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 3890ab3a32..0d478015bb 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -580,15 +580,15 @@ class DocType(Document): if self.is_submittable: if not frappe.db.sql("""select name from tabDocField where fieldname = 'amended_from' and parent = %s""", self.name): - self.append("fields", { - "label": "Amended From", - "fieldtype": "Link", - "fieldname": "amended_from", - "options": self.name, - "read_only": 1, - "print_hide": 1, - "no_copy": 1 - }) + self.append("fields", { + "label": "Amended From", + "fieldtype": "Link", + "fieldname": "amended_from", + "options": self.name, + "read_only": 1, + "print_hide": 1, + "no_copy": 1 + }) def make_cancellable(self): """If is_submittable is set, add original_name docfield.""" diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 765ead275f..afaabcc805 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -119,18 +119,17 @@ class TestNaming(unittest.TestCase): frappe.db.sql("""delete from `tabSeries` where name = %s""", series) def test_naming_for_cancelled_and_amended_doc(self): - if not frappe.db.exists('DocType', 'Submittable Doctype'): - frappe.get_doc({ - "doctype": "DocType", - "module": "Core", - "custom": 1, - "is_submittable": 1, - "permissions": [{ - "role": "System Manager", - "read": 1 - }], - "name": 'Submittable Doctype' - }).insert() + frappe.get_doc({ + "doctype": "DocType", + "module": "Core", + "custom": 1, + "is_submittable": 1, + "permissions": [{ + "role": "System Manager", + "read": 1 + }], + "name": 'Submittable Doctype' + }).insert() doc = frappe.new_doc('Submittable DocType') doc.save() From ba267b6e628ea57009aa310645ba2f539708fe76 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 16 Apr 2021 13:03:21 +0530 Subject: [PATCH 087/868] fix: update patch --- frappe/patches.txt | 2 +- .../add_original_name_docfield_to_submittable_doctypes.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/frappe/patches.txt b/frappe/patches.txt index a722bb39fa..1db775f17c 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -337,4 +337,4 @@ frappe.patches.v12_0.rename_uploaded_files_with_proper_name frappe.patches.v13_0.queryreport_columns frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty -frappe.patches.v13_0.add_original_name_docfield_to_submittable_doctypes ####### +frappe.patches.v13_0.add_original_name_docfield_to_submittable_doctypes diff --git a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py index 725d37fd4a..d870e63305 100644 --- a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py +++ b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py @@ -1,11 +1,9 @@ import frappe -from frappe.database.schema import add_column def execute(): for doctype in frappe.db.get_all('DocType'): doctype = frappe.get_doc("DocType", doctype.name) if doctype.is_submittable and frappe.db.table_exists(doctype.name): doctype.make_cancellable() - if not frappe.db.has_column(doctype.name, 'original_name'): - add_column(doctype.name, 'original_name', 'Text') + frappe.reload_doctype(doctype.name) doctype.db_update_all() From 26801f215cf03f9cb921752456ca6117bbb987f3 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 16 Apr 2021 13:10:14 +0530 Subject: [PATCH 088/868] fix: use orm --- frappe/core/doctype/doctype/doctype.py | 48 +++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 0d478015bb..aad0321fa0 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -577,33 +577,33 @@ class DocType(Document): def make_amendable(self): """If is_submittable is set, add amended_from docfields.""" - if self.is_submittable: - if not frappe.db.sql("""select name from tabDocField - where fieldname = 'amended_from' and parent = %s""", self.name): - self.append("fields", { - "label": "Amended From", - "fieldtype": "Link", - "fieldname": "amended_from", - "options": self.name, - "read_only": 1, - "print_hide": 1, - "no_copy": 1 - }) + if self.is_submittable and\ + not frappe.db.get_value('DocField', {'fieldname': 'amended_from', 'parent': self.name}): + + self.append("fields", { + "label": "Amended From", + "fieldtype": "Link", + "fieldname": "amended_from", + "options": self.name, + "read_only": 1, + "print_hide": 1, + "no_copy": 1 + }) def make_cancellable(self): """If is_submittable is set, add original_name docfield.""" - if self.is_submittable: - if not frappe.db.sql("""select name from tabDocField - where fieldname = 'original_name' and parent = %s""", self.name): - self.append("fields", { - "label": "Original Name", - "fieldtype": "Text", - "fieldname": "original_name", - "read_only": 1, - "hidden": 1, - "print_hide": 1, - "no_copy": 1 - }) + if self.is_submittable and\ + not frappe.db.get_value('DocField', {'fieldname': 'amended_from', 'parent': self.name}): + + self.append("fields", { + "label": "Original Name", + "fieldtype": "Text", + "fieldname": "original_name", + "read_only": 1, + "hidden": 1, + "print_hide": 1, + "no_copy": 1 + }) def make_repeatable(self): """If allow_auto_repeat is set, add auto_repeat custom field.""" From 413383bf5cbbe27fb2b93c23e761e0a5b8b7f1f4 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 16 Apr 2021 13:38:06 +0530 Subject: [PATCH 089/868] fix: condition in make_cancellable --- frappe/core/doctype/doctype/doctype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index aad0321fa0..c6f6b628cc 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -593,7 +593,7 @@ class DocType(Document): def make_cancellable(self): """If is_submittable is set, add original_name docfield.""" if self.is_submittable and\ - not frappe.db.get_value('DocField', {'fieldname': 'amended_from', 'parent': self.name}): + not frappe.db.get_value('DocField', {'fieldname': 'original_name', 'parent': self.name}): self.append("fields", { "label": "Original Name", From 2cf5915eee428e026de8b4ad9b8c75c60d756eee Mon Sep 17 00:00:00 2001 From: Prssanna Desai Date: Fri, 16 Apr 2021 13:38:33 +0530 Subject: [PATCH 090/868] fix: use get_meta Co-authored-by: Faris Ansari --- .../v13_0/add_original_name_docfield_to_submittable_doctypes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py index d870e63305..c5080cc692 100644 --- a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py +++ b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py @@ -2,7 +2,7 @@ import frappe def execute(): for doctype in frappe.db.get_all('DocType'): - doctype = frappe.get_doc("DocType", doctype.name) + doctype = frappe.get_meta(doctype.name) if doctype.is_submittable and frappe.db.table_exists(doctype.name): doctype.make_cancellable() frappe.reload_doctype(doctype.name) From 209ece8b6cc23fce390d8bb04d5463a85320dd34 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 16 Apr 2021 14:03:36 +0530 Subject: [PATCH 091/868] fix: delete test submittable doctype --- frappe/tests/test_naming.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index afaabcc805..7be2cc3ef7 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -119,7 +119,7 @@ class TestNaming(unittest.TestCase): frappe.db.sql("""delete from `tabSeries` where name = %s""", series) def test_naming_for_cancelled_and_amended_doc(self): - frappe.get_doc({ + submittable_doctype = frappe.get_doc({ "doctype": "DocType", "module": "Core", "custom": 1, @@ -149,3 +149,5 @@ class TestNaming(unittest.TestCase): amended_doc.submit() amended_doc.cancel() self.assertEqual(amended_doc.name, "{}-2".format(original_name)) + + submittable_doctype.delete() \ No newline at end of file From 0c603f0d769536d3351386cb2cd7aaccd99797a5 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 16 Apr 2021 17:27:12 +0530 Subject: [PATCH 092/868] test: fix cancel docs tests --- frappe/core/doctype/doctype/test_doctype.py | 4 ++++ .../add_original_name_docfield_to_submittable_doctypes.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 9c492d2c36..5a53600fff 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -350,6 +350,7 @@ class TestDocType(unittest.TestCase): dump_docs = json.dumps(docs.get('docs')) cancel_all_linked_docs(dump_docs) data_link_doc.cancel() + data_doc.name = '{}-1'.format(data_doc.name) data_doc.load_from_db() self.assertEqual(data_link_doc.docstatus, 2) self.assertEqual(data_doc.docstatus, 2) @@ -435,7 +436,10 @@ class TestDocType(unittest.TestCase): self.assertRaises(frappe.LinkExistsError, data_link_doc_1.cancel) data_doc.load_from_db() + + data_doc_2.name = '{}-1'.format(data_doc_2.name) data_doc_2.load_from_db() + self.assertEqual(data_link_doc_1.docstatus, 2) #linked doc is canceled diff --git a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py index c5080cc692..eccff2334f 100644 --- a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py +++ b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py @@ -2,7 +2,7 @@ import frappe def execute(): for doctype in frappe.db.get_all('DocType'): - doctype = frappe.get_meta(doctype.name) + doctype = frappe.get_doc('DocType', doctype.name) if doctype.is_submittable and frappe.db.table_exists(doctype.name): doctype.make_cancellable() frappe.reload_doctype(doctype.name) From b550e54f15d02bbb14d79c70344a89f0f73d9c33 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 29 Apr 2021 17:31:56 +0530 Subject: [PATCH 093/868] fix: add column in patch --- .../add_original_name_docfield_to_submittable_doctypes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py index eccff2334f..d17242e90a 100644 --- a/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py +++ b/frappe/patches/v13_0/add_original_name_docfield_to_submittable_doctypes.py @@ -1,9 +1,11 @@ import frappe +from frappe.database.schema import add_column def execute(): for doctype in frappe.db.get_all('DocType'): doctype = frappe.get_doc('DocType', doctype.name) if doctype.is_submittable and frappe.db.table_exists(doctype.name): doctype.make_cancellable() - frappe.reload_doctype(doctype.name) + if not frappe.db.has_column(doctype.name, 'original_name'): + add_column(doctype.name, 'original_name', 'Text') doctype.db_update_all() From 081677c6c4bf6190c804fb432ee2e83d14c74dda Mon Sep 17 00:00:00 2001 From: Prssanna Desai Date: Fri, 7 May 2021 11:30:35 +0530 Subject: [PATCH 094/868] fix: typo in test --- frappe/tests/test_naming.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 7be2cc3ef7..e7933ec7b3 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -131,7 +131,7 @@ class TestNaming(unittest.TestCase): "name": 'Submittable Doctype' }).insert() - doc = frappe.new_doc('Submittable DocType') + doc = frappe.new_doc('Submittable Doctype') doc.save() original_name = doc.name From d3d4b49796c551915b965a1d195787286fc16d90 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 17 May 2021 23:00:37 +0530 Subject: [PATCH 095/868] refactor: Simplify sidebar and breadcrumbs code --- frappe/website/context.py | 303 +++--------------- .../website/page_controllers/template_page.py | 56 ++-- 2 files changed, 83 insertions(+), 276 deletions(-) diff --git a/frappe/website/context.py b/frappe/website/context.py index ed5c89f149..c8dade5b8b 100644 --- a/frappe/website/context.py +++ b/frappe/website/context.py @@ -1,206 +1,28 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt +import json +import os -from __future__ import unicode_literals -import frappe, os, json - -from frappe.website.doctype.website_settings.website_settings import get_website_settings -from frappe.website.router import get_page_context +import frappe from frappe.model.document import Document -def get_context(path, args=None): - if args and args.source: - context = args - else: - context = get_page_context(path) - if args: - context.update(args) - - if hasattr(frappe.local, 'request'): - # for (remove leading slash) - # path could be overriden in render.resolve_from_map - context["path"] = frappe.local.request.path.strip('/ ') - else: - context["path"] = path - - context.canonical = frappe.utils.get_url(frappe.utils.escape_html(context.path)) - context.route = context.path - context = build_context(context) - - # set using frappe.respond_as_web_page - if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): - context.update(frappe.local.response.context) - - # to be able to inspect the context dict - # Use the macro "inspect" from macros.html - context._context_dict = context - - context.developer_mode = frappe.conf.developer_mode - - return context - -def update_controller_context(context, controller): - module = frappe.get_module(controller) - - if module: - # get config fields - for prop in ("base_template_path", "template", "no_cache", "sitemap", - "condition_field"): - if hasattr(module, prop): - context[prop] = getattr(module, prop) - - if hasattr(module, "get_context"): - import inspect - try: - if inspect.getfullargspec(module.get_context).args: - ret = module.get_context(context) - else: - ret = module.get_context() - if ret: - context.update(ret) - except (frappe.PermissionError, frappe.PageDoesNotExistError, frappe.Redirect): - raise - except: - if not any([frappe.flags.in_migrate, frappe.flags.in_website_search_build]): - frappe.errprint(frappe.utils.get_traceback()) - - if hasattr(module, "get_children"): - context.children = module.get_children(context) - - -def build_context(context): - """get_context method of doc or module is supposed to render - content templates and push it into context""" - context = frappe._dict(context) - - if not "url_prefix" in context: - context.url_prefix = "" - - if context.url_prefix and context.url_prefix[-1]!='/': - context.url_prefix += '/' - - # for backward compatibility - context.docs_base_url = '/docs' - - context.update(get_website_settings(context)) - context.update(frappe.local.conf.get("website_context") or {}) - - # provide doc - if context.doc: - context.update(context.doc.as_dict()) - context.update(context.doc.get_website_properties()) - - if not context.template: - context.template = context.doc.meta.get_web_template() - - if hasattr(context.doc, "get_context"): - ret = context.doc.get_context(context) - - if ret: - context.update(ret) - - for prop in ("no_cache", "sitemap"): - if not prop in context: - context[prop] = getattr(context.doc, prop, False) - - elif context.controller: - # controller based context - update_controller_context(context, context.controller) - - # controller context extensions - context_controller_hooks = frappe.get_hooks("extend_website_page_controller_context") or {} - for controller, extension in context_controller_hooks.items(): - if isinstance(extension, list): - for ext in extension: - if controller == context.controller: - update_controller_context(context, ext) - else: - update_controller_context(context, extension) - - add_metatags(context) - add_sidebar_and_breadcrumbs(context) - - # determine templates to be used - if not context.base_template_path: - app_base = frappe.get_hooks("base_template") - context.base_template_path = app_base[-1] if app_base else "templates/base.html" - - if context.title_prefix and context.title and not context.title.startswith(context.title_prefix): - context.title = '{0} - {1}'.format(context.title_prefix, context.title) - - # apply context from hooks - update_website_context = frappe.get_hooks('update_website_context') - for method in update_website_context: - values = frappe.get_attr(method)(context) - if values: - context.update(values) - - return context - -def load_sidebar(context, sidebar_json_path): - with open(sidebar_json_path, 'r') as sidebarfile: - try: - sidebar_json = sidebarfile.read() - context.sidebar_items = json.loads(sidebar_json) - context.show_sidebar = 1 - except json.decoder.JSONDecodeError: - frappe.throw('Invalid Sidebar JSON at ' + sidebar_json_path) - -def get_sidebar_json_path(path, look_for=False): - ''' - Get _sidebar.json path from directory path - - :param path: path of the current diretory - :param look_for: if True, look for _sidebar.json going upwards from given path - - :return: _sidebar.json path - ''' - if os.path.split(path)[1] == 'www' or path == '/' or not path: - return '' - - sidebar_json_path = os.path.join(path, '_sidebar.json') - if os.path.exists(sidebar_json_path): - return sidebar_json_path - else: - if look_for: - return get_sidebar_json_path(os.path.split(path)[0], look_for) - else: - return '' - -def add_sidebar_and_breadcrumbs(context): - '''Add sidebar and breadcrumbs to context''' - from frappe.website.router import get_page_info_from_template - if context.show_sidebar: - context.no_cache = 1 - add_sidebar_data(context) - else: - if context.basepath: - hooks = frappe.get_hooks('look_for_sidebar_json') - look_for_sidebar_json = hooks[0] if hooks else 0 - sidebar_json_path = get_sidebar_json_path( - context.basepath, - look_for_sidebar_json - ) - if sidebar_json_path: - load_sidebar(context, sidebar_json_path) - - if context.add_breadcrumbs and not context.parents: - if context.basepath: - parent_path = os.path.dirname(context.path).rstrip('/') - page_info = get_page_info_from_template(parent_path) - if page_info: - context.parents = [dict(route=parent_path, title=page_info.title)] - -def add_sidebar_data(context): - from frappe.utils.user import get_fullname_and_avatar +def get_sidebar_data(parent_sidebar, basepath): import frappe.www.list + sidebar_data = frappe._dict() - if context.show_sidebar and context.website_sidebar: - context.sidebar_items = frappe.get_all('Website Sidebar Item', - filters=dict(parent=context.website_sidebar), fields=['title', 'route', '`group`'], + hooks = frappe.get_hooks('look_for_sidebar_json') + look_for_sidebar_json = hooks[0] if hooks else 0 + + if basepath and look_for_sidebar_json: + sidebar_items = get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json) + sidebar_data['sidebar_items'] = sidebar_items + + if not sidebar_data.sidebar_items and parent_sidebar: + sidebar_data.sidebar_items = frappe.get_all('Website Sidebar Item', + filters=dict(parent=parent_sidebar), fields=['title', 'route', '`group`'], order_by='idx asc') - if not context.sidebar_items: + if not sidebar_data.sidebar_items: sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) if sidebar_items == None: sidebar_items = [] @@ -224,74 +46,41 @@ def add_sidebar_data(context): add_items(sidebar_items, items_via_hooks) frappe.cache().hset('portal_menu_items', frappe.session.user, sidebar_items) + sidebar_data.sidebar_items = sidebar_items - context.sidebar_items = sidebar_items + return sidebar_data - info = get_fullname_and_avatar(frappe.session.user) - context["fullname"] = info.fullname - context["user_image"] = info.avatar - context["user"] = info.name +def get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json): + sidebar_items = frappe._dict() + sidebar_json_path = get_sidebar_json_path(basepath, look_for_sidebar_json) + if not sidebar_json_path: return sidebar_items + with open(sidebar_json_path, 'r') as sidebarfile: + try: + sidebar_json = sidebarfile.read() + sidebar_items = json.loads(sidebar_json) + except json.decoder.JSONDecodeError: + frappe.throw('Invalid Sidebar JSON at ' + sidebar_json_path) -def add_metatags(context): - tags = frappe._dict(context.get("metatags") or {}) + return sidebar_items - if "og:type" not in tags: - tags["og:type"] = "article" +def get_sidebar_json_path(path, look_for=False): + ''' + Get _sidebar.json path from directory path - if "title" not in tags and context.title: - tags["title"] = context.title + :param path: path of the current diretory + :param look_for: if True, look for _sidebar.json going upwards from given path - title = tags.get("name") or tags.get("title") - if title: - tags["og:title"] = tags["twitter:title"] = title - tags["twitter:card"] = "summary" + :return: _sidebar.json path + ''' + if os.path.split(path)[1] == 'www' or path == '/' or not path: + return '' - if not tags.get('description') and context.description: - tags["description"] = context.description - - description = tags.get("description") - if description: - tags["og:description"] = tags["twitter:description"] = description - - if "image" not in tags and context.image: - tags["image"] = context.image - - image = tags.get("image") - if image: - tags["og:image"] = tags["twitter:image"] = tags["image"] = frappe.utils.get_url(image) - tags['twitter:card'] = "summary_large_image" - - if "author" not in tags and context.author: - tags["author"] = context.author - - tags["og:url"] = tags["url"] = frappe.utils.get_url(context.path) - - if "published_on" not in tags and context.published_on: - tags["published_on"] = context.published_on - - if "published_on" in tags: - tags["datePublished"] = tags["published_on"] - del tags["published_on"] - - tags["language"] = frappe.local.lang or "en" - - # Get meta tags from Website Route meta - # they can override the defaults set above - route = context.path - if route == '': - # homepage - route = frappe.db.get_single_value('Website Settings', 'home_page') - - route_exists = (route - and not route.endswith(('.js', '.css')) - and frappe.db.exists('Website Route Meta', route)) - - if route_exists: - website_route_meta = frappe.get_doc('Website Route Meta', route) - for meta_tag in website_route_meta.meta_tags: - d = meta_tag.get_meta_dict() - tags.update(d) - - # update tags in context - context.metatags = tags + sidebar_json_path = os.path.join(path, '_sidebar.json') + if os.path.exists(sidebar_json_path): + return sidebar_json_path + else: + if look_for: + return get_sidebar_json_path(os.path.split(path)[0], look_for) + else: + return '' diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index f2664fb928..5b001a55e7 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -3,7 +3,7 @@ import os import frappe from frappe.website.page_controllers.base_template_page import BaseTemplatePage -from frappe.website.context import add_sidebar_and_breadcrumbs +from frappe.website.context import get_sidebar_data from frappe.website.render import build_response from frappe.website.router import get_base_template from frappe.website.utils import (extract_comment_tag, @@ -12,29 +12,32 @@ from frappe.website.utils import (extract_comment_tag, WEBPAGE_PY_MODULE_PROPERTIES = ("base_template_path", "template", "no_cache", "sitemap", "condition_field") class TemplatePage(BaseTemplatePage): - def validate(self): - for app in frappe.get_installed_apps(frappe_last=True): - if self.find_page_in_app(app): - return True + def __init__(self, path, http_status_code=None): + super().__init__(path=path, http_status_code=http_status_code) + self.set_template_path() - def find_page_in_app(self, app): + def set_template_path(self): ''' Searches for file matching the path in the /www - and /templates/pages folders + and /templates/pages folders and sets path if match is found ''' - app_path = frappe.get_app_path(app) folders = get_start_folders() + for app in frappe.get_installed_apps(frappe_last=True): + app_path = frappe.get_app_path(app) - for dirname in folders: - search_path = os.path.join(app_path, dirname, self.path) - for p in self.get_index_path_options(search_path): - file_path = frappe.as_unicode(p) - if os.path.exists(file_path) and not os.path.isdir(file_path): - self.app = app - self.app_path = app_path - self.template_path = os.path.relpath(file_path, self.app_path) - self.basepath = os.path.dirname(file_path) - return True + for dirname in folders: + search_path = os.path.join(app_path, dirname, self.path) + for p in self.get_index_path_options(search_path): + file_path = frappe.as_unicode(p) + if os.path.exists(file_path) and not os.path.isdir(file_path): + self.app = app + self.app_path = app_path + self.template_path = os.path.relpath(file_path, self.app_path) + self.basepath = os.path.dirname(file_path) + return + + def validate(self): + return hasattr(self, 'template_path') and bool(self.template_path) def get_index_path_options(self, search_path): return (f'{search_path}{d}' for d in ('', '.html', '.md', '/index.html', '/index.md')) @@ -59,12 +62,20 @@ class TemplatePage(BaseTemplatePage): return html def post_process_context(self): + self.set_user_info() self.add_sidebar_and_breadcrumbs() self.set_missing_values() super(TemplatePage, self).post_process_context() def add_sidebar_and_breadcrumbs(self): - add_sidebar_and_breadcrumbs(self.context) + if self.basepath: + sidebar_data = get_sidebar_data(self.context.website_sidebar, self.basepath) or None + self.context.sidebar_items = sidebar_data.sidebar_items + + if self.context.add_breadcrumbs and not self.context.parents: + # TODO: set correct title and route for breadcrumbs + parent_path = os.path.dirname(self.path) + self.context.parents = [dict(route=parent_path, title=extract_title(source='', path=parent_path))] def set_pymodule(self): ''' @@ -229,6 +240,13 @@ class TemplatePage(BaseTemplatePage): # for backward compatibility self.context.docs_base_url = '/docs' + def set_user_info(self): + from frappe.utils.user import get_fullname_and_avatar + info = get_fullname_and_avatar(frappe.session.user) + self.context["fullname"] = info.fullname + self.context["user_image"] = info.avatar + self.context["user"] = info.name + def get_start_folders(): return frappe.local.flags.web_pages_folders or ('www', 'templates/pages') From 19879943102d669ad94b82a9ba89177f2430d8d2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 17 May 2021 23:37:28 +0530 Subject: [PATCH 096/868] refactor: Move unwanted code from validate - Also, removed unwanted code in render.py --- frappe/website/page_controllers/error_page.py | 5 ++- frappe/website/page_controllers/list_page.py | 11 ++++--- .../page_controllers/not_found_page.py | 8 +++-- .../page_controllers/not_permitted_page.py | 9 +++-- frappe/website/page_controllers/print_page.py | 14 +++++--- .../website/page_controllers/static_page.py | 32 ++++++++++-------- frappe/website/render.py | 33 +------------------ 7 files changed, 50 insertions(+), 62 deletions(-) diff --git a/frappe/website/page_controllers/error_page.py b/frappe/website/page_controllers/error_page.py index 1f54a5f38c..554949684f 100644 --- a/frappe/website/page_controllers/error_page.py +++ b/frappe/website/page_controllers/error_page.py @@ -1,7 +1,10 @@ from frappe.website.page_controllers.template_page import TemplatePage class ErrorPage(TemplatePage): - def __init__(self, path, http_status_code, exception): + def __init__(self, path=None, http_status_code=None, exception=None): path = 'error' super().__init__(path=path, http_status_code=http_status_code) self.http_status_code = getattr(exception, 'http_status_code', None) or http_status_code or 500 + + def validate(self): + return True diff --git a/frappe/website/page_controllers/list_page.py b/frappe/website/page_controllers/list_page.py index 2cb6ed5f26..cc6f150dd2 100644 --- a/frappe/website/page_controllers/list_page.py +++ b/frappe/website/page_controllers/list_page.py @@ -3,8 +3,9 @@ from frappe.website.page_controllers.template_page import TemplatePage class ListPage(TemplatePage): def validate(self): - if frappe.db.get_value('DocType', self.path): - frappe.local.form_dict.doctype = self.path - self.set_standard_path('list') - return True - return False + return frappe.db.exists('DocType', self.path, True) + + def render(self): + frappe.local.form_dict.doctype = self.path + self.set_standard_path('list') + return super().render() diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_controllers/not_found_page.py index 1d15877e9d..aebc0006ae 100644 --- a/frappe/website/page_controllers/not_found_page.py +++ b/frappe/website/page_controllers/not_found_page.py @@ -2,7 +2,9 @@ from frappe.website.page_controllers.template_page import TemplatePage class NotFoundPage(TemplatePage): def __init__(self, path, http_status_code): + path = '404' + http_status_code = 404 super().__init__(path=path, http_status_code=http_status_code) - self.path = '404' - self.http_status_code = 404 - self.template_path = '404' + + def validate(self): + return True diff --git a/frappe/website/page_controllers/not_permitted_page.py b/frappe/website/page_controllers/not_permitted_page.py index 61c6b88e09..3ed732d80b 100644 --- a/frappe/website/page_controllers/not_permitted_page.py +++ b/frappe/website/page_controllers/not_permitted_page.py @@ -1,13 +1,18 @@ import frappe from frappe import _ from frappe.website.page_controllers.template_page import TemplatePage +from frappe.utils import cstr class NotPermittedPage(TemplatePage): - def __init__(self, path, http_status_code): + def __init__(self, path=None, http_status_code=None, exception=''): + frappe.local.message = cstr(exception) super().__init__(path=path, http_status_code=http_status_code) self.http_status_code = 403 def validate(self): + return True + + def render(self): frappe.local.message_title = _("Not Permitted") frappe.local.response['context'] = dict( indicator_color = 'red', @@ -16,4 +21,4 @@ class NotPermittedPage(TemplatePage): fullpage=True ) self.set_standard_path('message') - return True + return super().render() diff --git a/frappe/website/page_controllers/print_page.py b/frappe/website/page_controllers/print_page.py index 6daea7fcbc..574f335f5d 100644 --- a/frappe/website/page_controllers/print_page.py +++ b/frappe/website/page_controllers/print_page.py @@ -9,11 +9,15 @@ class PrintPage(TemplatePage): def validate(self): parts = self.path.split('/', 1) if len(parts)==2: - if (frappe.db.get_value('DocType', parts[0]) - and frappe.db.get_value(parts[0], parts[1])): - frappe.form_dict.doctype = parts[0] - frappe.form_dict.name = parts[1] - self.set_standard_path('printview') + if (frappe.db.exists('DocType', parts[0], True) + and frappe.db.exists(parts[0], parts[1], True)): return True return False + + def render(self): + parts = self.path.split('/', 1) + frappe.form_dict.doctype = parts[0] + frappe.form_dict.name = parts[1] + self.set_standard_path('printview') + return super().render() diff --git a/frappe/website/page_controllers/static_page.py b/frappe/website/page_controllers/static_page.py index 8f474e71be..8c07440ebb 100644 --- a/frappe/website/page_controllers/static_page.py +++ b/frappe/website/page_controllers/static_page.py @@ -7,27 +7,31 @@ from werkzeug.wsgi import wrap_file import frappe from frappe.website.page_controllers.web_page import WebPage +UNSUPPORTED_STATIC_PAGE_TYPES = ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json') class StaticPage(WebPage): - def validate(self): - if ('.' not in self.path): - return False - extension = self.path.rsplit('.', 1)[-1] - if extension in ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json'): - return False + def __init__(self, path, http_status_code=None): + super().__init__(path=path, http_status_code=http_status_code) + self.set_file_path() - if self.find_path_in_apps(): - return True - - return False - - def find_path_in_apps(self): + def set_file_path(self): + self.file_path = '' + if not self.is_valid_file_path(): return for app in frappe.get_installed_apps(): file_path = frappe.get_app_path(app, 'www') + '/' + self.path if os.path.exists(file_path): self.file_path = file_path - return True - return False + + def validate(self): + return self.is_valid_file_path() and self.file_path + + def is_valid_file_path(self): + if ('.' not in self.path): + return False + extension = self.path.rsplit('.', 1)[-1] + if extension in UNSUPPORTED_STATIC_PAGE_TYPES: + return False + return True def render(self): f = open(self.file_path, 'rb') diff --git a/frappe/website/render.py b/frappe/website/render.py index 87eddf3463..6a1d5a404e 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -11,9 +11,8 @@ from werkzeug.wrappers import Response import frappe import frappe.sessions -from frappe.website.context import get_context from frappe.website.router import evaluate_dynamic_routes -from frappe.website.utils import (can_cache, get_home_page, get_next_link, get_toc) +from frappe.website.utils import get_home_page def build_response(path, data, http_status_code, headers=None): @@ -54,36 +53,6 @@ def add_preload_headers(response): import traceback traceback.print_exc() - -def build_page(path): - if not getattr(frappe.local, "path", None): - frappe.local.path = path - - context = get_context(path) - - if context.source: - html = frappe.render_template(context.source, context) - elif context.template: - if path.endswith('min.js'): - html = frappe.get_jloader().get_source(frappe.get_jenv(), context.template)[0] - else: - html = frappe.get_template(context.template).render(context) - - if '{index}' in html: - html = html.replace('{index}', get_toc(context.route)) - - if '{next}' in html: - html = html.replace('{next}', get_next_link(context.route)) - - # html = frappe.get_template(context.base_template_path).render(context) - - if can_cache(context.no_cache): - page_cache = frappe.cache().hget("website_page", path) or {} - page_cache[frappe.local.lang] = html - frappe.cache().hset("website_page", path, page_cache) - - return html - def resolve_path(path): if not path: path = "index" From 5318697c0fd74d7fd534e1e645fdd6e34464cb08 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 08:40:37 +0530 Subject: [PATCH 097/868] feat: Add redirect page --- frappe/website/page_controllers/redirect_page.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 frappe/website/page_controllers/redirect_page.py diff --git a/frappe/website/page_controllers/redirect_page.py b/frappe/website/page_controllers/redirect_page.py new file mode 100644 index 0000000000..f3a0ba6e7f --- /dev/null +++ b/frappe/website/page_controllers/redirect_page.py @@ -0,0 +1,16 @@ +import frappe +from frappe.website.render import build_response + +class RedirectPage(object): + def __init__(self, path, http_status_code=301): + self.path = path + self.http_status_code = http_status_code + + def validate(self): + return True + + def render(self): + return build_response(self.path, "", 301, { + "Location": frappe.flags.redirect_location or (frappe.local.response or {}).get('location'), + "Cache-Control": "no-store, no-cache, must-revalidate" + }) From a02e5f766a70258ab05e741afc64263f06970137 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 08:43:49 +0530 Subject: [PATCH 098/868] refactor: Add path_resolver to separate route resolving part --- frappe/website/path_resolver.py | 67 +++++++++++++++++++++++++++++++++ frappe/website/serve.py | 54 +++++++++++--------------- 2 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 frappe/website/path_resolver.py diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py new file mode 100644 index 0000000000..d6e43f4f1f --- /dev/null +++ b/frappe/website/path_resolver.py @@ -0,0 +1,67 @@ +from frappe.website.redirect import resolve_redirect +from frappe.website.render import resolve_path +import frappe + +from frappe.website.page_controllers.document_page import DocumentPage +from frappe.website.page_controllers.list_page import ListPage +from frappe.website.page_controllers.not_found_page import NotFoundPage +from frappe.website.page_controllers.print_page import PrintPage +from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_controllers.static_page import StaticPage +from frappe.website.page_controllers.web_form import WebFormPage + +class PathResolver(): + def __init__(self, path, http_status_code=None): + self._path = path + self.http_status_code = http_status_code + # self.url_map = get_url_map() + + @property + def path(self): + return self._path.strip('/ ') + + def resolve(self): + '''Returns endpoint and a renderer instance that can render the endpoint''' + query_string = frappe.local.request.query_string + resolve_redirect(self.path, query_string) + endpoint = resolve_path(self.path) + # urls = self.url_map.bind_to_environ(frappe.local.request.environ) + + renderers = (StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage) + + for renderer in renderers: + renderer_instance = renderer(endpoint, self.http_status_code) + can_render = renderer_instance.validate() + if can_render: + return endpoint, renderer_instance + + return endpoint, None + +# #> Path > Path > resolve using url_map > path.endpoint +# # +# # +# # +# # pathclass url_map + +# def get_url_map(): +# Map([Rule('/', endpoint=get_home_page, defaults={'renderer': TemplatePage})]) + + +# query_string = None +# response = None + +# if not path: +# path = frappe.local.request.path +# query_string = frappe.local.request.query_string + +# try: +# path = path.strip('/ ') +# resolve_redirect(path, query_string) +# path = resolve_path(path) +# # there is no way to determine the type of the page based on the route +# # so evaluate each type of page sequentially +# renderers = [StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage] +# for renderer in renderers: +# response = renderer(path, http_status_code).get() +# if response: +# break diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 47ca0aa1d2..bdec8a16ba 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,49 +1,37 @@ import frappe -from frappe.utils import cstr -from frappe.website.page_controllers.document_page import DocumentPage from frappe.website.page_controllers.error_page import ErrorPage -from frappe.website.page_controllers.list_page import ListPage -from frappe.website.page_controllers.not_found_page import NotFoundPage from frappe.website.page_controllers.not_permitted_page import NotPermittedPage -from frappe.website.page_controllers.print_page import PrintPage -from frappe.website.page_controllers.template_page import TemplatePage -from frappe.website.page_controllers.static_page import StaticPage -from frappe.website.page_controllers.web_form import WebFormPage - -from frappe.website.redirect import resolve_redirect -from frappe.website.render import build_response, resolve_path +from frappe.website.page_controllers.redirect_page import RedirectPage +from frappe.website.path_resolver import PathResolver +from frappe.website.utils import can_cache def get_response(path=None, http_status_code=200): - """render html page""" - query_string = None + """Resolves path and renders page""" response = None + path = path or frappe.local.request.path + endpoint = path + # if can_cache(): + # # return rendered page + # page_cache = frappe.cache().hget("website_page", path) + # if page_cache and frappe.local.lang in page_cache: + # out = page_cache[frappe.local.lang] - if not path: - path = frappe.local.request.path - query_string = frappe.local.request.query_string + # if out: + # frappe.local.response.from_cache = True + # return out try: - path = path.strip('/ ') - resolve_redirect(path, query_string) - path = resolve_path(path) - # there is no way to determine the type of the page based on the route - # so evaluate each type of page sequentially - renderers = [StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage] - for renderer in renderers: - response = renderer(path, http_status_code).get() - if response: - break + path_resolver = PathResolver(path, http_status_code) + endpoint, renderer_instance = path_resolver.resolve() + if renderer_instance: + response = renderer_instance.render() except frappe.Redirect: - return build_response(path, "", 301, { - "Location": frappe.flags.redirect_location or (frappe.local.response or {}).get('location'), - "Cache-Control": "no-store, no-cache, must-revalidate" - }) + return RedirectPage(endpoint or path, http_status_code).render() except frappe.PermissionError as e: - frappe.local.message = cstr(e) - response = NotPermittedPage(path, http_status_code).get() + response = NotPermittedPage(endpoint, http_status_code, exception=e).render() except Exception as e: - response = ErrorPage(path, http_status_code, exception=e).get() + response = ErrorPage(exception=e).render() return response From c8d588819f940b89e8a48a5190ecf22a188b5ece Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 09:05:02 +0530 Subject: [PATCH 099/868] refactor: Move get_sidebar_data method to utils - Also, rename get_sidebar_data to get_sidebar_items & delete context.py - Remove commented text --- frappe/website/context.py | 86 ---------------- .../website/page_controllers/template_page.py | 5 +- frappe/website/path_resolver.py | 39 +------- frappe/website/serve.py | 4 +- frappe/website/utils.py | 97 +++++++++++++++++-- 5 files changed, 99 insertions(+), 132 deletions(-) delete mode 100644 frappe/website/context.py diff --git a/frappe/website/context.py b/frappe/website/context.py deleted file mode 100644 index c8dade5b8b..0000000000 --- a/frappe/website/context.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt -import json -import os - -import frappe -from frappe.model.document import Document - -def get_sidebar_data(parent_sidebar, basepath): - import frappe.www.list - sidebar_data = frappe._dict() - - hooks = frappe.get_hooks('look_for_sidebar_json') - look_for_sidebar_json = hooks[0] if hooks else 0 - - if basepath and look_for_sidebar_json: - sidebar_items = get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json) - sidebar_data['sidebar_items'] = sidebar_items - - if not sidebar_data.sidebar_items and parent_sidebar: - sidebar_data.sidebar_items = frappe.get_all('Website Sidebar Item', - filters=dict(parent=parent_sidebar), fields=['title', 'route', '`group`'], - order_by='idx asc') - - if not sidebar_data.sidebar_items: - sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) - if sidebar_items == None: - sidebar_items = [] - roles = frappe.get_roles() - portal_settings = frappe.get_doc('Portal Settings', 'Portal Settings') - - def add_items(sidebar_items, items): - for d in items: - if d.get('enabled') and ((not d.get('role')) or d.get('role') in roles): - sidebar_items.append(d.as_dict() if isinstance(d, Document) else d) - - if not portal_settings.hide_standard_menu: - add_items(sidebar_items, portal_settings.get('menu')) - - if portal_settings.custom_menu: - add_items(sidebar_items, portal_settings.get('custom_menu')) - - items_via_hooks = frappe.get_hooks('portal_menu_items') - if items_via_hooks: - for i in items_via_hooks: i['enabled'] = 1 - add_items(sidebar_items, items_via_hooks) - - frappe.cache().hset('portal_menu_items', frappe.session.user, sidebar_items) - sidebar_data.sidebar_items = sidebar_items - - return sidebar_data - -def get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json): - sidebar_items = frappe._dict() - sidebar_json_path = get_sidebar_json_path(basepath, look_for_sidebar_json) - if not sidebar_json_path: return sidebar_items - - with open(sidebar_json_path, 'r') as sidebarfile: - try: - sidebar_json = sidebarfile.read() - sidebar_items = json.loads(sidebar_json) - except json.decoder.JSONDecodeError: - frappe.throw('Invalid Sidebar JSON at ' + sidebar_json_path) - - return sidebar_items - -def get_sidebar_json_path(path, look_for=False): - ''' - Get _sidebar.json path from directory path - - :param path: path of the current diretory - :param look_for: if True, look for _sidebar.json going upwards from given path - - :return: _sidebar.json path - ''' - if os.path.split(path)[1] == 'www' or path == '/' or not path: - return '' - - sidebar_json_path = os.path.join(path, '_sidebar.json') - if os.path.exists(sidebar_json_path): - return sidebar_json_path - else: - if look_for: - return get_sidebar_json_path(os.path.split(path)[0], look_for) - else: - return '' diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 5b001a55e7..12f459afd7 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -3,7 +3,7 @@ import os import frappe from frappe.website.page_controllers.base_template_page import BaseTemplatePage -from frappe.website.context import get_sidebar_data +from frappe.website.utils import get_sidebar_items from frappe.website.render import build_response from frappe.website.router import get_base_template from frappe.website.utils import (extract_comment_tag, @@ -69,8 +69,7 @@ class TemplatePage(BaseTemplatePage): def add_sidebar_and_breadcrumbs(self): if self.basepath: - sidebar_data = get_sidebar_data(self.context.website_sidebar, self.basepath) or None - self.context.sidebar_items = sidebar_data.sidebar_items + self.context.sidebar_items = get_sidebar_items(self.context.website_sidebar, self.basepath) if self.context.add_breadcrumbs and not self.context.parents: # TODO: set correct title and route for breadcrumbs diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index d6e43f4f1f..b9f8972380 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -1,20 +1,19 @@ -from frappe.website.redirect import resolve_redirect -from frappe.website.render import resolve_path import frappe - from frappe.website.page_controllers.document_page import DocumentPage from frappe.website.page_controllers.list_page import ListPage from frappe.website.page_controllers.not_found_page import NotFoundPage from frappe.website.page_controllers.print_page import PrintPage -from frappe.website.page_controllers.template_page import TemplatePage from frappe.website.page_controllers.static_page import StaticPage +from frappe.website.page_controllers.template_page import TemplatePage from frappe.website.page_controllers.web_form import WebFormPage +from frappe.website.redirect import resolve_redirect +from frappe.website.render import resolve_path + class PathResolver(): def __init__(self, path, http_status_code=None): self._path = path self.http_status_code = http_status_code - # self.url_map = get_url_map() @property def path(self): @@ -25,7 +24,6 @@ class PathResolver(): query_string = frappe.local.request.query_string resolve_redirect(self.path, query_string) endpoint = resolve_path(self.path) - # urls = self.url_map.bind_to_environ(frappe.local.request.environ) renderers = (StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage) @@ -36,32 +34,3 @@ class PathResolver(): return endpoint, renderer_instance return endpoint, None - -# #> Path > Path > resolve using url_map > path.endpoint -# # -# # -# # -# # pathclass url_map - -# def get_url_map(): -# Map([Rule('/', endpoint=get_home_page, defaults={'renderer': TemplatePage})]) - - -# query_string = None -# response = None - -# if not path: -# path = frappe.local.request.path -# query_string = frappe.local.request.query_string - -# try: -# path = path.strip('/ ') -# resolve_redirect(path, query_string) -# path = resolve_path(path) -# # there is no way to determine the type of the page based on the route -# # so evaluate each type of page sequentially -# renderers = [StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage] -# for renderer in renderers: -# response = renderer(path, http_status_code).get() -# if response: -# break diff --git a/frappe/website/serve.py b/frappe/website/serve.py index bdec8a16ba..9b28fd2e3b 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,10 +1,10 @@ import frappe - from frappe.website.page_controllers.error_page import ErrorPage from frappe.website.page_controllers.not_permitted_page import NotPermittedPage from frappe.website.page_controllers.redirect_page import RedirectPage from frappe.website.path_resolver import PathResolver -from frappe.website.utils import can_cache + +#from frappe.website.utils import can_cache def get_response(path=None, http_status_code=200): """Resolves path and renders page""" diff --git a/frappe/website/utils.py b/frappe/website/utils.py index a5fe9c3986..723d878fac 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -2,16 +2,21 @@ # MIT License. See license.txt from __future__ import unicode_literals -import functools -import re -import os -import frappe -import yaml -from six import iteritems +import functools +import json +import os +import re + +import yaml from past.builtins import cmp +from six import iteritems + +import frappe +from frappe.model.document import Document from frappe.utils import md_to_html + def delete_page_cache(path): cache = frappe.cache() cache.delete_value('full_index') @@ -439,3 +444,83 @@ def get_frontmatter(string): "attributes": yaml.safe_load(frontmatter), "body": body, } + +def get_sidebar_items(parent_sidebar, basepath): + import frappe.www.list + sidebar_items = [] + + hooks = frappe.get_hooks('look_for_sidebar_json') + look_for_sidebar_json = hooks[0] if hooks else 0 + + if basepath and look_for_sidebar_json: + sidebar_items = get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json) + + if not sidebar_items and parent_sidebar: + sidebar_items = frappe.get_all('Website Sidebar Item', + filters=dict(parent=parent_sidebar), fields=['title', 'route', '`group`'], + order_by='idx asc') + + if not sidebar_items: + sidebar_items = get_portal_sidebar_items() + + return sidebar_items + + +def get_portal_sidebar_items(): + sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) + if sidebar_items == None: + sidebar_items = [] + roles = frappe.get_roles() + portal_settings = frappe.get_doc('Portal Settings', 'Portal Settings') + + def add_items(sidebar_items, items): + for d in items: + if d.get('enabled') and ((not d.get('role')) or d.get('role') in roles): + sidebar_items.append(d.as_dict() if isinstance(d, Document) else d) + + if not portal_settings.hide_standard_menu: + add_items(sidebar_items, portal_settings.get('menu')) + + if portal_settings.custom_menu: + add_items(sidebar_items, portal_settings.get('custom_menu')) + + items_via_hooks = frappe.get_hooks('portal_menu_items') + if items_via_hooks: + for i in items_via_hooks: i['enabled'] = 1 + add_items(sidebar_items, items_via_hooks) + + frappe.cache().hset('portal_menu_items', frappe.session.user, sidebar_items) + + return sidebar_items + +def get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json): + sidebar_items = frappe._dict() + sidebar_json_path = get_sidebar_json_path(basepath, look_for_sidebar_json) + if not sidebar_json_path: return sidebar_items + + with open(sidebar_json_path, 'r') as sidebarfile: + try: + sidebar_json = sidebarfile.read() + sidebar_items = json.loads(sidebar_json) + except json.decoder.JSONDecodeError: + frappe.throw('Invalid Sidebar JSON at ' + sidebar_json_path) + + return sidebar_items + +def get_sidebar_json_path(path, look_for=False): + '''Get _sidebar.json path from directory path + :param path: path of the current diretory + :param look_for: if True, look for _sidebar.json going upwards from given path + :return: _sidebar.json path + ''' + if os.path.split(path)[1] == 'www' or path == '/' or not path: + return '' + + sidebar_json_path = os.path.join(path, '_sidebar.json') + if os.path.exists(sidebar_json_path): + return sidebar_json_path + else: + if look_for: + return get_sidebar_json_path(os.path.split(path)[0], look_for) + else: + return '' From d6a539362d1a3401f549f6788450116004d6b986 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 09:13:13 +0530 Subject: [PATCH 100/868] style: Fix formatting issue --- frappe/website/page_controllers/static_page.py | 3 ++- frappe/website/utils.py | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frappe/website/page_controllers/static_page.py b/frappe/website/page_controllers/static_page.py index 8c07440ebb..767cc872d1 100644 --- a/frappe/website/page_controllers/static_page.py +++ b/frappe/website/page_controllers/static_page.py @@ -16,7 +16,8 @@ class StaticPage(WebPage): def set_file_path(self): self.file_path = '' - if not self.is_valid_file_path(): return + if not self.is_valid_file_path(): + return for app in frappe.get_installed_apps(): file_path = frappe.get_app_path(app, 'www') + '/' + self.path if os.path.exists(file_path): diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 723d878fac..2d16658efb 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -468,7 +468,7 @@ def get_sidebar_items(parent_sidebar, basepath): def get_portal_sidebar_items(): sidebar_items = frappe.cache().hget('portal_menu_items', frappe.session.user) - if sidebar_items == None: + if sidebar_items is None: sidebar_items = [] roles = frappe.get_roles() portal_settings = frappe.get_doc('Portal Settings', 'Portal Settings') @@ -486,7 +486,8 @@ def get_portal_sidebar_items(): items_via_hooks = frappe.get_hooks('portal_menu_items') if items_via_hooks: - for i in items_via_hooks: i['enabled'] = 1 + for i in items_via_hooks: + i['enabled'] = 1 add_items(sidebar_items, items_via_hooks) frappe.cache().hset('portal_menu_items', frappe.session.user, sidebar_items) @@ -494,9 +495,10 @@ def get_portal_sidebar_items(): return sidebar_items def get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json): - sidebar_items = frappe._dict() + sidebar_items = [] sidebar_json_path = get_sidebar_json_path(basepath, look_for_sidebar_json) - if not sidebar_json_path: return sidebar_items + if not sidebar_json_path: + return sidebar_items with open(sidebar_json_path, 'r') as sidebarfile: try: From 0c575f02eae7c66861a12b9c264d8ae05c11e760 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 11:43:42 +0530 Subject: [PATCH 101/868] fix: Handle encoding issue and some edge cases --- frappe/website/page_controllers/template_page.py | 2 +- frappe/website/path_resolver.py | 2 +- frappe/website/serve.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 12f459afd7..9f3bf66701 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -234,7 +234,7 @@ class TemplatePage(BaseTemplatePage): self.context.url_prefix += '/' self.context.path = self.path - self.context.pathname = frappe.local.path + self.context.pathname = frappe.local.path if hasattr(frappe, 'local') else self.path # for backward compatibility self.context.docs_base_url = '/docs' diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index b9f8972380..1368932792 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -21,7 +21,7 @@ class PathResolver(): def resolve(self): '''Returns endpoint and a renderer instance that can render the endpoint''' - query_string = frappe.local.request.query_string + query_string = frappe.local.request.query_string if hasattr(frappe.local, 'request') else None resolve_redirect(self.path, query_string) endpoint = resolve_path(self.path) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 9b28fd2e3b..7a93ada825 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -37,4 +37,4 @@ def get_response(path=None, http_status_code=200): def get_response_content(path=None, http_status_code=200): response = get_response(path, http_status_code) - return response.data + return str(response.data, 'utf-8') From ca89fa6a32a7bfb4488bb5af28f6af29aa0cf915 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 18 May 2021 14:31:34 +0530 Subject: [PATCH 102/868] fix: Edit & Delete Card --- frappe/desk/desktop.py | 19 +++++++-- frappe/desk/doctype/workspace/workspace.py | 13 ++++-- .../public/js/frappe/widgets/links_widget.js | 12 ++++-- .../public/js/frappe/widgets/widget_dialog.js | 6 +-- .../public/js/frappe/widgets/widget_group.js | 10 ++--- frappe/public/js/frappe/wiki_blocks/card.js | 40 ++++++++++++------- .../public/js/frappe/wiki_blocks/shortcut.js | 12 +++--- 7 files changed, 74 insertions(+), 38 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 2a09978744..3713a489e3 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -550,10 +550,23 @@ def save_new_widget(page, new_widgets): if widgets.card: original_page.build_links_table_from_card(widgets.card) + # remove duplicate and unwanted widgets content = frappe.db.get_value("Internal Wiki Page", page, "content") - for wid in ['shortcut']: - widd = [x['data'][ wid + '_name'] for x in json.loads(content) if x['type'] == wid] - original_page.set(wid+'s', [ele for ele in original_page.get(wid+'s') if ele.label in widd]) + page_widgets = {} + for wid in ['shortcut', 'card', 'chart']: + # get list of widget's name from internal wiki page + page_widgets[wid] = [x['data'][wid + '_name'] for x in json.loads(content) if x['type'] == wid] + + updated_widgets = [] + original_page.get('shortcuts').reverse() + for w in original_page.get('shortcuts'): + if w.label in page_widgets['shortcut'] and w.label not in [x.label for x in updated_widgets]: + updated_widgets.append(w) + original_page.set('shortcuts', updated_widgets) + + for i, v in enumerate(original_page.links): + if v.type == 'Card Break' and v.label not in page_widgets['card']: + del original_page.links[ i : i+v.link_count+1] try: original_page.save(ignore_permissions=True) diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 18aa383455..7e50b8db70 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -105,11 +105,18 @@ class Workspace(Document): for idx, card in enumerate(config): links = loads(card.get('links')) + # remove duplicate before adding + duplicate_links = [x for x in self.links if(x.label == card.get('label') and x.type == 'Card Break')] + for v in duplicate_links: + del self.links[ v.idx-1 : v.idx+v.link_count] + self.append('links', { "label": card.get('label'), "type": "Card Break", "icon": card.get('icon'), - "hidden": card.get('hidden') or False + "hidden": card.get('hidden') or False, + "link_count": card.get('link_count'), + "idx": self.links[-1].idx + 1 }) for link in links: @@ -121,10 +128,10 @@ class Workspace(Document): "onboard": link.get('onboard'), "only_for": link.get('only_for'), "dependencies": link.get('dependencies'), - "is_query_report": link.get('is_query_report') + "is_query_report": link.get('is_query_report'), + "idx": self.links[-1].idx + 1 }) - def disable_saving_as_standard(): return frappe.flags.in_install or \ frappe.flags.in_patch or \ diff --git a/frappe/public/js/frappe/widgets/links_widget.js b/frappe/public/js/frappe/widgets/links_widget.js index 05280a22c8..26d52c1fcc 100644 --- a/frappe/public/js/frappe/widgets/links_widget.js +++ b/frappe/public/js/frappe/widgets/links_widget.js @@ -12,14 +12,18 @@ export default class LinksWidget extends Widget { return { name: this.name, links: JSON.stringify(this.links), + link_count: this.links.length, label: this.label, hidden: this.hidden, }; } set_body() { - this.options = {}; - this.options.links = this.links; + + if (!this.options) { + this.options = {}; + this.options.links = this.links; + } this.widget.addClass("links-widget-box"); const is_link_disabled = item => { return item.dependencies && item.incomplete_dependencies; @@ -74,7 +78,9 @@ export default class LinksWidget extends Widget { ${get_link_for_item(item)} `); }); - + if (this.in_customize_mode) { + this.body.empty(); + } this.link_list.forEach(link => link.appendTo(this.body)); } diff --git a/frappe/public/js/frappe/widgets/widget_dialog.js b/frappe/public/js/frappe/widgets/widget_dialog.js index 5bcaaf9e3e..02be3bd15a 100644 --- a/frappe/public/js/frappe/widgets/widget_dialog.js +++ b/frappe/public/js/frappe/widgets/widget_dialog.js @@ -142,9 +142,9 @@ class CardDialog extends WidgetDialog { fieldtype: 'Table', label: __('Card Links'), editable_grid: 1, - data: this.data || [], + data: me.values ? JSON.parse(me.values.links) : [], get_data: () => { - return this.data || []; + return me.values ? JSON.parse(me.values.links) : []; }, fields: [ { @@ -529,7 +529,7 @@ export default function get_dialog_constructor(type) { chart: ChartDialog, shortcut: ShortcutDialog, number_card: NumberCardDialog, - card: CardDialog, + links: CardDialog, }; return widget_map[type] || WidgetDialog; diff --git a/frappe/public/js/frappe/widgets/widget_group.js b/frappe/public/js/frappe/widgets/widget_group.js index 913a362932..d8f92edc5d 100644 --- a/frappe/public/js/frappe/widgets/widget_group.js +++ b/frappe/public/js/frappe/widgets/widget_group.js @@ -205,12 +205,12 @@ export class SingleWidgetGroup { widget_type: this.type, container: this.container, height: this.height || null, + options: { + ...this.options, + on_delete: () => this.on_delete(), + on_edit: () => this.on_edit(widget_object) + } }); - widget_object.options = { - ...this.options, - on_delete: () => this.on_delete(), - on_edit: () => this.on_edit(widget_object) - }; this.widgets_list.push(widget_object); this.widgets_dict[widget.name] = widget_object; diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index 89821129e0..5426fd24ce 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -11,9 +11,10 @@ export default class Card { return true; } - constructor({data, api, config, readOnly}) { + constructor({data, api, config, readOnly, block}) { this.data = data; this.api = api; + this.block = block; this.config = config; this.readOnly = readOnly; this.sections = {}; @@ -28,7 +29,7 @@ export default class Card { allow_create: this.allow_customization, allow_delete: this.allow_customization, allow_hiding: false, - allow_edit: false, + allow_edit: true, }; } @@ -64,24 +65,25 @@ export default class Card { } _new_card() { - const dialog_class = get_dialog_constructor('card'); + const dialog_class = get_dialog_constructor('links'); this.dialog = new dialog_class({ label: this.label, type: 'card', primary_action: (widget) => { widget.in_customize_mode = 1; - let wid = frappe.widget.make_widget({ + this.card_widget = frappe.widget.make_widget({ ...widget, widget_type: 'links', - container: this.wrapper + container: this.wrapper, + options: { + ...this.options, + on_delete: () => this.api.blocks.delete(), + on_edit: () => this.on_edit(this.card_widget) + } }); - wid.options = { - ...this.options, - on_delete: () => this.api.blocks.delete() - }; - wid.customize(this.options); - this.wrapper.setAttribute("card_name", wid.label); - this.new_card_widget = wid.get_config(); + this.card_widget.customize(this.options); + this.wrapper.setAttribute("card_name", this.card_widget.label); + this.new_card_widget = this.card_widget.get_config(); }, }); @@ -156,22 +158,30 @@ export default class Card { this.card_field.make(); } + on_edit(card_obj) { + let card = card_obj.get_config(); + this.card_widget.widgets = card; + this.wrapper.setAttribute("card_name", card.label); + this.new_card_widget = card_obj.get_config(); + } + _make_cards(card_name) { let card = this.config.page_data.cards.items.find(obj => { return obj.label == card_name; }); this.wrapper.innerHTML = ''; card.in_customize_mode = !this.readOnly; - let card_widget = new frappe.widget.SingleWidgetGroup({ + this.card_widget = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "links", options: this.options, widgets: card, - api: this.api + api: this.api, + block: this.block }); this.wrapper.setAttribute("card_name", card_name); if (!this.readOnly) { - card_widget.customize(); + this.card_widget.customize(); } } } \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index f57c9ef7f1..ba98cbc382 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -73,13 +73,13 @@ export default class Shortcut { this.shortcut_widget = frappe.widget.make_widget({ ...widget, widget_type: 'shortcut', - container: this.wrapper + container: this.wrapper, + options: { + ...this.options, + on_delete: () => this.api.blocks.delete(), + on_edit: () => this.on_edit(this.shortcut_widget) + } }); - this.shortcut_widget.options = { - ...this.options, - on_delete: () => this.api.blocks.delete(), - on_edit: () => this.on_edit(this.shortcut_widget) - }; this.shortcut_widget.customize(this.options); this.wrapper.setAttribute("shortcut_name", this.shortcut_widget.label); this.new_shortcut_widget = this.shortcut_widget.get_config(); From c217b32fa91c1a8e252a343bcb21f9c7283ca2e5 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 15:41:23 +0530 Subject: [PATCH 103/868] fix: Add cache_html decorator to cache HTML --- .../website/page_controllers/template_page.py | 5 +++-- frappe/website/serve.py | 10 --------- frappe/website/utils.py | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 9f3bf66701..635b8a56fe 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -6,8 +6,8 @@ from frappe.website.page_controllers.base_template_page import BaseTemplatePage from frappe.website.utils import get_sidebar_items from frappe.website.render import build_response from frappe.website.router import get_base_template -from frappe.website.utils import (extract_comment_tag, - extract_title, get_next_link, get_toc, get_frontmatter) +from frappe.website.utils import (extract_comment_tag, extract_title, + get_next_link, get_toc, get_frontmatter, cache_html) WEBPAGE_PY_MODULE_PROPERTIES = ("base_template_path", "template", "no_cache", "sitemap", "condition_field") @@ -45,6 +45,7 @@ class TemplatePage(BaseTemplatePage): def render(self): return build_response(self.path, self.get_html(), self.http_status_code, self.headers) + @cache_html def get_html(self): # context object should be separate from self for security # because it will be accessed via the user defined template diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 7a93ada825..7010b768d8 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -4,22 +4,12 @@ from frappe.website.page_controllers.not_permitted_page import NotPermittedPage from frappe.website.page_controllers.redirect_page import RedirectPage from frappe.website.path_resolver import PathResolver -#from frappe.website.utils import can_cache def get_response(path=None, http_status_code=200): """Resolves path and renders page""" response = None path = path or frappe.local.request.path endpoint = path - # if can_cache(): - # # return rendered page - # page_cache = frappe.cache().hget("website_page", path) - # if page_cache and frappe.local.lang in page_cache: - # out = page_cache[frappe.local.lang] - - # if out: - # frappe.local.response.from_cache = True - # return out try: path_resolver = PathResolver(path, http_status_code) diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 2d16658efb..576d1d911c 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -7,6 +7,7 @@ import functools import json import os import re +from functools import wraps import yaml from past.builtins import cmp @@ -526,3 +527,24 @@ def get_sidebar_json_path(path, look_for=False): return get_sidebar_json_path(os.path.split(path)[0], look_for) else: return '' + +def cache_html(func): + @wraps(func) + def cache_html_decorator(*args, **kwargs): + if can_cache(): + html = None + page_cache = frappe.cache().hget("website_page", args[0].path) + if page_cache and frappe.local.lang in page_cache: + html = page_cache[frappe.local.lang] + if html: + frappe.local.response.from_cache = True + return html + html = func(*args, **kwargs) + if can_cache(): + page_cache = frappe.cache().hget("website_page", args[0].path) or {} + page_cache[frappe.local.lang] = html + frappe.cache().hset("website_page", args[0].path, page_cache) + + return html + + return cache_html_decorator From c551338c0d7a665730ba845ccda5b4f09107301e Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 18 May 2021 15:41:31 +0530 Subject: [PATCH 104/868] fix: ensure website theme is applied correctly --- frappe/public/scss/website/css_variables.scss | 2 ++ frappe/public/scss/website/sidebar.scss | 6 +++--- .../doctype/website_theme/website_theme_template.scss | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/frappe/public/scss/website/css_variables.scss b/frappe/public/scss/website/css_variables.scss index 2aeb842802..463a0db49e 100644 --- a/frappe/public/scss/website/css_variables.scss +++ b/frappe/public/scss/website/css_variables.scss @@ -28,4 +28,6 @@ --font-size-4xl: #{$font-size-4xl}; --font-size-5xl: #{$font-size-5xl}; --font-size-6xl: #{$font-size-6xl}; + + --card-border-radius: #{$card-border-radius}; } diff --git a/frappe/public/scss/website/sidebar.scss b/frappe/public/scss/website/sidebar.scss index b13eaf2a74..76956c9136 100644 --- a/frappe/public/scss/website/sidebar.scss +++ b/frappe/public/scss/website/sidebar.scss @@ -10,7 +10,7 @@ margin-top: 0.25rem; border-radius: 0.375rem; font-size: $font-size-sm; - color: $gray-600; + color: var(--text-color); text-decoration: none; font-weight: 500; @include transition(); @@ -26,8 +26,8 @@ } .sidebar-item a.active { - color: $primary; - background-color: $primary-light; + color: var(--primary); + background-color: var(--primary-light); } .sidebar-item-icon { diff --git a/frappe/website/doctype/website_theme/website_theme_template.scss b/frappe/website/doctype/website_theme/website_theme_template.scss index fbd640690b..2a67baf541 100644 --- a/frappe/website/doctype/website_theme/website_theme_template.scss +++ b/frappe/website/doctype/website_theme/website_theme_template.scss @@ -30,3 +30,14 @@ body { // Custom Theme {{ custom_scss or '' }} + +:root { + --primary: #{$primary}; + --primary-color: #{$primary}; + --primary-light: #{$primary-light}; + --light: #{$light}; + --bg-color: #{$body-bg}; + --text-color: #{$body-color}; + --text-light: #{$body-color}; +} + From a74352cfad16c3ba3650087c7403aaee7431bae1 Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 18 May 2021 16:19:25 +0530 Subject: [PATCH 105/868] fix: button colors --- frappe/public/scss/common/buttons.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/public/scss/common/buttons.scss b/frappe/public/scss/common/buttons.scss index 591dc5bba6..de3a4cfc20 100644 --- a/frappe/public/scss/common/buttons.scss +++ b/frappe/public/scss/common/buttons.scss @@ -48,13 +48,13 @@ $active-border: darken($primary-light, 12.5%) ); - color: var(--blue-500); + color: var(--primary); &:hover, &:active { - color: var(--blue-500); + color: var(--primary); } &:focus { - box-shadow: 0 0 0 0.2rem var(--blue-50) + box-shadow: 0 0 0 0.2rem var(--primary-light); } } @@ -77,11 +77,11 @@ } .btn.btn-primary { - background-color: var(--primary-color); + background-color: var(--primary); color: var(--white); white-space: nowrap; --icon-stroke: currentColor; - --icon-fill-bg: var(--primary-color); + --icon-fill-bg: var(--primary); } .btn.btn-danger { From 7ce6a776d04bfa0b52c562275f6c8198bfebce07 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 18 May 2021 16:44:14 +0530 Subject: [PATCH 106/868] fix: Remove duplicate card fix --- frappe/desk/doctype/workspace/workspace.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 7e50b8db70..d9bf5fa618 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -106,9 +106,9 @@ class Workspace(Document): links = loads(card.get('links')) # remove duplicate before adding - duplicate_links = [x for x in self.links if(x.label == card.get('label') and x.type == 'Card Break')] - for v in duplicate_links: - del self.links[ v.idx-1 : v.idx+v.link_count] + for idx, link in enumerate(self.links): + if link.label == card.get('label') and link.type == 'Card Break': + del self.links[idx : idx + link.link_count + 1] self.append('links', { "label": card.get('label'), From c6c2eeed72b2cd4e4ed572e37ca64bf6884b6225 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 18 May 2021 17:54:42 +0530 Subject: [PATCH 107/868] fix: Add, Edit & Delete Chart --- frappe/desk/desktop.py | 41 +++++---- frappe/public/js/frappe/wiki_blocks/chart.js | 89 +++++++++++++------- 2 files changed, 83 insertions(+), 47 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 3713a489e3..6d0356747d 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -551,22 +551,7 @@ def save_new_widget(page, new_widgets): original_page.build_links_table_from_card(widgets.card) # remove duplicate and unwanted widgets - content = frappe.db.get_value("Internal Wiki Page", page, "content") - page_widgets = {} - for wid in ['shortcut', 'card', 'chart']: - # get list of widget's name from internal wiki page - page_widgets[wid] = [x['data'][wid + '_name'] for x in json.loads(content) if x['type'] == wid] - - updated_widgets = [] - original_page.get('shortcuts').reverse() - for w in original_page.get('shortcuts'): - if w.label in page_widgets['shortcut'] and w.label not in [x.label for x in updated_widgets]: - updated_widgets.append(w) - original_page.set('shortcuts', updated_widgets) - - for i, v in enumerate(original_page.links): - if v.type == 'Card Break' and v.label not in page_widgets['card']: - del original_page.links[ i : i+v.link_count+1] + clean_up(original_page, page) try: original_page.save(ignore_permissions=True) @@ -586,6 +571,30 @@ def save_new_widget(page, new_widgets): return True +def clean_up(original_page, page): + page_widgets = {} + + content = frappe.db.get_value("Internal Wiki Page", page, "content") + + for wid in ['shortcut', 'card', 'chart']: + # get list of widget's name from internal wiki page + page_widgets[wid] = [x['data'][wid + '_name'] for x in json.loads(content) if x['type'] == wid] + + # shortcut & chart cleanup + for wid in ['shortcut', 'chart']: + updated_widgets = [] + original_page.get(wid+'s').reverse() + + for w in original_page.get(wid+'s'): + if w.label in page_widgets[wid] and w.label not in [x.label for x in updated_widgets]: + updated_widgets.append(w) + original_page.set(wid+'s', updated_widgets) + + # card cleanup + for i, v in enumerate(original_page.links): + if v.type == 'Card Break' and v.label not in page_widgets['card']: + del original_page.links[i : i+v.link_count+1] + def new_widget(config, doctype, parentfield): if not config: return [] diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index 1d637ef5b6..6c51ad873e 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -1,3 +1,4 @@ +import get_dialog_constructor from "../widgets/widget_dialog.js"; export default class Chart { static get toolbox() { return { @@ -10,34 +11,32 @@ export default class Chart { return true; } - constructor({data, api, config, readOnly}) { + constructor({data, api, config, readOnly, block}) { this.data = data; this.api = api; + this.block = block; this.config = config; this.readOnly = readOnly; - this.sections = {}; this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; this.pb = this.data.pb ? this.data.pb : "0"; this.pl = this.data.pl ? this.data.pl : "0"; this.allow_customization = !this.readOnly; + this.options = { + allow_sorting: this.allow_customization, + allow_create: this.allow_customization, + allow_delete: this.allow_customization, + allow_hiding: false, + allow_edit: true, + max_widget_count: 2, + }; } render() { - let me = this; this.wrapper = document.createElement('div'); - this._make_fieldgroup(this.wrapper, [{ - fieldtype: "Select", - label: "Chart Name", - fieldname: "chart_name", - options: this.config.page_data.charts.items.map(({ chart_name }) => chart_name), - change: function() { - if (this.value) { - me._make_charts(this.value); - } - } - }]); + this._new_chart(); + if (this.data && this.data.chart_name) { this._make_charts(this.data.chart_name); } @@ -51,7 +50,8 @@ export default class Chart { pt: this._getPadding("t"), pr: this._getPadding("r"), pb: this._getPadding("b"), - pl: this._getPadding("l") + pl: this._getPadding("l"), + new: this.new_chart_widget }; } @@ -64,6 +64,34 @@ export default class Chart { e.classList.add("pl-" + this.pl); } + _new_chart() { + const dialog_class = get_dialog_constructor('chart'); + this.dialog = new dialog_class({ + label: this.label, + type: 'chart', + primary_action: (widget) => { + widget.in_customize_mode = 1; + this.chart_widget = frappe.widget.make_widget({ + ...widget, + widget_type: 'chart', + container: this.wrapper, + options: { + ...this.options, + on_delete: () => this.api.blocks.delete(), + on_edit: () => this.on_edit(this.chart_widget) + } + }); + this.chart_widget.customize(this.options); + this.wrapper.setAttribute("chart_name", this.chart_widget.label); + this.new_chart_widget = this.chart_widget.get_config(); + }, + }); + + if (!this.readOnly && this.data && !this.data.chart_name) { + this.dialog.make(); + } + } + _getCol() { var e = 12; var t = "col-12"; @@ -130,32 +158,31 @@ export default class Chart { this.chart_field.make(); } + on_edit(chart_obj) { + let chart = chart_obj.get_config(); + this.chart_widget.widgets = chart; + this.wrapper.setAttribute("chart_name", chart.label); + this.new_chart_widget = chart_obj.get_config(); + } + _make_charts(chart_name) { let chart = this.config.page_data.charts.items.find(obj => { - return obj.chart_name == chart_name; + return obj.label == chart_name; }); + if (!chart) return; this.wrapper.innerHTML = ''; - this.sections = {}; - chart.in_customize_mode = !this.readOnly; - this.sections["charts"] = new frappe.widget.SingleWidgetGroup({ + this.chart_widget = new frappe.widget.SingleWidgetGroup({ container: this.wrapper, type: "chart", - columns: 1, class_name: "widget-charts", - // hidden: Boolean(this.onboarding_widget), - options: { - allow_sorting: this.allow_customization, - allow_create: this.allow_customization, - allow_delete: this.allow_customization, - allow_hiding: false, - allow_edit: true, - max_widget_count: 2, - }, - widgets: chart + options: this.options, + widgets: chart, + api: this.api, + block: this.block }); this.wrapper.setAttribute("chart_name", chart_name); if (!this.readOnly) { - this.sections["charts"].customize(); + this.chart_widget.customize(); } } } \ No newline at end of file From 2b8aaa53759f4f6168f6572dbda79092b2517437 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 18 May 2021 21:12:45 +0530 Subject: [PATCH 108/868] fix(minor): expose limited methods of json module --- frappe/utils/safe_exec.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index 6c1fa21685..2472de70f0 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -61,7 +61,9 @@ def get_safe_globals(): out = NamespaceDict( # make available limited methods of frappe - json=json, + json=NamespaceDict( + loads = json.loads, + dumps = json.dumps), dict=dict, log=frappe.log, _dict=frappe._dict, From a2248192e1273298a932e06b03b2a7dd00c389f2 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 18 May 2021 21:42:59 +0530 Subject: [PATCH 109/868] fix: Chart config fix --- frappe/public/js/frappe/views/wiki.js | 10 ++++++++++ frappe/public/js/frappe/widgets/chart_widget.js | 2 ++ 2 files changed, 12 insertions(+) diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index 057ae25902..4b52708194 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -207,6 +207,16 @@ frappe.views.Wiki = class Wiki { page: page }).then(data => { this.page_data = data; + if (!this.page_data) return; + + return frappe.dashboard_utils.get_dashboard_settings().then(settings => { + let chart_config = settings.chart_config ? JSON.parse(settings.chart_config) : {}; + if (this.page_data.charts.items) { + this.page_data.charts.items.map(chart => { + chart.chart_settings = chart_config[chart.chart_name] || {}; + }); + } + }); }); } diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 0c36f013ec..44f3edc038 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -349,6 +349,8 @@ export default class ChartWidget extends Widget { } setup_filter_button() { + if (this.in_customize_mode) return; + this.is_document_type = this.chart_doc.chart_type !== "Report" && this.chart_doc.chart_type !== "Custom"; From 6375818c10d73e9ae02ba7ee6e1821e3b4143857 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 21:57:20 +0530 Subject: [PATCH 110/868] fix: 404 caching --- .../page_controllers/not_found_page.py | 20 +++++++++++++++++++ frappe/website/serve.py | 6 ++++++ frappe/website/utils.py | 3 ++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_controllers/not_found_page.py index aebc0006ae..1f6bbd4b02 100644 --- a/frappe/website/page_controllers/not_found_page.py +++ b/frappe/website/page_controllers/not_found_page.py @@ -1,10 +1,30 @@ +import frappe from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.utils import can_cache +from urllib.parse import urlparse + +HOMEPAGE_PATHS = ('/', '/index', '', 'index') class NotFoundPage(TemplatePage): def __init__(self, path, http_status_code): + self.resolved_path = path path = '404' http_status_code = 404 super().__init__(path=path, http_status_code=http_status_code) def validate(self): return True + + def render(self): + if can_cache_404(self.resolved_path): + frappe.cache().hset('website_404', frappe.request.url, True) + return super().render() + +def can_cache_404(path): + # do not cache 404 for custom homepages + return can_cache() and not is_custom_home_page(path) + +def is_custom_home_page(path): + url = frappe.request.url + url_parts = urlparse(url) + return url_parts.path in HOMEPAGE_PATHS and path not in HOMEPAGE_PATHS diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 7010b768d8..56fed22469 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,8 +1,10 @@ import frappe from frappe.website.page_controllers.error_page import ErrorPage +from frappe.website.page_controllers.not_found_page import NotFoundPage from frappe.website.page_controllers.not_permitted_page import NotPermittedPage from frappe.website.page_controllers.redirect_page import RedirectPage from frappe.website.path_resolver import PathResolver +from frappe.website.utils import can_cache def get_response(path=None, http_status_code=200): @@ -11,6 +13,10 @@ def get_response(path=None, http_status_code=200): path = path or frappe.local.request.path endpoint = path + if can_cache() and frappe.cache().hget('website_404', frappe.request.url): + response = NotFoundPage(path=path).render() + return response + try: path_resolver = PathResolver(path, http_status_code) endpoint, renderer_instance = path_resolver.resolve() diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 576d1d911c..be18466714 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -540,7 +540,8 @@ def cache_html(func): frappe.local.response.from_cache = True return html html = func(*args, **kwargs) - if can_cache(): + context = args[0].context + if can_cache(context.no_cache): page_cache = frappe.cache().hget("website_page", args[0].path) or {} page_cache[frappe.local.lang] = html frappe.cache().hset("website_page", args[0].path, page_cache) From 48b9198ebd717fe3e3ac1ae1598c78dc04e91266 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 18 May 2021 23:34:30 +0530 Subject: [PATCH 111/868] test: Add test case to validate base_template_path --- frappe/website/doctype/web_page/test_web_page.py | 9 ++++++++- frappe/www/_test/_test_folder/_test_page.html | 3 +++ frappe/www/_test/_test_folder/_test_page.py | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 frappe/www/_test/_test_folder/_test_page.html create mode 100644 frappe/www/_test/_test_folder/_test_page.py diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index daaa41f5a8..2c43acc226 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import unittest import frappe from frappe.website.router import resolve_route -from frappe.website.serve import get_response +from frappe.website.serve import get_response, get_response_content from frappe.utils import set_request test_records = frappe.get_test_records('Web Page') @@ -73,4 +73,11 @@ class TestWebPage(unittest.TestCase): finally: web_page.delete() + def test_custom_base_template_path(self): + content = get_response_content('/_test/_test_folder/_test_page') + # assert the text in base template is rendered + self.assertTrue('

This is for testing

' in frappe.as_unicode(content)) + + # assert template block rendered + self.assertTrue('

Test content

' in frappe.as_unicode(content)) diff --git a/frappe/www/_test/_test_folder/_test_page.html b/frappe/www/_test/_test_folder/_test_page.html new file mode 100644 index 0000000000..7364235e10 --- /dev/null +++ b/frappe/www/_test/_test_folder/_test_page.html @@ -0,0 +1,3 @@ +{% block content %} +

Test content

+{% endblock %} diff --git a/frappe/www/_test/_test_folder/_test_page.py b/frappe/www/_test/_test_folder/_test_page.py new file mode 100644 index 0000000000..fa7b5f5727 --- /dev/null +++ b/frappe/www/_test/_test_folder/_test_page.py @@ -0,0 +1,2 @@ +def get_context(context): + context.base_template_path = 'frappe/templates/test/_test_base.html' From 1be1c25e587c98b62a6134496dac19cd9f4af88e Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 19 May 2021 04:46:19 +0530 Subject: [PATCH 112/868] fix: 404 caching - Move 404 resolving code to path resolver --- .../page_controllers/not_found_page.py | 28 +++++++++++-------- frappe/website/path_resolver.py | 12 ++++++-- frappe/website/serve.py | 6 ---- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_controllers/not_found_page.py index 1f6bbd4b02..13c6358512 100644 --- a/frappe/website/page_controllers/not_found_page.py +++ b/frappe/website/page_controllers/not_found_page.py @@ -1,13 +1,16 @@ +import os +from urllib.parse import urlparse + import frappe from frappe.website.page_controllers.template_page import TemplatePage from frappe.website.utils import can_cache -from urllib.parse import urlparse -HOMEPAGE_PATHS = ('/', '/index', '', 'index') +HOMEPAGE_PATHS = ('/', '/index', 'index') class NotFoundPage(TemplatePage): def __init__(self, path, http_status_code): - self.resolved_path = path + self.request_path = path + self.request_url = frappe.local.request.url if hasattr(frappe.local, 'request') else '' path = '404' http_status_code = 404 super().__init__(path=path, http_status_code=http_status_code) @@ -16,15 +19,16 @@ class NotFoundPage(TemplatePage): return True def render(self): - if can_cache_404(self.resolved_path): - frappe.cache().hset('website_404', frappe.request.url, True) + if self.can_cache_404(): + frappe.cache().hset('website_404', self.request_url, True) return super().render() -def can_cache_404(path): - # do not cache 404 for custom homepages - return can_cache() and not is_custom_home_page(path) + def can_cache_404(self): + # do not cache 404 for custom homepages + return can_cache() and self.request_url and not self.is_custom_home_page() -def is_custom_home_page(path): - url = frappe.request.url - url_parts = urlparse(url) - return url_parts.path in HOMEPAGE_PATHS and path not in HOMEPAGE_PATHS + def is_custom_home_page(self): + url_parts = urlparse(self.request_url) + request_url = os.path.splitext(url_parts.path)[0] + request_path = os.path.splitext(self.request_path)[0] + return request_url in HOMEPAGE_PATHS and request_path not in HOMEPAGE_PATHS diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index 1368932792..1a813fac60 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -8,6 +8,7 @@ from frappe.website.page_controllers.template_page import TemplatePage from frappe.website.page_controllers.web_form import WebFormPage from frappe.website.redirect import resolve_redirect from frappe.website.render import resolve_path +from frappe.website.utils import can_cache class PathResolver(): @@ -21,8 +22,15 @@ class PathResolver(): def resolve(self): '''Returns endpoint and a renderer instance that can render the endpoint''' - query_string = frappe.local.request.query_string if hasattr(frappe.local, 'request') else None - resolve_redirect(self.path, query_string) + request = frappe._dict() + if hasattr(frappe.local, 'request'): + request = frappe.local.request or request + + # check if the request url is in 404 list + if request.url and can_cache() and frappe.cache().hget('website_404', request.url): + return self.path, NotFoundPage(self.path) + + resolve_redirect(self.path, request.query_string) endpoint = resolve_path(self.path) renderers = (StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage) diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 56fed22469..7010b768d8 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,10 +1,8 @@ import frappe from frappe.website.page_controllers.error_page import ErrorPage -from frappe.website.page_controllers.not_found_page import NotFoundPage from frappe.website.page_controllers.not_permitted_page import NotPermittedPage from frappe.website.page_controllers.redirect_page import RedirectPage from frappe.website.path_resolver import PathResolver -from frappe.website.utils import can_cache def get_response(path=None, http_status_code=200): @@ -13,10 +11,6 @@ def get_response(path=None, http_status_code=200): path = path or frappe.local.request.path endpoint = path - if can_cache() and frappe.cache().hget('website_404', frappe.request.url): - response = NotFoundPage(path=path).render() - return response - try: path_resolver = PathResolver(path, http_status_code) endpoint, renderer_instance = path_resolver.resolve() From b193666c71a32550ce61a2a9a7bc722ef1b2a2fd Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 19 May 2021 11:34:04 +0530 Subject: [PATCH 113/868] fix: Do not set content type for paths ending with .com To avoid unnecessary download --- frappe/website/render.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/website/render.py b/frappe/website/render.py index 6a1d5a404e..c14d8e0d48 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -103,7 +103,9 @@ def set_content_type(response, data, path): response.mimetype = 'text/html' response.charset = 'utf-8' - if "." in path: + # ignore paths ending with .com to avoid unnecessary download + # https://bugs.python.org/issue22347 + if "." in path and not path.endswith('.com'): content_type, encoding = mimetypes.guess_type(path) if content_type: response.mimetype = content_type From 0b37e0dbd7a4f82d0562685723757282304611f2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 19 May 2021 13:55:45 +0530 Subject: [PATCH 114/868] fix: Check if resolved file_path in StaticPage is a file --- frappe/website/page_controllers/static_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/website/page_controllers/static_page.py b/frappe/website/page_controllers/static_page.py index 767cc872d1..b292a62922 100644 --- a/frappe/website/page_controllers/static_page.py +++ b/frappe/website/page_controllers/static_page.py @@ -20,7 +20,7 @@ class StaticPage(WebPage): return for app in frappe.get_installed_apps(): file_path = frappe.get_app_path(app, 'www') + '/' + self.path - if os.path.exists(file_path): + if os.path.isfile(file_path): self.file_path = file_path def validate(self): From 68aa1805aaca41476ea4d47cba9d88ab7cf17c18 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 19 May 2021 14:03:31 +0530 Subject: [PATCH 115/868] fix: Exception handling --- frappe/utils/global_search.py | 4 +-- .../website/doctype/web_page/test_web_page.py | 31 ++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py index 4c78d63918..a7d484a7ff 100644 --- a/frappe/utils/global_search.py +++ b/frappe/utils/global_search.py @@ -332,8 +332,8 @@ def add_route_to_global_search(route): route=route ) sync_value_in_queue(value) - except (frappe.PermissionError, frappe.DoesNotExistError, frappe.ValidationError, Exception) as e: - raise e + except Exception: + pass frappe.set_user('Administrator') diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index 2c43acc226..b40b63b0d5 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -63,7 +63,7 @@ class TestWebPage(unittest.TestCase): dynamic_route = 1, route = '/doctype-view/', content_type = 'HTML', - dymamic_template = 1, + dynamic_template = 1, main_section_html = '
{{ frappe.form_dict.doctype }}
' )).insert() @@ -81,3 +81,32 @@ class TestWebPage(unittest.TestCase): # assert template block rendered self.assertTrue('

Test content

' in frappe.as_unicode(content)) + def test_home_page(self): + content = get_response_content(path='/') + print(content) + content = get_response_content(path='/index') + print(content) + + def test_table_of_content(self): + page = get_response(path='/_test/_test_folder/_test_toc') + print(page) + + def test_sidebar_data(self): + pass + + def test_meta_tags(self): + pass + + def test_breadcrumbs(self): + pass + + def test_downloadable_file(self): + pass + + + + +# breadcrumb +# validate +# cache no-cache +# page context caching From aa0151ce744b3b13265f9f6cfa4e0724c38e4afb Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 19 May 2021 16:28:40 +0530 Subject: [PATCH 116/868] fix: Drag, Delete sidebar page --- frappe/desk/desktop.py | 1 - .../internal_wiki_page/internal_wiki_page.py | 15 ++- frappe/public/js/frappe/views/wiki.js | 110 +++++++++++++----- frappe/public/scss/desk/wiki.scss | 17 +++ 4 files changed, 109 insertions(+), 34 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 6d0356747d..a87ca6bc02 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -538,7 +538,6 @@ def save_customization(page, config): return True -@frappe.whitelist() def save_new_widget(page, new_widgets): original_page = frappe.get_doc("Workspace", page) widgets = _dict(loads(new_widgets)) diff --git a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py index 6e695ef516..3fba588343 100644 --- a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py +++ b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe import json +from frappe.desk.desktop import save_new_widget from frappe.model.document import Document class InternalWikiPage(Document): @@ -16,7 +17,7 @@ class InternalWikiPage(Document): self.sequence_id = frappe.get_last_doc('Internal Wiki Page').sequence_id + 1 @frappe.whitelist() -def save_wiki_page(title, parent, sb_items, blocks, save=True): +def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, save=True): if save: if not frappe.db.exists("Workspace", title): wspace = frappe.new_doc('Workspace') @@ -38,6 +39,18 @@ def save_wiki_page(title, parent, sb_items, blocks, save=True): doc = frappe.get_doc('Internal Wiki Page', d.get('name')) doc.sequence_id = d.get('sequence_id') doc.save() + + if json.loads(deleted_pages): + for d in json.loads(deleted_pages): + wiki_doc = frappe.get_doc('Internal Wiki Page', d) + wiki_doc.delete() + wspace_doc = frappe.get_doc('Workspace', d) + if not wspace_doc.is_standard: + wspace_doc.delete() + return 'Build' + + if json.loads(new_widgets): + save_new_widget(title, new_widgets) return doc.title diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index 4b52708194..1053f7b76e 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -12,6 +12,7 @@ frappe.views.Wiki = class Wiki { this.sections = {}; this.sidebar_items = {}; this.sorted_sidebar_items = []; + this.deleted_sidebar_items = []; this.tools = {}; this.isReadOnly = true; this.new_page = null; @@ -37,13 +38,13 @@ frappe.views.Wiki = class Wiki { for (let page of this.all_pages || []) { frappe.wiki_pages[frappe.router.slug(page.name)] = page; } - frappe.router.route(); this.make_sidebar(root_pages); } if (this.new_page) { frappe.set_route(`wiki/${frappe.router.slug(this.new_page)}`); this.new_page = null; } + frappe.router.route(); }); } @@ -65,12 +66,12 @@ frappe.views.Wiki = class Wiki {
@@ -85,25 +86,34 @@ frappe.views.Wiki = class Wiki { const get_child_item = function (item) { return $(` - - `) + `); $spacer.appendTo(this.wrapper); this.wrapper.classList.add('widget', 'new-widget'); this.wrapper.style.minHeight = 50 + 'px'; - let $widget_control = $spacer.find('.widget-control') + let $widget_control = $spacer.find('.widget-control'); this.add_custom_button( frappe.utils.icon('delete', 'xs'), @@ -47,7 +47,7 @@ export default class Spacer { null, $widget_control ); - + this.add_custom_button( frappe.utils.icon('drag', 'xs'), null, From bcbc14d047cc16b3847d03bc7db4b28d0b2f363a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 20 May 2021 17:11:12 +0530 Subject: [PATCH 130/868] chore: Rename test suite and remove unused imports --- frappe/tests/test_frappe_client.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/tests/test_frappe_client.py b/frappe/tests/test_frappe_client.py index 6453062877..e1cdbb6ccd 100644 --- a/frappe/tests/test_frappe_client.py +++ b/frappe/tests/test_frappe_client.py @@ -1,8 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals -import unittest, frappe, os +import unittest, frappe from frappe.core.doctype.user.user import generate_keys from frappe.frappeclient import FrappeClient, FrappeException from frappe.utils.data import get_url @@ -10,7 +9,7 @@ from frappe.utils.data import get_url import requests import base64 -class TestAPI(unittest.TestCase): +class TestFrappeClient(unittest.TestCase): def test_insert_many(self): server = FrappeClient(get_url(), "Administrator", "admin", verify=False) frappe.db.sql("delete from `tabNote` where title in ('Sing','a','song','of','sixpence')") From 4a814571a8008672cbae058351a21d9a8665b714 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 20 May 2021 19:26:11 +0530 Subject: [PATCH 131/868] test: Added tests for Frappe APIs * Added tests for /api/resource usage * Added tests for /api/method base endpoints --- frappe/tests/test_api.py | 170 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 frappe/tests/test_api.py diff --git a/frappe/tests/test_api.py b/frappe/tests/test_api.py new file mode 100644 index 0000000000..4d00df22a5 --- /dev/null +++ b/frappe/tests/test_api.py @@ -0,0 +1,170 @@ +import unittest +from random import choice + +import requests +from semantic_version import Version + +import frappe +from frappe.utils import get_site_url + + +def maintain_state(f): + def wrapper(*args, **kwargs): + frappe.db.rollback() + r = f(*args, **kwargs) + frappe.db.commit() + return r + + return wrapper + + +class TestResourceAPI(unittest.TestCase): + SITE_URL = get_site_url(frappe.local.site) + RESOURCE_URL = f"{SITE_URL}/api/resource" + DOCTYPE = "ToDo" + GENERATED_DOCUMENTS = [] + + @classmethod + @maintain_state + def setUpClass(self): + for _ in range(10): + doc = frappe.get_doc( + {"doctype": "ToDo", "description": frappe.mock("paragraph")} + ).insert() + self.GENERATED_DOCUMENTS.append(doc.name) + + @classmethod + @maintain_state + def tearDownClass(self): + for name in self.GENERATED_DOCUMENTS: + frappe.delete_doc_if_exists(self.DOCTYPE, name) + + @property + def sid(self): + if not getattr(self, "_sid", None): + self._sid = requests.post( + f"{self.SITE_URL}/api/method/login", + data={ + "usr": "Administrator", + "pwd": "root" or frappe.conf.admin_password or "admin", + }, + ).cookies.get("sid") + + return self._sid + + def get(self, path, params=""): + return requests.get(f"{self.RESOURCE_URL}/{path}?sid={self.sid}{params}") + + def post(self, path, data): + return requests.post( + f"{self.RESOURCE_URL}/{path}?sid={self.sid}", data=frappe.as_json(data) + ) + + def put(self, path, data): + return requests.put( + f"{self.RESOURCE_URL}/{path}?sid={self.sid}", data=frappe.as_json(data) + ) + + def delete(self, path): + return requests.delete(f"{self.RESOURCE_URL}/{path}?sid={self.sid}") + + def test_unauthorized_call(self): + # test 1: fetch documents without auth + response = requests.get(f"{self.RESOURCE_URL}/{self.DOCTYPE}") + self.assertEqual(response.status_code, 403) + + def test_get_list(self): + # test 2: fetch documents without params + response = self.get(self.DOCTYPE) + self.assertEqual(response.status_code, 200) + self.assertIsInstance(response.json(), dict) + self.assertIn("data", response.json()) + + def test_get_list_limit(self): + # test 3: fetch data with limit + response = self.get(self.DOCTYPE, "&limit=2") + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.json()["data"]), 2) + + def test_get_list_dict(self): + # test 4: fetch response as (not) dict + response = self.get(self.DOCTYPE, "&as_dict=True") + json = frappe._dict(response.json()) + self.assertEqual(response.status_code, 200) + self.assertIsInstance(json.data, list) + self.assertIsInstance(json.data[0], dict) + + response = self.get(self.DOCTYPE, "&as_dict=False") + json = frappe._dict(response.json()) + self.assertEqual(response.status_code, 200) + self.assertIsInstance(json.data, list) + self.assertIsInstance(json.data[0], list) + + def test_get_list_debug(self): + # test 5: fetch response with debug + response = self.get(self.DOCTYPE, "&debug=true") + self.assertEqual(response.status_code, 200) + self.assertIn("exc", response.json()) + self.assertIsInstance(response.json()["exc"], str) + self.assertIsInstance(eval(response.json()["exc"]), list) + + def test_get_list_fields(self): + # test 6: fetch response with fields + response = self.get(self.DOCTYPE, r'&fields=["description"]') + self.assertEqual(response.status_code, 200) + json = frappe._dict(response.json()) + self.assertIn("description", json.data[0]) + + def test_create_document(self): + # test 7: POST method on /api/resource to create doc + data = {"description": frappe.mock("paragraph")} + response = self.post(self.DOCTYPE, data) + self.assertEqual(response.status_code, 200) + docname = response.json()["data"]["name"] + self.assertIsInstance(docname, str) + self.GENERATED_DOCUMENTS.append(docname) + + def test_update_document(self): + # test 8: PUT method on /api/resource to update doc + generated_desc = frappe.mock("paragraph") + data = {"description": generated_desc} + random_doc = choice(self.GENERATED_DOCUMENTS) + desc_before_update = frappe.db.get_value(self.DOCTYPE, random_doc, "description") + + response = self.put(f"{self.DOCTYPE}/{random_doc}", data=data) + self.assertEqual(response.status_code, 200) + self.assertNotEqual(response.json()["data"]["description"], desc_before_update) + self.assertEqual(response.json()["data"]["description"], generated_desc) + + def test_delete_document(self): + # test 9: DELETE method on /api/resource + doc_to_delete = choice(self.GENERATED_DOCUMENTS) + response = self.delete(f"{self.DOCTYPE}/{doc_to_delete}") + self.assertEqual(response.status_code, 202) + self.assertDictEqual(response.json(), {"message": "ok"}) + + non_existent_doc = frappe.generate_hash(length=12) + response = self.delete(f"{self.DOCTYPE}/{non_existent_doc}") + self.assertEqual(response.status_code, 404) + self.assertDictEqual(response.json(), {}) + + +class TestMethodAPI(unittest.TestCase): + METHOD_URL = f"{get_site_url(frappe.local.site)}/api/method" + + def test_version(self): + # test 1: test for /api/method/version + response = requests.get(f"{self.METHOD_URL}/version") + json = frappe._dict(response.json()) + + self.assertEqual(response.status_code, 200) + self.assertIsInstance(json, dict) + self.assertIsInstance(json.message, str) + self.assertEqual(Version(json.message), Version(frappe.__version__)) + + def test_ping(self): + # test 2: test for /api/method/ping + response = requests.get(f"{self.METHOD_URL}/ping") + self.assertEqual(response.status_code, 200) + self.assertIsInstance(response.json(), dict) + self.assertEqual(response.json()['message'], "pong") From 969e2b6db95d1c865730776921e853cdeb0284ef Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 20 May 2021 20:04:40 +0530 Subject: [PATCH 132/868] fix: allow only system manager Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- frappe/core/doctype/document_naming_rule/document_naming_rule.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.py b/frappe/core/doctype/document_naming_rule/document_naming_rule.py index 13d54dffdd..7fa7c73efd 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.py @@ -33,5 +33,6 @@ class DocumentNamingRule(Document): @frappe.whitelist() def update_current(name, new_counter): + frappe.only_for('System Manager') frappe.db.set_value('Document Naming Rule', name, 'counter', new_counter) frappe.db.commit() From 730bcc8c035bc5aec5173f1feb0b06a2e5c664de Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 20 May 2021 20:05:00 +0530 Subject: [PATCH 133/868] fix: do not explicitly commit Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- frappe/core/doctype/document_naming_rule/document_naming_rule.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.py b/frappe/core/doctype/document_naming_rule/document_naming_rule.py index 7fa7c73efd..653c056caa 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.py @@ -35,4 +35,3 @@ class DocumentNamingRule(Document): def update_current(name, new_counter): frappe.only_for('System Manager') frappe.db.set_value('Document Naming Rule', name, 'counter', new_counter) - frappe.db.commit() From e16988b887d129c13fe30f9d67e27ff0fad93a82 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Thu, 20 May 2021 20:05:58 +0530 Subject: [PATCH 134/868] chore: change description --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 5e77e71820..f4b7428aff 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -31,7 +31,7 @@ frappe.ui.form.on('Document Naming Rule', { label: __('New Counter'), default: frm.doc.counter, reqd: 1, - description: __('This will update the counter and will affect all documents that will be created') + description: __('Updating counter may lead to document name conflicts if not done properly') }]; let primary_action_label = __('Save'); From a1ad85a9cf284086d265dc4e20b8fa22110bcb27 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Thu, 20 May 2021 21:41:29 +0530 Subject: [PATCH 135/868] fix: show & hide sidebar controls --- frappe/public/js/frappe/views/wiki.js | 7 +++---- frappe/public/scss/desk/wiki.scss | 29 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index d994cb97af..cbc6eacf33 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -282,15 +282,14 @@ frappe.views.Wiki = class Wiki { } show_sidebar_actions() { - $('.sidebar-item-control .drag-handle').removeClass('hidden'); - $('.sidebar-item-control .delete-page').removeClass('hidden'); + this.sidebar.find('.standard-sidebar-section').addClass('show-control'); } add_sidebar_actions(item, sidebar_control) { this.add_custom_button( frappe.utils.icon('drag', 'xs'), null, - "drag-handle hidden", + "drag-handle", `${__('Drag')}`, null, sidebar_control @@ -298,7 +297,7 @@ frappe.views.Wiki = class Wiki { this.add_custom_button( frappe.utils.icon('delete', 'xs'), () => this.delete_page(item.name), - "delete-page hidden", + "delete-page", `${__('Delete')}`, null, sidebar_control diff --git a/frappe/public/scss/desk/wiki.scss b/frappe/public/scss/desk/wiki.scss index 7b20b29598..1a5f9376f9 100644 --- a/frappe/public/scss/desk/wiki.scss +++ b/frappe/public/scss/desk/wiki.scss @@ -25,6 +25,11 @@ .drag-handle { cursor: all-scroll; cursor: -webkit-grabbing; + display: none; + } + + .delete-page { + display: none; } svg { @@ -50,6 +55,30 @@ overflow: hidden; flex: 1; } + + .standard-sidebar-section.show-control { + .desk-sidebar-item.standard-sidebar-item { + &:hover { + .drag-handle { + display: inline-block; + } + + .delete-page { + display: inline-block; + } + } + + &.selected { + .drag-handle { + display: inline-block; + } + + .delete-page { + display: inline-block; + } + } + } + } } .ce-header { From dfc23eb3a3e42869430cf686a29f0b4188894618 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 21 May 2021 11:22:19 +0530 Subject: [PATCH 136/868] fix(test): Set admin password correctly --- frappe/tests/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/tests/test_api.py b/frappe/tests/test_api.py index 4d00df22a5..7e77aab779 100644 --- a/frappe/tests/test_api.py +++ b/frappe/tests/test_api.py @@ -46,7 +46,7 @@ class TestResourceAPI(unittest.TestCase): f"{self.SITE_URL}/api/method/login", data={ "usr": "Administrator", - "pwd": "root" or frappe.conf.admin_password or "admin", + "pwd": frappe.conf.admin_password or "admin", }, ).cookies.get("sid") From c9dc4ee441eae931b0d1918ba18fd0ce81df5967 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Fri, 21 May 2021 11:38:36 +0530 Subject: [PATCH 137/868] Update frappe/core/doctype/document_naming_rule/document_naming_rule.js Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index f4b7428aff..cd85615f5f 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -31,7 +31,7 @@ frappe.ui.form.on('Document Naming Rule', { label: __('New Counter'), default: frm.doc.counter, reqd: 1, - description: __('Updating counter may lead to document name conflicts if not done properly') + description: __('Warning: Updating counter may lead to document name conflicts if not done properly') }]; let primary_action_label = __('Save'); From bcb4c5182ffdb9d7d70b239d8ee6b222ece63f0e Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Fri, 21 May 2021 11:38:43 +0530 Subject: [PATCH 138/868] Update frappe/core/doctype/document_naming_rule/document_naming_rule.js Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index cd85615f5f..b1123cba28 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -50,7 +50,7 @@ frappe.ui.form.on('Document Naming Rule', { }); }; - var dialog = new frappe.ui.Dialog({ + const dialog = new frappe.ui.Dialog({ title: __('Update Counter Value for Prefix: {0}', [frm.doc.prefix]), fields, primary_action_label, From 3f056d147dea656dd531c7e794da05a513aa44f7 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Fri, 21 May 2021 11:38:49 +0530 Subject: [PATCH 139/868] Update frappe/core/doctype/document_naming_rule/document_naming_rule.js Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index b1123cba28..3aea9e04a7 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -4,7 +4,7 @@ frappe.ui.form.on('Document Naming Rule', { refresh: function(frm) { frm.trigger('document_type'); - if (!frm.doc.__islocal) frm.trigger("add_button"); + if (!frm.doc.__islocal) frm.trigger("add_update_counter_button"); }, document_type: (frm) => { // update the select field options with fieldnames From fa53c47e58cf7f8c85bd1ba13ad6973ec998b2d0 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Fri, 21 May 2021 11:38:57 +0530 Subject: [PATCH 140/868] Update frappe/core/doctype/document_naming_rule/document_naming_rule.js Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 3aea9e04a7..0f0bdd149c 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -22,7 +22,7 @@ frappe.ui.form.on('Document Naming Rule', { }); } }, - add_button: (frm) => { + add_update_counter_button: (frm) => { frm.add_custom_button(__('Update Counter'), function() { const fields = [{ From 58400d6214ec61ff9733a4caf46bad18dff71880 Mon Sep 17 00:00:00 2001 From: Mohammad Hasnain Mohsin Rajan Date: Fri, 21 May 2021 14:15:14 +0530 Subject: [PATCH 141/868] Update frappe/core/doctype/document_naming_rule/document_naming_rule.js Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- .../core/doctype/document_naming_rule/document_naming_rule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.js b/frappe/core/doctype/document_naming_rule/document_naming_rule.js index 0f0bdd149c..097a4e9a6e 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.js +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.js @@ -44,7 +44,7 @@ frappe.ui.form.on('Document Naming Rule', { new_counter: fields.new_counter }, callback: function() { - frm.set_value("counter", fields.new_counter); + frm.set_value("counter", fields.new_counter); dialog.hide(); } }); From 5b96b79ed43a391ad82f43bda408aeb99596a8ae Mon Sep 17 00:00:00 2001 From: leela Date: Wed, 12 May 2021 13:49:43 +0530 Subject: [PATCH 142/868] refactor: incoming mails --- .../doctype/communication/communication.py | 40 +- .../doctype/email_account/email_account.py | 395 +++--------------- .../email/doctype/email_queue/email_queue.py | 5 + frappe/email/email_body.py | 4 +- frappe/email/receive.py | 368 +++++++++++++++- frappe/hooks.py | 6 +- 6 files changed, 461 insertions(+), 357 deletions(-) diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 5ebf714645..a9c1c1f5a3 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -21,9 +21,11 @@ from frappe.automation.doctype.assignment_rule.assignment_rule import apply as a exclude_from_linked_with = True class Communication(Document): + """Communication represents an external communication like Email. + """ no_feed_on_delete = True + DOCTYPE = 'Communication' - """Communication represents an external communication like Email.""" def onload(self): """create email flag queue""" if self.communication_type == "Communication" and self.communication_medium == "Email" \ @@ -149,6 +151,23 @@ class Communication(Document): self.email_status = "Spam" + @classmethod + def find(cls, name, ignore_error=False): + try: + return frappe.get_doc(cls.DOCTYPE, name) + except frappe.DoesNotExistError: + if ignore_error: + return + raise + + @classmethod + def find_one_by_filters(cls, *, order_by=None, **kwargs): + name = frappe.db.get_value(cls.DOCTYPE, kwargs, order_by=order_by) + return cls.find(name) if name else None + + def update_db(self, **kwargs): + frappe.db.set_value(self.DOCTYPE, self.name, kwargs) + def set_sender_full_name(self): if not self.sender_full_name and self.sender: if self.sender == "Administrator": @@ -180,6 +199,8 @@ class Communication(Document): if not self.sender_full_name: self.sender_full_name = sender_email + + def send(self, print_html=None, print_format=None, attachments=None, send_me_a_copy=False, recipients=None): """Send communication via Email. @@ -306,6 +327,21 @@ class Communication(Document): if autosave: self.save(ignore_permissions=ignore_permissions) + # @classmethod + # def add_incoming_mail(cls, email, uid, seen_status): + # if exists_already(): + # pass # Modify UID + # else: + # pass # Call new() to create object +class InMailMixin: + @classmethod + def add_incoming_mail(cls, email, uid, seen_status): + if exists_already(): + pass # Modify UID + else: + pass # Call new() to create object + + def on_doctype_update(): """Add indexes in `tabCommunication`""" frappe.db.add_index("Communication", ["reference_doctype", "reference_name"]) @@ -485,4 +521,4 @@ def set_avg_response_time(parent, communication): response_times.append(response_time) if response_times: avg_response_time = sum(response_times) / len(response_times) - parent.db_set("avg_response_time", avg_response_time) \ No newline at end of file + parent.db_set("avg_response_time", avg_response_time) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 36b662bb39..0a66efb480 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -19,7 +19,7 @@ from frappe.utils import (validate_email_address, cint, cstr, get_datetime, from frappe.utils.user import is_system_user from frappe.utils.jinja import render_template from frappe.email.smtp import SMTPServer -from frappe.email.receive import EmailServer, Email +from frappe.email.receive import EmailServer, Email, InboundMail, SentEmailInInboxError from poplib import error_proto from dateutil.relativedelta import relativedelta from datetime import datetime, timedelta @@ -430,89 +430,79 @@ class EmailAccount(Document): def receive(self, test_mails=None): """Called by scheduler to receive emails from this EMail account using POP3/IMAP.""" - def get_seen(status): - if not status: - return None - seen = 1 if status == "SEEN" else 0 - return seen + exceptions = [] + inbound_mails = self.get_inbound_mails(test_mails=test_mails) + for mail in inbound_mails: + try: + communication = mail.process() + frappe.db.commit() + # If email already exists in the system + # then do not send notifications for the same email. + if communication and mail.flags.is_new_communication: + # notify all participants of this thread + if self.enable_auto_reply: + self.send_auto_reply(communication, mail) - if self.enable_incoming: - uid_list = [] - exceptions = [] - seen_status = [] - uid_reindexed = False - email_server = None + attachments = [] + if hasattr(communication, '_attachments'): + attachments = [d.file_name for d in communication._attachments] + communication.notify(attachments=attachments, fetched_from_email_account=True) + except SentEmailInInboxError: + frappe.db.rollback() + except Exception: + frappe.db.rollback() + frappe.log_error('email_account.receive') + if self.use_imap: + self.handle_bad_emails(mail.uid, mail.raw_message, frappe.get_traceback()) + exceptions.append(frappe.get_traceback()) - if frappe.local.flags.in_test: - incoming_mails = test_mails or [] - else: - email_sync_rule = self.build_email_sync_rule() + #notify if user is linked to account + if len(inbound_mails)>0 and not frappe.local.flags.in_test: + frappe.publish_realtime('new_email', + {"account":self.email_account_name, "number":len(inbound_mails)} + ) - try: - email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) - except Exception: - frappe.log_error(title=_("Error while connecting to email account {0}").format(self.name)) + if exceptions: + raise Exception(frappe.as_json(exceptions)) - if not email_server: - return + def get_inbound_mails(self, test_mails=None): + """retrive and return inbound mails. - emails = email_server.get_messages() - if not emails: - return + TODO: Handle for tests + """ + if not self.enable_incoming: + return [] - incoming_mails = emails.get("latest_messages", []) - uid_list = emails.get("uid_list", []) - seen_status = emails.get("seen_status", []) - uid_reindexed = emails.get("uid_reindexed", False) + if frappe.local.flags.in_test: + return [InboundMail(msg, self) for msg in test_mails or []] - for idx, msg in enumerate(incoming_mails): - uid = None if not uid_list else uid_list[idx] - self.flags.notify = True + email_sync_rule = self.build_email_sync_rule() + try: + email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) + messages = email_server.get_messages() or {} + except Exception: + raise + print("In exception...") + frappe.log_error(title=_("Error while connecting to email account {0}").format(self.name)) + return [] - try: - args = { - "uid": uid, - "seen": None if not seen_status else get_seen(seen_status.get(uid, None)), - "uid_reindexed": uid_reindexed - } - communication = self.insert_communication(msg, args=args) + mails = [] + for index, message in enumerate(messages.get("latest_messages", [])): + print("RAW MESSAGE TYPE: ", type(message)) + uid = messages['uid_list'][index] + seen_status = 1 if messages['seen_status'][uid]=='SEEN' else 0 + mails.append(InboundMail(message, self, uid, seen_status)) - except SentEmailInInbox: - frappe.db.rollback() + return mails - except Exception: - frappe.db.rollback() - frappe.log_error('email_account.receive') - if self.use_imap: - self.handle_bad_emails(email_server, uid, msg, frappe.get_traceback()) - exceptions.append(frappe.get_traceback()) - - else: - frappe.db.commit() - if communication and self.flags.notify: - - # If email already exists in the system - # then do not send notifications for the same email. - - attachments = [] - - if hasattr(communication, '_attachments'): - attachments = [d.file_name for d in communication._attachments] - - communication.notify(attachments=attachments, fetched_from_email_account=True) - - #notify if user is linked to account - if len(incoming_mails)>0 and not frappe.local.flags.in_test: - frappe.publish_realtime('new_email', {"account":self.email_account_name, "number":len(incoming_mails)}) - - if exceptions: - raise Exception(frappe.as_json(exceptions)) - - def handle_bad_emails(self, email_server, uid, raw, reason): - if email_server and cint(email_server.settings.use_imap): + def handle_bad_emails(self, uid, raw, reason): + if cint(self.use_imap): import email try: - mail = email.message_from_string(raw) + if isinstance(raw, bytes): + mail = email.message_from_bytes(raw) + else: + mail = email.message_from_string(raw) message_id = mail.get('Message-ID') except Exception: @@ -524,275 +514,18 @@ class EmailAccount(Document): "reason":reason, "message_id": message_id, "doctype": "Unhandled Email", - "email_account": email_server.settings.email_account + "email_account": self.name }) unhandled_email.insert(ignore_permissions=True) frappe.db.commit() - def insert_communication(self, msg, args=None): - if isinstance(msg, list): - raw, uid, seen = msg - else: - raw = msg - uid = -1 - seen = 0 - if isinstance(args, dict): - if args.get("uid", -1): uid = args.get("uid", -1) - if args.get("seen", 0): seen = args.get("seen", 0) - - email = Email(raw) - - if email.from_email == self.email_id and not email.mail.get("Reply-To"): - # gmail shows sent emails in inbox - # and we don't want emails sent by us to be pulled back into the system again - # dont count emails sent by the system get those - if frappe.flags.in_test: - print('WARN: Cannot pull email. Sender sames as recipient inbox') - raise SentEmailInInbox - - if email.message_id: - # https://stackoverflow.com/a/18367248 - names = frappe.db.sql("""SELECT DISTINCT `name`, `creation` FROM `tabCommunication` - WHERE `message_id`='{message_id}' - ORDER BY `creation` DESC LIMIT 1""".format( - message_id=email.message_id - ), as_dict=True) - - if names: - name = names[0].get("name") - # email is already available update communication uid instead - frappe.db.set_value("Communication", name, "uid", uid, update_modified=False) - - self.flags.notify = False - - return frappe.get_doc("Communication", name) - - if email.content_type == 'text/html': - email.content = clean_email_html(email.content) - - communication = frappe.get_doc({ - "doctype": "Communication", - "subject": email.subject, - "content": email.content, - 'text_content': email.text_content, - "sent_or_received": "Received", - "sender_full_name": email.from_real_name, - "sender": email.from_email, - "recipients": email.mail.get("To"), - "cc": email.mail.get("CC"), - "email_account": self.name, - "communication_medium": "Email", - "uid": int(uid or -1), - "message_id": email.message_id, - "communication_date": email.date, - "has_attachment": 1 if email.attachments else 0, - "seen": seen or 0 - }) - - self.set_thread(communication, email) - if communication.seen: - # get email account user and set communication as seen - users = frappe.get_all("User Email", filters={ "email_account": self.name }, - fields=["parent"]) - users = list(set([ user.get("parent") for user in users ])) - communication._seen = json.dumps(users) - - communication.flags.in_receive = True - communication.insert(ignore_permissions=True) - - # save attachments - communication._attachments = email.save_attachments_in_doc(communication) - - # replace inline images - dirty = False - for file in communication._attachments: - if file.name in email.cid_map and email.cid_map[file.name]: - dirty = True - - email.content = email.content.replace("cid:{0}".format(email.cid_map[file.name]), - file.file_url) - - if dirty: - # not sure if using save() will trigger anything - communication.db_set("content", sanitize_html(email.content)) - - # notify all participants of this thread - if self.enable_auto_reply and getattr(communication, "is_first", False): - self.send_auto_reply(communication, email) - - return communication - - def set_thread(self, communication, email): - """Appends communication to parent based on thread ID. Will extract - parent communication and will link the communication to the reference of that - communication. Also set the status of parent transaction to Open or Replied. - - If no thread id is found and `append_to` is set for the email account, - it will create a new parent transaction (e.g. Issue)""" - parent = None - - parent = self.find_parent_from_in_reply_to(communication, email) - - if not parent and self.append_to: - self.set_sender_field_and_subject_field() - - if not parent and self.append_to: - parent = self.find_parent_based_on_subject_and_sender(communication, email) - - if not parent and self.append_to and self.append_to!="Communication": - parent = self.create_new_parent(communication, email) - - if parent: - communication.reference_doctype = parent.doctype - communication.reference_name = parent.name - - # check if message is notification and disable notifications for this message - isnotification = email.mail.get("isnotification") - if isnotification: - if "notification" in isnotification: - communication.unread_notification_sent = 1 - - def set_sender_field_and_subject_field(self): - '''Identify the sender and subject fields from the `append_to` DocType''' - # set subject_field and sender_field - meta = frappe.get_meta(self.append_to) - self.subject_field = None - self.sender_field = None - - if hasattr(meta, "subject_field"): - self.subject_field = meta.subject_field - - if hasattr(meta, "sender_field"): - self.sender_field = meta.sender_field - - def find_parent_based_on_subject_and_sender(self, communication, email): - '''Find parent document based on subject and sender match''' - parent = None - - if self.append_to and self.sender_field: - if self.subject_field: - if '#' in email.subject: - # try and match if ID is found - # document ID is appended to subject - # example "Re: Your email (#OPP-2020-2334343)" - parent_id = email.subject.rsplit('#', 1)[-1].strip(' ()') - if parent_id: - parent = frappe.db.get_all(self.append_to, filters = dict(name = parent_id), - fields = 'name') - - if not parent: - # try and match by subject and sender - # if sent by same sender with same subject, - # append it to old coversation - subject = frappe.as_unicode(strip(re.sub(r"(^\s*(fw|fwd|wg)[^:]*:|\s*(re|aw)[^:]*:\s*)*", - "", email.subject, 0, flags=re.IGNORECASE))) - - parent = frappe.db.get_all(self.append_to, filters={ - self.sender_field: email.from_email, - self.subject_field: ("like", "%{0}%".format(subject)), - "creation": (">", (get_datetime() - relativedelta(days=60)).strftime(DATE_FORMAT)) - }, fields = "name", limit = 1) - - if not parent and len(subject) > 10 and is_system_user(email.from_email): - # match only subject field - # when the from_email is of a user in the system - # and subject is atleast 10 chars long - parent = frappe.db.get_all(self.append_to, filters={ - self.subject_field: ("like", "%{0}%".format(subject)), - "creation": (">", (get_datetime() - relativedelta(days=60)).strftime(DATE_FORMAT)) - }, fields = "name", limit = 1) - - - - if parent: - parent = frappe._dict(doctype=self.append_to, name=parent[0].name) - return parent - - def create_new_parent(self, communication, email): - '''If no parent found, create a new reference document''' - - # no parent found, but must be tagged - # insert parent type doc - parent = frappe.new_doc(self.append_to) - - if self.subject_field: - parent.set(self.subject_field, frappe.as_unicode(email.subject)[:140]) - - if self.sender_field: - parent.set(self.sender_field, frappe.as_unicode(email.from_email)) - - if parent.meta.has_field("email_account"): - parent.email_account = self.name - - parent.flags.ignore_mandatory = True - - try: - parent.insert(ignore_permissions=True) - except frappe.DuplicateEntryError: - # try and find matching parent - parent_name = frappe.db.get_value(self.append_to, {self.sender_field: email.from_email}) - if parent_name: - parent.name = parent_name - else: - parent = None - - # NOTE if parent isn't found and there's no subject match, it is likely that it is a new conversation thread and hence is_first = True - communication.is_first = True - - return parent - - def find_parent_from_in_reply_to(self, communication, email): - '''Returns parent reference if embedded in In-Reply-To header - - Message-ID is formatted as `{message_id}@{site}`''' - parent = None - in_reply_to = (email.mail.get("In-Reply-To") or "").strip(" <>") - - if in_reply_to: - if "@{0}".format(frappe.local.site) in in_reply_to: - # reply to a communication sent from the system - email_queue = frappe.db.get_value('Email Queue', dict(message_id=in_reply_to), ['communication','reference_doctype', 'reference_name']) - if email_queue: - parent_communication, parent_doctype, parent_name = email_queue - if parent_communication: - communication.in_reply_to = parent_communication - else: - reference, domain = in_reply_to.split("@", 1) - parent_doctype, parent_name = 'Communication', reference - - if frappe.db.exists(parent_doctype, parent_name): - parent = frappe._dict(doctype=parent_doctype, name=parent_name) - - # set in_reply_to of current communication - if parent_doctype=='Communication': - # communication.in_reply_to = email_queue.communication - - if parent.reference_name: - # the true parent is the communication parent - parent = frappe.get_doc(parent.reference_doctype, - parent.reference_name) - else: - comm = frappe.db.get_value('Communication', - dict( - message_id=in_reply_to, - creation=['>=', add_days(get_datetime(), -30)]), - ['reference_doctype', 'reference_name'], as_dict=1) - if comm: - parent = frappe._dict(doctype=comm.reference_doctype, name=comm.reference_name) - - return parent - def send_auto_reply(self, communication, email): """Send auto reply if set.""" from frappe.core.doctype.communication.email import set_incoming_outgoing_accounts - if self.enable_auto_reply: set_incoming_outgoing_accounts(communication) - if self.send_unsubscribe_message: - unsubscribe_message = _("Leave this conversation") - else: - unsubscribe_message = "" + unsubscribe_message = (self.send_unsubscribe_message and _("Leave this conversation")) or "" frappe.sendmail(recipients = [email.from_email], sender = self.email_id, diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index 076dfc5417..3c34182fe6 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -45,6 +45,11 @@ class EmailQueue(Document): def find(cls, name): return frappe.get_doc(cls.DOCTYPE, name) + @classmethod + def find_one_by_filters(cls, **kwargs): + name = frappe.db.get_value(cls.DOCTYPE, kwargs) + return cls.find(name) if name else None + def update_db(self, commit=False, **kwargs): frappe.db.set_value(self.DOCTYPE, self.name, kwargs) if commit: diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py index 45888119ea..7a24583c83 100755 --- a/frappe/email/email_body.py +++ b/frappe/email/email_body.py @@ -359,9 +359,7 @@ def add_attachment(fname, fcontent, content_type=None, def get_message_id(): '''Returns Message ID created from doctype and name''' - return "<{unique}@{site}>".format( - site=frappe.local.site, - unique=email.utils.make_msgid(random_string(10)).split('@')[0].split('<')[1]) + return email.utils.make_msgid(domain=frappe.local.site) def get_signature(email_account): if email_account and email_account.add_signature and email_account.signature: diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 949da4a343..52b9110ddb 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -8,6 +8,7 @@ import imaplib import poplib import re import time +import json from email.header import decode_header import _socket @@ -20,13 +21,26 @@ from frappe import _, safe_decode, safe_encode from frappe.core.doctype.file.file import (MaxFileSizeReachedError, get_random_filename) from frappe.utils import (cint, convert_utc_to_user_timezone, cstr, - extract_email_id, markdown, now, parse_addr, strip) + extract_email_id, markdown, now, parse_addr, strip, get_datetime, + add_days, sanitize_html) +from frappe.utils.user import is_system_user +from frappe.utils.html_utils import clean_email_html + +# fix due to a python bug in poplib that limits it to 2048 +poplib._MAXLINE = 20480 +imaplib._MAXLINE = 20480 + +# fix due to a python bug in poplib that limits it to 2048 +poplib._MAXLINE = 20480 +imaplib._MAXLINE = 20480 class EmailSizeExceededError(frappe.ValidationError): pass class EmailTimeoutError(frappe.ValidationError): pass class TotalSizeExceededError(frappe.ValidationError): pass class LoginLimitExceeded(frappe.ValidationError): pass +class SentEmailInInboxError(Exception): + pass class EmailServer: """Wrapper for POP server to pull emails.""" @@ -100,14 +114,11 @@ class EmailServer: def get_messages(self): """Returns new email messages in a list.""" - if not self.check_mails(): - return # nothing to do + if not (self.check_mails() or self.connect()): + return [] frappe.db.commit() - if not self.connect(): - return - uid_list = [] try: @@ -116,7 +127,6 @@ class EmailServer: self.latest_messages = [] self.seen_status = {} self.uid_reindexed = False - uid_list = email_list = self.get_new_mails() if not email_list: @@ -132,11 +142,7 @@ class EmailServer: self.max_email_size = cint(frappe.local.conf.get("max_email_size")) self.max_total_size = 5 * self.max_email_size - for i, message_meta in enumerate(email_list): - # do not pull more than NUM emails - if (i+1) > num: - break - + for i, message_meta in enumerate(email_list[:num]): try: self.retrieve_message(message_meta, i+1) except (TotalSizeExceededError, EmailTimeoutError, LoginLimitExceeded): @@ -152,7 +158,6 @@ class EmailServer: except Exception as e: if self.has_login_limit_exceeded(e): pass - else: raise @@ -284,7 +289,7 @@ class EmailServer: flags = [] for flag in imaplib.ParseFlags(flag_string) or []: - pattern = re.compile("\w+") + pattern = re.compile(r"\w+") match = re.search(pattern, frappe.as_unicode(flag)) flags.append(match.group(0)) @@ -369,6 +374,7 @@ class Email: else: self.mail = email.message_from_string(content) + self.raw_message = content self.text_content = '' self.html_content = '' self.attachments = [] @@ -391,6 +397,10 @@ class Email: if self.date > now(): self.date = now() + @property + def in_reply_to(self): + return (self.mail.get("In-Reply-To") or "").strip(" <>") + def parse(self): """Walk and process multi-part email.""" for part in self.mail.walk(): @@ -555,13 +565,335 @@ class Email: def get_thread_id(self): """Extract thread ID from `[]`""" - l = re.findall('(?<=\[)[\w/-]+', self.subject) + l = re.findall(r'(?<=\[)[\w/-]+', self.subject) return l and l[0] or None + def is_reply(self): + return bool(self.in_reply_to) -# fix due to a python bug in poplib that limits it to 2048 -poplib._MAXLINE = 20480 -imaplib._MAXLINE = 20480 +class InboundMail(Email): + """Class representation of incoming mail along with mail handlers. + """ + def __init__(self, content, email_account, uid=None, seen_status=None): + super().__init__(content) + self.email_account = email_account + self.uid = uid or -1 + self.seen_status = seen_status or 0 + + # System documents related to this mail + self._parent_email_queue = None + self._parent_communication = None + self._reference_document = None + + self.flags = frappe._dict() + + def get_content(self): + if self.content_type == 'text/html': + return clean_email_html(self.content) + + def process(self): + """Create communication record from email. + """ + if self.is_sender_same_as_receiver() and not self.is_reply(): + if frappe.flags.in_test: + print('WARN: Cannot pull email. Sender same as recipient inbox') + raise SentEmailInInboxError + + communication = self.is_exist_in_system() + if communication: + communication.update_db(uid=self.uid) + communication.reload() + return communication + + self.flags.is_new_communication = True + return self._build_communication_doc() + + def _build_communication_doc(self): + data = self.as_dict() + data['doctype'] = "Communication" + + if self.parent_communication(): + data['in_reply_to'] = self.parent_communication().name + + if self.reference_document(): + data['reference_doctype'] = self.reference_document().doctype + data['reference_name'] = self.reference_document().name + elif self.email_account.append_to and self.email_account.append_to != 'Communication': + reference_doc = self._create_reference_document(self.email_account.append_to) + if reference_doc: + data['reference_doctype'] = reference_doc.doctype + data['reference_name'] = reference_doc.name + data['is_first'] = True + + if self.is_notification(): + # Disable notifications for notification. + data['unread_notification_sent'] = 1 + + if self.seen_status: + data['_seen'] = json.dumps(self.get_users_linked_to_account(self.email_account)) + + communication = frappe.get_doc(data) + communication.flags.in_receive = True + communication.insert(ignore_permissions=True) + + # save attachments + communication._attachments = self.save_attachments_in_doc(communication) + communication.content = sanitize_html(self.replace_inline_images(communication._attachments)) + communication.save() + return communication + + def replace_inline_images(self, attachments): + # replace inline images + content = self.content + for file in attachments: + if file.name in self.cid_map and self.cid_map[file.name]: + content = content.replace("cid:{0}".format(self.cid_map[file.name]), + file.file_url) + return content + + def is_notification(self): + isnotification = self.mail.get("isnotification") + return isnotification and ("notification" in isnotification) + + def is_exist_in_system(self): + """Check if this email already exists in the system(as communication document). + """ + from frappe.core.doctype.communication.communication import Communication + if not self.message_id: + return + + return Communication.find_one_by_filters(message_id = self.message_id, + order_by = 'creation DESC') + + def is_sender_same_as_receiver(self): + return self.from_email == self.email_account.email_id + + def is_reply_to_system_sent_mail(self): + """Is it a reply to already sent mail. + """ + return self.is_reply() and frappe.local.site in self.in_reply_to + + def parent_email_queue(self): + """Get parent record from `Email Queue`. + + If it is a reply to already sent mail, then there will be a parent record in EMail Queue. + """ + from frappe.email.doctype.email_queue.email_queue import EmailQueue + + if self._parent_email_queue is not None: + return self._parent_email_queue + + parent_email_queue = '' + if self.is_reply_to_system_sent_mail(): + parent_email_queue = EmailQueue.find_one_by_filters(message_id=self.in_reply_to) + + self._parent_email_queue = parent_email_queue or '' + return self._parent_email_queue + + def parent_communication(self): + """Find a related communication so that we can prepare a mail thread. + + The way it happens is by using in-reply-to header, and we can't make thread if it does not exist. + + Here are the cases to handle: + 1. If mail is a reply to already sent mail, then we can get parent communicaion from + Email Queue record. + 2. Sometimes we send communication name in message-ID directly, use that to get parent communication. + 3. Sender sent a reply but reply is on top of what (s)he sent before, + then parent record exists directly in communication. + """ + from frappe.core.doctype.communication.communication import Communication + if self._parent_communication is not None: + return self._parent_communication + + if not self.is_reply(): + return '' + + if not self.is_reply_to_system_sent_mail(): + communication = Communication.find_one_by_filters(message_id=self.in_reply_to, + creation = ['>=', self.get_relative_dt(-30)]) + elif self.parent_email_queue() and self.parent_email_queue().communication: + communication = Communication.find(self.parent_email_queue().communication, ignore_error=True) + else: + reference = self.in_reply_to + if '@' in self.in_reply_to: + reference, _ = self.in_reply_to.split("@", 1) + communication = Communication.find(reference, ignore_error=True) + + self._parent_communication = communication or '' + return self._parent_communication + + def reference_document(self): + """Reference document is a document to which mail relate to. + + We can get reference document from Parent record(EmailQueue | Communication) if exists. + Otherwise we do subject match to find reference document if we know the reference(append_to) doctype. + """ + if self._reference_document is not None: + return self._reference_document + + reference_document = "" + parent = self.parent_email_queue() or self.parent_communication() + + if parent and parent.reference_doctype: + reference_doctype, reference_name = parent.reference_doctype, parent.reference_name + reference_document = self.get_doc(reference_doctype, reference_name, ignore_error=True) + + if not reference_document and self.email_account.append_to: + reference_document = self.match_record_by_subject_and_sender(self.email_account.append_to) + + # if not reference_document: + # reference_document = Create_reference_document(self.email_account.append_to) + + self._reference_document = reference_document or '' + return self._reference_document + + def get_reference_name_from_subject(self): + """ + Ex: "Re: Your email (#OPP-2020-2334343)" + """ + return self.subject.rsplit('#', 1)[-1].strip(' ()') + + def match_record_by_subject_and_sender(self, doctype): + """Find a record in the given doctype that matches with email subject and sender. + + Cases: + 1. Sometimes record name is part of subject. We can get document by parsing name from subject + 2. Find by matching sender and subject + 3. Find by matching subject alone (Special case) + Ex: when a System User is using Outlook and replies to an email from their own client, + it reaches the Email Account with the threading info lost and the (sender + subject match) + doesn't work because the sender in the first communication was someone different to whom + the system user is replying to via the common email account in Frappe. This fix bypasses + the sender match when the sender is a system user and subject is atleast 10 chars long + (for additional safety) + + NOTE: We consider not to match by subject if match record is very old. + """ + name = self.get_reference_name_from_subject() + email_fields = self.get_email_fields(doctype) + + record = self.get_doc(doctype, name, ignore_error=True) if name else None + + if not record: + subject = self.clean_subject(self.subject) + filters = { + email_fields.subject_field: ("like", f"%{subject}%"), + "creation": (">", self.get_relative_dt(days=-60)) + } + + # Sender check is not needed incase mail is from system user. + if not (len(subject) > 10 and is_system_user(self.from_email)): + filters[email_fields.sender_field] = self.from_email + + name = frappe.db.get_value(self.email_account.append_to, filters = filters) + record = self.get_doc(doctype, name, ignore_error=True) if name else None + return record + + def _create_reference_document(self, doctype): + """ Create reference document if it does not exist in the system. + """ + parent = frappe.new_doc(doctype) + email_fileds = self.get_email_fields(doctype) + + if email_fileds.subject_field: + parent.set(email_fileds.subject_field, frappe.as_unicode(self.subject)[:140]) + + if email_fileds.sender_field: + parent.set(email_fileds.sender_field, frappe.as_unicode(self.from_email)) + + parent.flags.ignore_mandatory = True + + try: + parent.insert(ignore_permissions=True) + except frappe.DuplicateEntryError: + # try and find matching parent + parent_name = frappe.db.get_value(self.email_account.append_to, + {email_fileds.sender_field: email.from_email} + ) + if parent_name: + parent.name = parent_name + else: + parent = None + return parent + + + @staticmethod + def get_doc(doctype, docname, ignore_error=False): + try: + print(doctype, docname) + return frappe.get_doc(doctype, docname) + except frappe.DoesNotExistError: + if ignore_error: + return + raise + + @staticmethod + def get_relative_dt(days): + """Get relative to current datetime. Only relative days are supported. + """ + return add_days(get_datetime(), days) + + @staticmethod + def get_users_linked_to_account(email_account): + """Get list of users who linked to Email account. + """ + users = frappe.get_all("User Email", filters={"email_account": email_account.name}, + fields=["parent"]) + return list(set([user.get("parent") for user in users])) + + @staticmethod + def clean_subject(subject): + """Remove Prefixes like 'fw', FWD', 're' etc from subject. + """ + # Match strings like "fw:", "re :" etc. + regex = r"(^\s*(fw|fwd|wg)[^:]*:|\s*(re|aw)[^:]*:\s*)*" + return frappe.as_unicode(strip(re.sub(regex, "", subject, 0, flags=re.IGNORECASE))) + + @staticmethod + def get_email_fields(doctype): + """Returns Email related fields of a doctype. + """ + fields = frappe._dict() + + email_fields = ['subject_field', 'sender_field'] + meta = frappe.get_meta(doctype) + + for field in email_fields: + if hasattr(meta, field): + fields[field] = getattr(meta, field) + print("FIELDS::::", fields) + return fields + + @staticmethod + def get_document(self, doctype, name): + """Is same as frappe.get_doc but suppresses the DoesNotExist error. + """ + try: + return frappe.get_doc(doctype, name) + except frappe.DoesNotExistError: + return None + + def as_dict(self): + """ + """ + return { + "subject": self.subject, + "content": self.get_content(), + 'text_content': self.text_content, + "sent_or_received": "Received", + "sender_full_name": self.from_real_name, + "sender": self.from_email, + "recipients": self.mail.get("To"), + "cc": self.mail.get("CC"), + "email_account": self.email_account.name, + "communication_medium": "Email", + "uid": self.uid, + "message_id": self.message_id, + "communication_date": self.date, + "has_attachment": 1 if self.attachments else 0, + "seen": self.seen_status or 0 + } class TimerMixin(object): def __init__(self, *args, **kwargs): diff --git a/frappe/hooks.py b/frappe/hooks.py index 1c78d47755..740aa94d9f 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -202,9 +202,9 @@ scheduler_events = { ] }, "all": [ - "frappe.email.queue.flush", - "frappe.email.doctype.email_account.email_account.pull", - "frappe.email.doctype.email_account.email_account.notify_unreplied", + # "frappe.email.queue.flush", + # "frappe.email.doctype.email_account.email_account.pull", + # "frappe.email.doctype.email_account.email_account.notify_unreplied", "frappe.integrations.doctype.razorpay_settings.razorpay_settings.capture_payment", 'frappe.utils.global_search.sync_global_search', "frappe.monitor.flush", From 78468508d4258ec8f810fac9bc41551d1a498c56 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Sun, 23 May 2021 13:11:02 +0530 Subject: [PATCH 143/868] fix: grid navigation with keyboard on multiple pages --- frappe/public/js/frappe/form/grid_row.js | 41 ++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 453b8b5f24..c25d074416 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -523,7 +523,7 @@ export default class GridRow { // hide other var open_row = this.get_open_form(); - if (show===undefined) show = !!!open_row; + if (show === undefined) show = !open_row; // call blur document.activeElement && document.activeElement.blur(); @@ -588,19 +588,42 @@ export default class GridRow { this.wrapper.removeClass("grid-row-open"); } open_prev() { - const row_index = this.wrapper.index(); - if (this.grid.grid_rows[row_index - 1]) { - this.grid.grid_rows[row_index - 1].toggle_view(true); - } + if (!this.doc) return; + this.open_row_at_index(this.doc.idx - 2); } open_next() { - const row_index = this.wrapper.index(); - if (this.grid.grid_rows[row_index + 1]) { - this.grid.grid_rows[row_index + 1].toggle_view(true); - } else { + if (!this.doc) return; + + if (!this.open_row_at_index(this.doc.idx)) { this.grid.add_new_row(null, null, true); } } + open_row_at_index(row_index) { + if (!this.grid.data[row_index]) return; + + this.change_page_if_reqd(row_index); + this.grid.grid_rows[row_index].toggle_view(true); + return true; + } + change_page_if_reqd(row_index) { + const { + page_index, + page_length + } = this.grid.grid_pagination; + + row_index++; + let new_page; + + if (row_index <= (page_index - 1) * page_length) { + new_page = page_index - 1; + } else if (row_index > page_index * page_length) { + new_page = page_index + 1; + } + + if (new_page) { + this.grid.grid_pagination.go_to_page(new_page); + } + } refresh_field(fieldname, txt) { let df = this.docfields.find(col => { return col.fieldname === fieldname; From 39e6c040de40564b8186827a437b37f3ace54c00 Mon Sep 17 00:00:00 2001 From: leela Date: Fri, 21 May 2021 18:57:40 +0530 Subject: [PATCH 144/868] test: Incoming mail tests are added --- .../doctype/communication/communication.py | 17 -- .../doctype/email_account/email_account.py | 3 - .../email_account/test_email_account.py | 245 +++++++++++++++++- .../test_mails/incoming-self-sent.raw | 91 +++++++ .../incoming-subject-placeholder.raw | 183 +++++++++++++ frappe/hooks.py | 6 +- 6 files changed, 509 insertions(+), 36 deletions(-) create mode 100644 frappe/email/doctype/email_account/test_mails/incoming-self-sent.raw create mode 100644 frappe/email/doctype/email_account/test_mails/incoming-subject-placeholder.raw diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index a9c1c1f5a3..9879807033 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -199,8 +199,6 @@ class Communication(Document): if not self.sender_full_name: self.sender_full_name = sender_email - - def send(self, print_html=None, print_format=None, attachments=None, send_me_a_copy=False, recipients=None): """Send communication via Email. @@ -327,21 +325,6 @@ class Communication(Document): if autosave: self.save(ignore_permissions=ignore_permissions) - # @classmethod - # def add_incoming_mail(cls, email, uid, seen_status): - # if exists_already(): - # pass # Modify UID - # else: - # pass # Call new() to create object -class InMailMixin: - @classmethod - def add_incoming_mail(cls, email, uid, seen_status): - if exists_already(): - pass # Modify UID - else: - pass # Call new() to create object - - def on_doctype_update(): """Add indexes in `tabCommunication`""" frappe.db.add_index("Communication", ["reference_doctype", "reference_name"]) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 0a66efb480..eea2dfc73e 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -468,7 +468,6 @@ class EmailAccount(Document): def get_inbound_mails(self, test_mails=None): """retrive and return inbound mails. - TODO: Handle for tests """ if not self.enable_incoming: return [] @@ -482,13 +481,11 @@ class EmailAccount(Document): messages = email_server.get_messages() or {} except Exception: raise - print("In exception...") frappe.log_error(title=_("Error while connecting to email account {0}").format(self.name)) return [] mails = [] for index, message in enumerate(messages.get("latest_messages", [])): - print("RAW MESSAGE TYPE: ", type(message)) uid = messages['uid_list'][index] seen_status = 1 if messages['seen_status'][uid]=='SEEN' else 0 mails.append(InboundMail(message, self, uid, seen_status)) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index f87ee32bb1..7bf49593f4 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -2,6 +2,10 @@ # See license.txt from __future__ import unicode_literals +from frappe.core.doctype import communication +from frappe.core.doctype.communication.communication import Communication +from frappe.email.receive import InboundMail, SentEmailInInboxError, Email +from frappe.email.email_body import get_message_id import frappe, os import unittest, email @@ -16,30 +20,37 @@ from frappe.email.doctype.email_account.email_account import notify_unreplied from datetime import datetime, timedelta class TestEmailAccount(unittest.TestCase): + @classmethod + def setUpClass(cls): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.db_set("enable_incoming", 1) + email_account.db_set("enable_auto_reply", 1) + + @classmethod + def tearDownClass(cls): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.db_set("enable_incoming", 0) + def setUp(self): frappe.flags.mute_emails = False frappe.flags.sent_mail = None - - email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.db_set("enable_incoming", 1) frappe.db.sql('delete from `tabEmail Queue`') + frappe.db.sql('delete from `tabUnhandled Email`') - def tearDown(self): - email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.db_set("enable_incoming", 0) + def get_test_mail(self, fname): + with open(os.path.join(os.path.dirname(__file__), "test_mails", fname), "r") as f: + return f.read() def test_incoming(self): cleanup("test_sender@example.com") - with open(os.path.join(os.path.dirname(__file__), "test_mails", "incoming-1.raw"), "r") as f: - test_mails = [f.read()] + test_mails = [self.get_test_mail('incoming-1.raw')] email_account = frappe.get_doc("Email Account", "_Test Email Account 1") email_account.receive(test_mails=test_mails) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) self.assertTrue("test_receiver@example.com" in comm.recipients) - # check if todo is created self.assertTrue(frappe.db.get_value(comm.reference_doctype, comm.reference_name, "name")) @@ -88,7 +99,7 @@ class TestEmailAccount(unittest.TestCase): email_account.receive(test_mails=test_mails) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) - self.assertTrue("From: \"Microsoft Outlook\" <test_sender@example.com>" in comm.content) + self.assertTrue("From: "Microsoft Outlook" <test_sender@example.com>" in comm.content) self.assertTrue("This is an e-mail message sent automatically by Microsoft Outlook while" in comm.content) def test_incoming_attached_email_from_outlook_layers(self): @@ -101,7 +112,7 @@ class TestEmailAccount(unittest.TestCase): email_account.receive(test_mails=test_mails) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) - self.assertTrue("From: \"Microsoft Outlook\" <test_sender@example.com>" in comm.content) + self.assertTrue("From: "Microsoft Outlook" <test_sender@example.com>" in comm.content) self.assertTrue("This is an e-mail message sent automatically by Microsoft Outlook while" in comm.content) def test_outgoing(self): @@ -166,7 +177,6 @@ class TestEmailAccount(unittest.TestCase): comm_list = frappe.get_all("Communication", filters={"sender":"test_sender@example.com"}, fields=["name", "reference_doctype", "reference_name"]) - # both communications attached to the same reference self.assertEqual(comm_list[0].reference_doctype, comm_list[1].reference_doctype) self.assertEqual(comm_list[0].reference_name, comm_list[1].reference_name) @@ -199,6 +209,215 @@ class TestEmailAccount(unittest.TestCase): self.assertEqual(comm_list[0].reference_doctype, event.doctype) self.assertEqual(comm_list[0].reference_name, event.name) + def test_auto_reply(self): + cleanup("test_sender@example.com") + + test_mails = [self.get_test_mail('incoming-1.raw')] + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.receive(test_mails=test_mails) + + comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) + self.assertTrue(frappe.db.get_value("Email Queue", {"reference_doctype": comm.reference_doctype, + "reference_name": comm.reference_name})) + + def test_handle_bad_emails(self): + mail_content = self.get_test_mail(fname="incoming-1.raw") + message_id = Email(mail_content).mail.get('Message-ID') + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.handle_bad_emails(uid=-1, raw=mail_content, reason="Testing") + self.assertTrue(frappe.db.get_value("Unhandled Email", {'message_id': message_id})) + +class TestInboundMail(unittest.TestCase): + @classmethod + def setUpClass(cls): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.db_set("enable_incoming", 1) + + @classmethod + def tearDownClass(cls): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.db_set("enable_incoming", 0) + + def tearDown(self): + cleanup() + frappe.db.sql('delete from `tabEmail Queue`') + frappe.db.sql('delete from `tabToDo`') + + def get_test_mail(self, fname): + with open(os.path.join(os.path.dirname(__file__), "test_mails", fname), "r") as f: + return f.read() + + def new_doc(self, doctype, **data): + doc = frappe.new_doc(doctype) + for field, value in data.items(): + setattr(doc, field, value) + doc.insert() + return doc + + def new_communication(self, **kwargs): + defaults = { + 'subject': "Test Subject" + } + d = {**defaults, **kwargs} + return self.new_doc('Communication', **d) + + def new_email_queue(self, **kwargs): + defaults = { + 'message_id': get_message_id().strip(" <>") + } + d = {**defaults, **kwargs} + return self.new_doc('Email Queue', **d) + + def new_todo(self, **kwargs): + defaults = { + 'description': "Description" + } + d = {**defaults, **kwargs} + return self.new_doc('ToDo', **d) + + def test_self_sent_mail(self): + """Check that we raise SentEmailInInboxError if the inbound mail is self sent mail. + """ + mail_content = self.get_test_mail(fname="incoming-self-sent.raw") + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 1, 1) + with self.assertRaises(SentEmailInInboxError): + inbound_mail.process() + + def test_mail_exist_validation(self): + """Do not create communication record if the mail is already downloaded into the system. + """ + mail_content = self.get_test_mail(fname="incoming-1.raw") + message_id = Email(mail_content).message_id + # Create new communication record in DB + communication = self.new_communication(message_id=message_id) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + new_communiction = inbound_mail.process() + + # Make sure that uid is changed to new uid + self.assertEqual(new_communiction.uid, 12345) + self.assertEqual(communication.name, new_communiction.name) + + def test_find_parent_email_queue(self): + """If the mail is reply to the already sent mail, there will be a email queue record. + """ + # Create email queue record + queue_record = self.new_email_queue() + + mail_content = self.get_test_mail(fname="reply-4.raw").replace( + "{{ message_id }}", queue_record.message_id + ) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + parent_queue = inbound_mail.parent_email_queue() + self.assertEqual(queue_record.name, parent_queue.name) + + def test_find_parent_communication_through_queue(self): + """Find parent communication of an inbound mail. + Cases where parent communication does exist: + 1. No parent communication is the mail is not a reply. + + Cases where parent communication does not exist: + 2. If mail is not a reply to system sent mail, then there can exist co + """ + # Create email queue record + communication = self.new_communication() + queue_record = self.new_email_queue(communication=communication.name) + mail_content = self.get_test_mail(fname="reply-4.raw").replace( + "{{ message_id }}", queue_record.message_id + ) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + parent_communication = inbound_mail.parent_communication() + self.assertEqual(parent_communication.name, communication.name) + + def test_find_parent_communication_for_self_reply(self): + """If the inbound email is a reply but not reply to system sent mail. + + Ex: User replied to his/her mail. + """ + message_id = "new-message-id" + mail_content = self.get_test_mail(fname="reply-4.raw").replace( + "{{ message_id }}", message_id + ) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + parent_communication = inbound_mail.parent_communication() + self.assertFalse(parent_communication) + + communication = self.new_communication(message_id=message_id) + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + parent_communication = inbound_mail.parent_communication() + self.assertEqual(parent_communication.name, communication.name) + + def test_find_parent_communication_from_header(self): + """Incase of header contains parent communication name + """ + communication = self.new_communication() + mail_content = self.get_test_mail(fname="reply-4.raw").replace( + "{{ message_id }}", f"<{communication.name}@{frappe.local.site}>" + ) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + parent_communication = inbound_mail.parent_communication() + self.assertEqual(parent_communication.name, communication.name) + + def test_reference_document(self): + # Create email queue record + todo = self.new_todo() + # communication = self.new_communication(reference_doctype='ToDo', reference_name=todo.name) + queue_record = self.new_email_queue(reference_doctype='ToDo', reference_name=todo.name) + mail_content = self.get_test_mail(fname="reply-4.raw").replace( + "{{ message_id }}", queue_record.message_id + ) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + reference_doc = inbound_mail.reference_document() + self.assertEqual(todo.name, reference_doc.name) + + def test_reference_document_by_record_name_in_subject(self): + # Create email queue record + todo = self.new_todo() + + mail_content = self.get_test_mail(fname="incoming-subject-placeholder.raw").replace( + "{{ subject }}", f"RE: (#{todo.name})" + ) + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + reference_doc = inbound_mail.reference_document() + self.assertEqual(todo.name, reference_doc.name) + + def test_reference_document_by_subject_match(self): + subject = "New todo" + todo = self.new_todo(sender='test_sender@example.com', description=subject) + + mail_content = self.get_test_mail(fname="incoming-subject-placeholder.raw").replace( + "{{ subject }}", f"RE: {subject}" + ) + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + reference_doc = inbound_mail.reference_document() + self.assertEqual(todo.name, reference_doc.name) + + def test_create_communication_from_mail(self): + # Create email queue record + mail_content = self.get_test_mail(fname="incoming-2.raw") + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + inbound_mail = InboundMail(mail_content, email_account, 12345, 1) + communication = inbound_mail.process() + self.assertTrue(communication.is_first) + self.assertTrue(communication._attachments) + def cleanup(sender=None): filters = {} if sender: @@ -207,4 +426,4 @@ def cleanup(sender=None): names = frappe.get_list("Communication", filters=filters, fields=["name"]) for name in names: frappe.delete_doc_if_exists("Communication", name.name) - frappe.delete_doc_if_exists("Communication Link", {"parent": name.name}) \ No newline at end of file + frappe.delete_doc_if_exists("Communication Link", {"parent": name.name}) diff --git a/frappe/email/doctype/email_account/test_mails/incoming-self-sent.raw b/frappe/email/doctype/email_account/test_mails/incoming-self-sent.raw new file mode 100644 index 0000000000..a16eecccd5 --- /dev/null +++ b/frappe/email/doctype/email_account/test_mails/incoming-self-sent.raw @@ -0,0 +1,91 @@ +Delivered-To: test_receiver@example.com +Received: by 10.96.153.227 with SMTP id vj3csp416144qdb; + Mon, 15 Sep 2014 03:35:07 -0700 (PDT) +X-Received: by 10.66.119.103 with SMTP id kt7mr36981968pab.95.1410777306321; + Mon, 15 Sep 2014 03:35:06 -0700 (PDT) +Return-Path: +Received: from mail-pa0-x230.google.com (mail-pa0-x230.google.com [2607:f8b0:400e:c03::230]) + by mx.google.com with ESMTPS id dg10si22178346pdb.115.2014.09.15.03.35.06 + for + (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); + Mon, 15 Sep 2014 03:35:06 -0700 (PDT) +Received-SPF: pass (google.com: domain of test@example.com designates 2607:f8b0:400e:c03::230 as permitted sender) client-ip=2607:f8b0:400e:c03::230; +Authentication-Results: mx.google.com; + spf=pass (google.com: domain of test@example.com designates 2607:f8b0:400e:c03::230 as permitted sender) smtp.mail=test@example.com; + dkim=pass header.i=@gmail.com; + dmarc=pass (p=NONE dis=NONE) header.from=gmail.com +Received: by mail-pa0-f48.google.com with SMTP id hz1so6118714pad.21 + for ; Mon, 15 Sep 2014 03:35:06 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=from:content-type:subject:message-id:date:to:mime-version; + bh=rwiLijtF3lfy9M6cP/7dv2Hm7NJuBwFZn1OFsN8Tlvs=; + b=x7U4Ny3Kz2ULRJ7a04NDBrBTVhP2ImIB9n3LVNGQDnDonPUM5Ro/wZcxPTVnBWZ2L1 + o1bGfP+lhBrvYUlHsd5r4FYC0Uvpad6hbzLr0DGUQgPTxW4cGKbtDEAq+BR2JWd9f803 + vdjSWdGk8w2dt2qbngTqIZkm5U2XWjICDOAYuPIseLUgCFwi9lLyOSARFB7mjAa2YL7Q + Nswk7mbWU1hbnHP6jaBb0m8QanTc7Up944HpNDRxIrB1ZHgKzYhXtx8nhnOx588ZGIAe + E6tyG8IwogR11vLkkrBhtMaOme9PohYx4F1CSTiwspmDCadEzJFGRe//lEXKmZHAYH6g + 90Zg== +X-Received: by 10.70.38.135 with SMTP id g7mr22078275pdk.100.1410777305744; + Mon, 15 Sep 2014 03:35:05 -0700 (PDT) +Return-Path: +Received: from [192.168.0.100] ([27.106.4.70]) + by mx.google.com with ESMTPSA id zr6sm11025126pbc.50.2014.09.15.03.35.02 + for + (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); + Mon, 15 Sep 2014 03:35:04 -0700 (PDT) +From: Rushabh Mehta +Content-Type: multipart/alternative; boundary="Apple-Mail=_57F71261-5C3A-43F6-918B-4438B96F61AA" +Subject: test mail 🦄🌈😎 +Message-Id: <9143999C-8456-4399-9CF1-4A2DA9DD7711@gmail.com> +Date: Mon, 15 Sep 2014 16:04:57 +0530 +To: Rushabh Mehta +Mime-Version: 1.0 (Mac OS X Mail 7.3 \(1878.6\)) +X-Mailer: Apple Mail (2.1878.6) + + +--Apple-Mail=_57F71261-5C3A-43F6-918B-4438B96F61AA +Content-Transfer-Encoding: 7bit +Content-Type: text/plain; + charset=us-ascii + +test mail + + + +@rushabh_mehta +https://erpnext.org + + +--Apple-Mail=_57F71261-5C3A-43F6-918B-4438B96F61AA +Content-Transfer-Encoding: quoted-printable +Content-Type: text/html; + charset=us-ascii + +test = +mail
+



@rushabh_mehta
+
+
= + +--Apple-Mail=_57F71261-5C3A-43F6-918B-4438B96F61AA-- diff --git a/frappe/email/doctype/email_account/test_mails/incoming-subject-placeholder.raw b/frappe/email/doctype/email_account/test_mails/incoming-subject-placeholder.raw new file mode 100644 index 0000000000..35ddf06b01 --- /dev/null +++ b/frappe/email/doctype/email_account/test_mails/incoming-subject-placeholder.raw @@ -0,0 +1,183 @@ +Return-path: +Envelope-to: test_receiver@example.com +Delivery-date: Wed, 27 Jan 2016 16:24:20 +0800 +Received: from 23-59-23-10.perm.iinet.net.au ([23.59.23.10]:62191 helo=DESKTOP7C66I2M) + by webcloud85.au.syrahost.com with esmtp (Exim 4.86) + (envelope-from ) + id 1aOLOj-002xFL-CP + for test_receiver@example.com; Wed, 27 Jan 2016 16:24:20 +0800 +From: +To: +References: +In-Reply-To: +Subject: RE: {{ subject }} +Date: Wed, 27 Jan 2016 16:24:09 +0800 +Message-ID: <000001d158dc$1b8363a0$528a2ae0$@example.com> +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_NextPart_000_0001_01D1591F.29A7DC20" +X-Mailer: Microsoft Outlook 14.0 +Thread-Index: AQJZfZxrgcB9KnMqoZ+S4Qq9hcoSeZ3+vGiQ +Content-Language: en-au + +This is a multipart message in MIME format. + +------=_NextPart_000_0001_01D1591F.29A7DC20 +Content-Type: multipart/alternative; + boundary="----=_NextPart_001_0002_01D1591F.29A7DC20" + + +------=_NextPart_001_0002_01D1591F.29A7DC20 +Content-Type: text/plain; + charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +Test purely for testing with the debugger has email attached + +=20 + +From: Notification [mailto:test_receiver@example.com]=20 +Sent: Wednesday, 27 January 2016 9:30 AM +To: test_receiver@example.com +Subject: Sales Invoice: SINV-12276 + +=20 + +test no 6 sent from bench to outlook to be replied to with messaging + + + + +------=_NextPart_001_0002_01D1591F.29A7DC20 +Content-Type: text/html; + charset="utf-8" +Content-Transfer-Encoding: quoted-printable + +hi there

Test purely for testing with the debugger has email = +attached

 

From:= + = +Notification [mailto:test_receiver@example.com]
Sent: Wednesday, 27 = +January 2016 9:30 AM
To: = +test_receiver@example.com
Subject: Sales Invoice: = +SINV-12276

 

test no 3 sent from bench to outlook to be replied to with = +messaging

fizz buzz

This email was sent to test_receiver@example.= +com and copied to SuperUser

Leave this conversation = +

hi

+------=_NextPart_001_0002_01D1591F.29A7DC20-- + +------=_NextPart_000_0001_01D1591F.29A7DC20 +Content-Type: message/rfc822 +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment + +Received: from 203-59-223-10.perm.iinet.net.au ([23.59.23.10]:49772 helo=DESKTOP7C66I2M) + by webcloud85.au.syrahost.com with esmtpsa (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) + (Exim 4.86) + (envelope-from ) + id 1aOEtO-003tI4-Kv + for test_receiver@example.com; Wed, 27 Jan 2016 09:27:30 +0800 +Return-Path: +From: "Microsoft Outlook" +To: +Subject: Microsoft Outlook Test Message +MIME-Version: 1.0 +Content-Type: text/plain; + charset="utf-8" +Content-Transfer-Encoding: quoted-printable +X-Mailer: Microsoft Outlook 14.0 +Thread-Index: AdFYoeN8x8wUI/+QSoCJkp33NKPVmw== + +This is an e-mail message sent automatically by Microsoft Outlook while = +testing the settings for your account. diff --git a/frappe/hooks.py b/frappe/hooks.py index 740aa94d9f..1c78d47755 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -202,9 +202,9 @@ scheduler_events = { ] }, "all": [ - # "frappe.email.queue.flush", - # "frappe.email.doctype.email_account.email_account.pull", - # "frappe.email.doctype.email_account.email_account.notify_unreplied", + "frappe.email.queue.flush", + "frappe.email.doctype.email_account.email_account.pull", + "frappe.email.doctype.email_account.email_account.notify_unreplied", "frappe.integrations.doctype.razorpay_settings.razorpay_settings.capture_payment", 'frappe.utils.global_search.sync_global_search', "frappe.monitor.flush", From 8294ee685d1b49165d041863d8ccd4a853d0fbc5 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 24 May 2021 12:42:18 +0530 Subject: [PATCH 145/868] fix: Tune button implemented on each block --- frappe/public/js/frappe/wiki_blocks/card.js | 36 +++++++++++++++++++ frappe/public/js/frappe/wiki_blocks/chart.js | 36 +++++++++++++++++++ frappe/public/js/frappe/wiki_blocks/header.js | 30 +++++++++++++--- .../public/js/frappe/wiki_blocks/paragraph.js | 30 +++++++++++++--- .../public/js/frappe/wiki_blocks/shortcut.js | 35 ++++++++++++++++++ frappe/public/js/frappe/wiki_blocks/spacer.js | 30 +++++++++++++--- frappe/public/scss/desk/wiki.scss | 12 +++++++ 7 files changed, 194 insertions(+), 15 deletions(-) diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index 64b685ca0a..81fdf0e08c 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -40,9 +40,45 @@ export default class Card { if (this.data && this.data.card_name) { this._make_cards(this.data.card_name); } + + if (!this.readOnly) { + let $widget_control = $(this.wrapper).find('.widget-control'); + this.add_custom_button( + frappe.utils.icon('dot-vertical', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50) + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control + ); + } + return this.wrapper; } + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { + if (!btn_type) btn_type = 'btn-secondary'; + let button = $( + `` + ); + button.click(event => { + event.stopPropagation(); + action && action(event); + }); + wrapper.prepend(button); + } + save(blockContent) { return { card_name: blockContent.getAttribute('card_name'), diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index 27aca1b29b..d6629c81bd 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -40,9 +40,45 @@ export default class Chart { if (this.data && this.data.chart_name) { this._make_charts(this.data.chart_name); } + + if (!this.readOnly) { + let $widget_control = $(this.wrapper).find('.widget-control'); + this.add_custom_button( + frappe.utils.icon('dot-vertical', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50) + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control + ); + } + return this.wrapper; } + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { + if (!btn_type) btn_type = 'btn-secondary'; + let button = $( + `` + ); + button.click(event => { + event.stopPropagation(); + action && action(event); + }); + wrapper.prepend(button); + } + save(blockContent) { return { chart_name: blockContent.getAttribute('chart_name'), diff --git a/frappe/public/js/frappe/wiki_blocks/header.js b/frappe/public/js/frappe/wiki_blocks/header.js index 574a455e44..ef6283a808 100644 --- a/frappe/public/js/frappe/wiki_blocks/header.js +++ b/frappe/public/js/frappe/wiki_blocks/header.js @@ -56,10 +56,21 @@ export default class Header { this.wrapper.classList.add('widget', 'header'); this.add_custom_button( - frappe.utils.icon('delete', 'xs'), - () => this.api.blocks.delete(), - "delete-header", - `${__('Delete')}`, + frappe.utils.icon('dot-vertical', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50) + }, + "tune-btn", + `${__('Tune')}`, null, $widget_control ); @@ -73,6 +84,15 @@ export default class Header { $widget_control ); + this.add_custom_button( + frappe.utils.icon('delete', 'xs'), + () => this.api.blocks.delete(), + "delete-header", + `${__('Delete')}`, + null, + $widget_control + ); + return this.wrapper; } return this._element; @@ -85,7 +105,7 @@ export default class Header { ); button.click(event => { event.stopPropagation(); - action && action(); + action && action(event); }); button.appendTo(wrapper); } diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index 558cf5a182..dac3dc9d1b 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -69,10 +69,21 @@ export default class Paragraph { this.wrapper.classList.add('widget'); this.add_custom_button( - frappe.utils.icon('delete', 'xs'), - () => this.api.blocks.delete(), - "delete-paragraph", - `${__('Delete')}`, + frappe.utils.icon('dot-vertical', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50) + }, + "tune-btn", + `${__('Tune')}`, null, $para_control ); @@ -86,6 +97,15 @@ export default class Paragraph { $para_control ); + this.add_custom_button( + frappe.utils.icon('delete', 'xs'), + () => this.api.blocks.delete(), + "delete-paragraph", + `${__('Delete')}`, + null, + $para_control + ); + return this.wrapper; } return this._element; @@ -98,7 +118,7 @@ export default class Paragraph { ); button.click(event => { event.stopPropagation(); - action && action(); + action && action(event); }); button.appendTo(wrapper); } diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index b4f59ec3e5..453113d5c6 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -39,9 +39,44 @@ export default class Shortcut { if (this.data && this.data.shortcut_name) { this._make_shortcuts(this.data.shortcut_name); } + + if (!this.readOnly) { + let $widget_control = $(this.wrapper).find('.widget-control'); + this.add_custom_button( + frappe.utils.icon('dot-vertical', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50) + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control + ); + } return this.wrapper; } + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { + if (!btn_type) btn_type = 'btn-secondary'; + let button = $( + `` + ); + button.click(event => { + event.stopPropagation(); + action && action(event); + }); + wrapper.prepend(button); + } + save(blockContent) { return { shortcut_name: blockContent.getAttribute('shortcut_name'), diff --git a/frappe/public/js/frappe/wiki_blocks/spacer.js b/frappe/public/js/frappe/wiki_blocks/spacer.js index a5a686df2f..8282db9455 100644 --- a/frappe/public/js/frappe/wiki_blocks/spacer.js +++ b/frappe/public/js/frappe/wiki_blocks/spacer.js @@ -40,10 +40,21 @@ export default class Spacer { let $widget_control = $spacer.find('.widget-control'); this.add_custom_button( - frappe.utils.icon('delete', 'xs'), - () => this.api.blocks.delete(), - "delete-spacer", - `${__('Delete')}`, + frappe.utils.icon('dot-vertical', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50) + }, + "tune-btn", + `${__('Tune')}`, null, $widget_control ); @@ -56,6 +67,15 @@ export default class Spacer { null, $widget_control ); + + this.add_custom_button( + frappe.utils.icon('delete', 'xs'), + () => this.api.blocks.delete(), + "delete-spacer", + `${__('Delete')}`, + null, + $widget_control + ); } return this.wrapper; } @@ -67,7 +87,7 @@ export default class Spacer { ); button.click(event => { event.stopPropagation(); - action && action(); + action && action(event); }); button.appendTo(wrapper); } diff --git a/frappe/public/scss/desk/wiki.scss b/frappe/public/scss/desk/wiki.scss index 1a5f9376f9..1db2c451a6 100644 --- a/frappe/public/scss/desk/wiki.scss +++ b/frappe/public/scss/desk/wiki.scss @@ -81,6 +81,18 @@ } } +.ce-settings { + width: fit-content; +} + +.tune-btn > * { + pointer-events: none; +} + +.ce-toolbar__settings-btn { + display: none; +} + .ce-header { padding: 0 !important; margin-bottom: 0 !important; From 1a0a095b34f33ddaba7615b9bddb1d4d8a1df30a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 24 May 2021 14:55:42 +0530 Subject: [PATCH 146/868] fix: Template path for document_page --- frappe/website/page_controllers/document_page.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/website/page_controllers/document_page.py b/frappe/website/page_controllers/document_page.py index 537b8ac658..c79e385a68 100644 --- a/frappe/website/page_controllers/document_page.py +++ b/frappe/website/page_controllers/document_page.py @@ -53,8 +53,8 @@ class DocumentPage(BaseTemplatePage): self.init_context() self.update_context() self.post_process_context() - - html = frappe.get_template(self.context.template_path).render(self.context) + template_path = self.context.template_path or self.context.template or '' + html = frappe.get_template(template_path).render(self.context) html = self.add_csrf_token(html) return build_response(self.path, html, self.http_status_code or 200, self.headers) From 363b646d02c4dae3fcc1ab5a1068797ed7277151 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 24 May 2021 16:44:04 +0530 Subject: [PATCH 147/868] fix: Miscellaneous changes --- frappe/public/js/frappe/views/wiki.js | 67 ++--- frappe/public/js/frappe/wiki_blocks/card.js | 4 +- frappe/public/js/frappe/wiki_blocks/chart.js | 4 +- frappe/public/js/frappe/wiki_blocks/header.js | 4 +- .../public/js/frappe/wiki_blocks/paragraph.js | 4 +- .../public/js/frappe/wiki_blocks/shortcut.js | 4 +- frappe/public/js/frappe/wiki_blocks/spacer.js | 4 +- frappe/public/scss/desk/wiki.scss | 229 +++++++++--------- 8 files changed, 160 insertions(+), 160 deletions(-) diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index cbc6eacf33..22036a8d2d 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -15,6 +15,37 @@ frappe.views.Wiki = class Wiki { this.new_page = null; this.prepare_container(); this.setup_wiki_pages(); + + this.tools = { + header: { + class: frappe.wiki_block.blocks['header'], + inlineToolbar: true + }, + paragraph: { + class: frappe.wiki_block.blocks['paragraph'], + inlineToolbar: true + }, + chart: { + class: frappe.wiki_block.blocks['chart'], + config: { + page_data: this.page_data || [] + } + }, + card: { + class: frappe.wiki_block.blocks['card'], + config: { + page_data: this.page_data || [] + } + }, + shortcut: { + class: frappe.wiki_block.blocks['shortcut'], + config: { + page_data: this.page_data || [] + } + }, + spacer: frappe.wiki_block.blocks['spacer'], + spacingTune: frappe.wiki_block.tunes['spacing_tune'], + }; } prepare_container() { @@ -99,6 +130,11 @@ frappe.views.Wiki = class Wiki { }; const make_sidebar_child_item = item => { + + if (frappe.router.slug(item.name) == this.get_page_to_show() || item.name == this.new_page) { + child_item_section.classList.toggle("hidden"); + } + let $child_item = get_child_item(item); let sidebar_control = $child_item.find('.sidebar-item-control'); this.add_sidebar_actions(item, sidebar_control); @@ -146,36 +182,6 @@ frappe.views.Wiki = class Wiki { this.get_content(page).then(() => { this.get_data(page).then(() => { if (this.content) { - this.tools = { - header: { - class: frappe.wiki_block.blocks['header'], - inlineToolbar: true - }, - paragraph: { - class: frappe.wiki_block.blocks['paragraph'], - inlineToolbar: true - }, - chart: { - class: frappe.wiki_block.blocks['chart'], - config: { - page_data: this.page_data || [] - } - }, - card: { - class: frappe.wiki_block.blocks['card'], - config: { - page_data: this.page_data || [] - } - }, - shortcut: { - class: frappe.wiki_block.blocks['shortcut'], - config: { - page_data: this.page_data || [] - } - }, - spacer: frappe.wiki_block.blocks['spacer'], - spacingTune: frappe.wiki_block.tunes['spacing_tune'], - }; if (this.editor) { this.editor.isReady.then(() => { this.editor.configuration.tools.chart.config.page_data = this.page_data; @@ -258,6 +264,7 @@ frappe.views.Wiki = class Wiki { } setup_actions() { + if (!this.isReadOnly) return; this.page.clear_inner_toolbar(); this.page.set_secondary_action( __("Customize"), diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index 81fdf0e08c..820056a6ab 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -44,7 +44,7 @@ export default class Card { if (!this.readOnly) { let $widget_control = $(this.wrapper).find('.widget-control'); this.add_custom_button( - frappe.utils.icon('dot-vertical', 'xs'), + frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; !$('.ce-settings.ce-settings--opened').length && @@ -55,7 +55,7 @@ export default class Card { top: position.top + 25, left: position.left - 77 }); - }, 50) + }, 50); }, "tune-btn", `${__('Tune')}`, diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index d6629c81bd..c7f92222c0 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -44,7 +44,7 @@ export default class Chart { if (!this.readOnly) { let $widget_control = $(this.wrapper).find('.widget-control'); this.add_custom_button( - frappe.utils.icon('dot-vertical', 'xs'), + frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; !$('.ce-settings.ce-settings--opened').length && @@ -55,7 +55,7 @@ export default class Chart { top: position.top + 25, left: position.left - 77 }); - }, 50) + }, 50); }, "tune-btn", `${__('Tune')}`, diff --git a/frappe/public/js/frappe/wiki_blocks/header.js b/frappe/public/js/frappe/wiki_blocks/header.js index ef6283a808..727f495a42 100644 --- a/frappe/public/js/frappe/wiki_blocks/header.js +++ b/frappe/public/js/frappe/wiki_blocks/header.js @@ -56,7 +56,7 @@ export default class Header { this.wrapper.classList.add('widget', 'header'); this.add_custom_button( - frappe.utils.icon('dot-vertical', 'xs'), + frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; !$('.ce-settings.ce-settings--opened').length && @@ -67,7 +67,7 @@ export default class Header { top: position.top + 25, left: position.left - 77 }); - }, 50) + }, 50); }, "tune-btn", `${__('Tune')}`, diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index dac3dc9d1b..cc05f3edbc 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -69,7 +69,7 @@ export default class Paragraph { this.wrapper.classList.add('widget'); this.add_custom_button( - frappe.utils.icon('dot-vertical', 'xs'), + frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; !$('.ce-settings.ce-settings--opened').length && @@ -80,7 +80,7 @@ export default class Paragraph { top: position.top + 25, left: position.left - 77 }); - }, 50) + }, 50); }, "tune-btn", `${__('Tune')}`, diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index 453113d5c6..c6d01a8800 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -43,7 +43,7 @@ export default class Shortcut { if (!this.readOnly) { let $widget_control = $(this.wrapper).find('.widget-control'); this.add_custom_button( - frappe.utils.icon('dot-vertical', 'xs'), + frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; !$('.ce-settings.ce-settings--opened').length && @@ -54,7 +54,7 @@ export default class Shortcut { top: position.top + 25, left: position.left - 77 }); - }, 50) + }, 50); }, "tune-btn", `${__('Tune')}`, diff --git a/frappe/public/js/frappe/wiki_blocks/spacer.js b/frappe/public/js/frappe/wiki_blocks/spacer.js index 8282db9455..5f26f06ca4 100644 --- a/frappe/public/js/frappe/wiki_blocks/spacer.js +++ b/frappe/public/js/frappe/wiki_blocks/spacer.js @@ -40,7 +40,7 @@ export default class Spacer { let $widget_control = $spacer.find('.widget-control'); this.add_custom_button( - frappe.utils.icon('dot-vertical', 'xs'), + frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; !$('.ce-settings.ce-settings--opened').length && @@ -51,7 +51,7 @@ export default class Spacer { top: position.top + 25, left: position.left - 77 }); - }, 50) + }, 50); }, "tune-btn", `${__('Tune')}`, diff --git a/frappe/public/scss/desk/wiki.scss b/frappe/public/scss/desk/wiki.scss index 1db2c451a6..cb911611d8 100644 --- a/frappe/public/scss/desk/wiki.scss +++ b/frappe/public/scss/desk/wiki.scss @@ -36,6 +36,16 @@ margin-right: 0; } } + + .sidebar-item-label { + flex: 1; + } + + .item-anchor { + display: flex; + overflow: hidden; + flex: 1; + } } .sidebar-child-item-container { @@ -46,16 +56,6 @@ } } - .sidebar-item-label { - flex: 1; - } - - .item-anchor { - display: flex; - overflow: hidden; - flex: 1; - } - .standard-sidebar-section.show-control { .desk-sidebar-item.standard-sidebar-item { &:hover { @@ -81,65 +81,86 @@ } } -.ce-settings { - width: fit-content; -} - -.tune-btn > * { - pointer-events: none; -} - -.ce-toolbar__settings-btn { - display: none; -} - -.ce-header { - padding: 0 !important; - margin-bottom: 0 !important; - flex: 1; -} - -.widget{ - &.header { - display: flex; - justify-content: center; - flex: 1; - padding-left: 15px !important; - padding-right: 15px !important; - min-height: 50px; - box-shadow: none; - background-color: var(--control-bg); - color: var(--text-muted); - } - - &:focus { - outline: none; - } - - &.new-widget { - align-items: inherit; - } - - .paragraph-control { - display: flex; - flex-direction: row-reverse; - position: absolute; - right: 20px; - gap: 5px; - background-color: var(--card-bg); - padding-left: 5px; - - .drag-handle { - cursor: all-scroll; - cursor: -webkit-grabbing; - } - } - -} - .codex-editor { min-height: 630px; + .codex-editor__redactor{ + display: flex; + flex-wrap: wrap; + flex-direction: row; + margin: 0px -7px; + padding-bottom: 20px !important; + + .ce-block{ + width: 100%; + padding-left: 0; + padding-right: 0; + + &.ce-block--selected { + .ce-block__content { + background-color: inherit; + } + } + + .ce-block__content { + max-width: 100%; + height: 100%; + padding: 7px; + + &> div { + height: 100%; + } + + .tune-btn > * { + pointer-events: none; + } + + .ce-header { + padding: 0 !important; + margin-bottom: 0 !important; + flex: 1; + } + + .widget{ + &.header { + display: flex; + justify-content: center; + flex: 1; + padding-left: 15px !important; + padding-right: 15px !important; + min-height: 50px; + box-shadow: none; + background-color: var(--control-bg); + color: var(--text-muted); + } + + &:focus { + outline: none; + } + + &.new-widget { + align-items: inherit; + } + + .paragraph-control { + display: flex; + flex-direction: row-reverse; + position: absolute; + right: 20px; + gap: 5px; + background-color: var(--card-bg); + padding-left: 5px; + + .drag-handle { + cursor: all-scroll; + cursor: -webkit-grabbing; + } + } + } + } + } + } + svg { fill: none; } @@ -153,6 +174,29 @@ stroke: none; width: fit-content; } + + .ce-settings { + width: fit-content; + + .cdx-settings-button.disabled{ + pointer-events: none; + opacity: .5 + } + .cdx-settings-sidebar{ + position: absolute; + right: 100%; + top:0; + background: #fff; + width: 108px; + height: 145px; + box-shadow: 0 3px 15px -3px rgba(13,20,33,.13); + border-radius: 0 4px 4px 0;z-index: 0; + } + } + + .ce-toolbar__settings-btn { + display: none; + } } .ce-inline-tool, .ce-inline-toolbar__dropdown { @@ -160,6 +204,7 @@ fill: currentColor; } } + @media (min-width: 1199px) { .ce-toolbar__content { max-width: 930px; @@ -190,57 +235,5 @@ max-width: 100%; } } - - div[card_name] { - height: inherit; - } - -} -.codex-editor__redactor{ - display: flex; - flex-wrap: wrap; - flex-direction: row; - margin: 0px -7px; -} -.ce-block{ - width: 100%; - padding-left: 0; - padding-right: 0; -} -.cdx-settings-input{ - border: 1px solid rgba(201,201,204,.48); - -webkit-box-shadow: inset 0 1px 2px 0 rgba(35,44,72,.06); - box-shadow: inset 0 1px 2px 0 rgba(35,44,72,.06); - border-radius: 3px;padding: 3px 8px;outline: none; - width: 100%; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} -.cdx-small{ - font-size: .6rem -} -.ce-block__content { - max-width: 100%; - height: 100%; - padding: 7px; - - &> div { - height: 100%; - } -} - -.cdx-settings-button.disabled{ - pointer-events: none; - opacity: .5 -} -.cdx-settings-sidebar{ - position: absolute; - right: 100%; - top:0; - background: #fff; - width: 108px; - height: 145px; - box-shadow: 0 3px 15px -3px rgba(13,20,33,.13); - border-radius: 0 4px 4px 0;z-index: 0; } \ No newline at end of file From 15f5b697d312c4ee6174fd4e40828c41d3eb581c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 24 May 2021 19:52:31 +0530 Subject: [PATCH 148/868] fix: Website template path --- frappe/website/page_controllers/base_template_page.py | 7 +++++-- frappe/website/page_controllers/document_page.py | 11 ++++++----- frappe/website/website_generator.py | 2 ++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py index af7fc43293..4d282dab9d 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_controllers/base_template_page.py @@ -5,6 +5,10 @@ from frappe.website.website_components.metatags import MetaTags class BaseTemplatePage(WebPage): + def __init__(self, path, http_status_code): + super().__init__(path=path, http_status_code=http_status_code) + self.template_path = '' + def init_context(self): self.context = frappe._dict() self.context.update(get_website_settings()) @@ -35,8 +39,7 @@ class BaseTemplatePage(WebPage): self.context.canonical = frappe.utils.get_url(frappe.utils.escape_html(self.path)) # context sends us a new template path - if self.context.template: - self.template_path = self.context.template + self.template_path = self.context.template or '' def set_base_template_if_missing(self): if not self.context.base_template_path: diff --git a/frappe/website/page_controllers/document_page.py b/frappe/website/page_controllers/document_page.py index c79e385a68..6ab384e77d 100644 --- a/frappe/website/page_controllers/document_page.py +++ b/frappe/website/page_controllers/document_page.py @@ -53,8 +53,7 @@ class DocumentPage(BaseTemplatePage): self.init_context() self.update_context() self.post_process_context() - template_path = self.context.template_path or self.context.template or '' - html = frappe.get_template(template_path).render(self.context) + html = frappe.get_template(self.template_path).render(self.context) html = self.add_csrf_token(html) return build_response(self.path, html, self.http_status_code or 200, self.headers) @@ -62,10 +61,12 @@ class DocumentPage(BaseTemplatePage): def update_context(self): self.context.doc = self.doc self.context.update(self.context.doc.as_dict()) - self.context.update(self.context.doc.get_website_properties()) + self.context.update(self.context.doc.get_page_info()) - if not self.context.template_path: - self.context.template_path = self.context.doc.meta.get_web_template() + self.template_path = self.context.template or self.template_path + + if not self.template_path: + self.template_path = self.context.doc.meta.get_web_template() if hasattr(self.doc, "get_context"): ret = self.doc.get_context(self.context) diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index fc08abeed9..f2638fd86d 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -129,6 +129,8 @@ class WebsiteGenerator(Document): if not route.page_title: route.page_title = self.get(self.get_title_field()) + route.title = route.page_title + return route def send_indexing_request(self, operation_type='URL_UPDATED'): From 63ce0c51361422c3386f6a62a3e3334560f5a71d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 24 May 2021 21:53:09 +0530 Subject: [PATCH 149/868] fix: Fallback to template_path if template is not set --- frappe/website/page_controllers/base_template_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py index 4d282dab9d..012f9fccc9 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_controllers/base_template_page.py @@ -39,7 +39,7 @@ class BaseTemplatePage(WebPage): self.context.canonical = frappe.utils.get_url(frappe.utils.escape_html(self.path)) # context sends us a new template path - self.template_path = self.context.template or '' + self.template_path = self.context.template or self.template_path def set_base_template_if_missing(self): if not self.context.base_template_path: From cbd00179cb16e0f08b8283d6f1d0f0e815cefef1 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 24 May 2021 22:31:23 +0530 Subject: [PATCH 150/868] fix: Move set_missing_values to base_template_page - Since it is common for all inherited pages from base_template_page --- .../page_controllers/base_template_page.py | 30 ++++++++++++------- .../website/page_controllers/template_page.py | 11 +------ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py index 012f9fccc9..f06869fd5f 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_controllers/base_template_page.py @@ -28,18 +28,10 @@ class BaseTemplatePage(WebPage): self.set_base_template_if_missing() self.set_title_with_prefix() self.update_website_context() - - # set using frappe.respond_as_web_page - if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): - self.context.update(frappe.local.response.context) - - # to be able to inspect the context dict - # Use the macro "inspect" from macros.html - self.context._context_dict = self.context - self.context.canonical = frappe.utils.get_url(frappe.utils.escape_html(self.path)) - # context sends us a new template path self.template_path = self.context.template or self.template_path + self.context._context_dict = self.context + self.set_missing_values() def set_base_template_if_missing(self): if not self.context.base_template_path: @@ -51,6 +43,24 @@ class BaseTemplatePage(WebPage): and not self.context.title.startswith(self.context.title_prefix)): self.context.title = '{0} - {1}'.format(self.context.title_prefix, self.context.title) + def set_missing_values(self): + # set using frappe.respond_as_web_page + if hasattr(frappe.local, 'response') and frappe.local.response.get('context'): + self.context.update(frappe.local.response.context) + + # to be able to inspect the context dict + # Use the macro "inspect" from macros.html + self.context.canonical = frappe.utils.get_url(frappe.utils.escape_html(self.path)) + + if "url_prefix" not in self.context: + self.context.url_prefix = "" + + if self.context.url_prefix and self.context.url_prefix[-1]!='/': + self.context.url_prefix += '/' + + self.context.path = self.path + self.context.pathname = frappe.local.path if hasattr(frappe, 'local') else self.path + def update_website_context(self): # apply context from hooks update_website_context = frappe.get_hooks('update_website_context') diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index 635b8a56fe..cd30fa02c8 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -65,7 +65,6 @@ class TemplatePage(BaseTemplatePage): def post_process_context(self): self.set_user_info() self.add_sidebar_and_breadcrumbs() - self.set_missing_values() super(TemplatePage, self).post_process_context() def add_sidebar_and_breadcrumbs(self): @@ -228,15 +227,7 @@ class TemplatePage(BaseTemplatePage): self.template_path = 'www/{path}.html'.format(path=path) def set_missing_values(self): - if "url_prefix" not in self.context: - self.context.url_prefix = "" - - if self.context.url_prefix and self.context.url_prefix[-1]!='/': - self.context.url_prefix += '/' - - self.context.path = self.path - self.context.pathname = frappe.local.path if hasattr(frappe, 'local') else self.path - + super().set_missing_values() # for backward compatibility self.context.docs_base_url = '/docs' From 70a8bd5945da8db42838cc61efe8312237d9e91d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 08:21:06 +0530 Subject: [PATCH 151/868] refactor: Rename validate function to can_render --- frappe/website/page_controllers/document_page.py | 2 +- frappe/website/page_controllers/error_page.py | 2 +- frappe/website/page_controllers/list_page.py | 2 +- frappe/website/page_controllers/not_found_page.py | 2 +- frappe/website/page_controllers/not_permitted_page.py | 2 +- frappe/website/page_controllers/print_page.py | 2 +- frappe/website/page_controllers/redirect_page.py | 2 +- frappe/website/page_controllers/static_page.py | 2 +- frappe/website/page_controllers/template_page.py | 2 +- frappe/website/page_controllers/web_form.py | 2 +- frappe/website/page_controllers/web_page.py | 2 +- frappe/website/path_resolver.py | 5 ++--- 12 files changed, 13 insertions(+), 14 deletions(-) diff --git a/frappe/website/page_controllers/document_page.py b/frappe/website/page_controllers/document_page.py index 6ab384e77d..1a42b5debb 100644 --- a/frappe/website/page_controllers/document_page.py +++ b/frappe/website/page_controllers/document_page.py @@ -7,7 +7,7 @@ from frappe.website.router import (get_doctypes_with_web_view, class DocumentPage(BaseTemplatePage): - def validate(self): + def can_render(self): ''' Find a document with matching `route` from all doctypes with `has_web_view`=1 ''' diff --git a/frappe/website/page_controllers/error_page.py b/frappe/website/page_controllers/error_page.py index 554949684f..52903d076b 100644 --- a/frappe/website/page_controllers/error_page.py +++ b/frappe/website/page_controllers/error_page.py @@ -6,5 +6,5 @@ class ErrorPage(TemplatePage): super().__init__(path=path, http_status_code=http_status_code) self.http_status_code = getattr(exception, 'http_status_code', None) or http_status_code or 500 - def validate(self): + def can_render(self): return True diff --git a/frappe/website/page_controllers/list_page.py b/frappe/website/page_controllers/list_page.py index cc6f150dd2..e3b92a2771 100644 --- a/frappe/website/page_controllers/list_page.py +++ b/frappe/website/page_controllers/list_page.py @@ -2,7 +2,7 @@ import frappe from frappe.website.page_controllers.template_page import TemplatePage class ListPage(TemplatePage): - def validate(self): + def can_render(self): return frappe.db.exists('DocType', self.path, True) def render(self): diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_controllers/not_found_page.py index 13c6358512..1f687ddb98 100644 --- a/frappe/website/page_controllers/not_found_page.py +++ b/frappe/website/page_controllers/not_found_page.py @@ -15,7 +15,7 @@ class NotFoundPage(TemplatePage): http_status_code = 404 super().__init__(path=path, http_status_code=http_status_code) - def validate(self): + def can_render(self): return True def render(self): diff --git a/frappe/website/page_controllers/not_permitted_page.py b/frappe/website/page_controllers/not_permitted_page.py index 3ed732d80b..75a8b756d8 100644 --- a/frappe/website/page_controllers/not_permitted_page.py +++ b/frappe/website/page_controllers/not_permitted_page.py @@ -9,7 +9,7 @@ class NotPermittedPage(TemplatePage): super().__init__(path=path, http_status_code=http_status_code) self.http_status_code = 403 - def validate(self): + def can_render(self): return True def render(self): diff --git a/frappe/website/page_controllers/print_page.py b/frappe/website/page_controllers/print_page.py index 574f335f5d..790ee75585 100644 --- a/frappe/website/page_controllers/print_page.py +++ b/frappe/website/page_controllers/print_page.py @@ -6,7 +6,7 @@ class PrintPage(TemplatePage): default path returns a printable object (based on permission) /Quotation/Q-0001 ''' - def validate(self): + def can_render(self): parts = self.path.split('/', 1) if len(parts)==2: if (frappe.db.exists('DocType', parts[0], True) diff --git a/frappe/website/page_controllers/redirect_page.py b/frappe/website/page_controllers/redirect_page.py index f3a0ba6e7f..0bfa8897a3 100644 --- a/frappe/website/page_controllers/redirect_page.py +++ b/frappe/website/page_controllers/redirect_page.py @@ -6,7 +6,7 @@ class RedirectPage(object): self.path = path self.http_status_code = http_status_code - def validate(self): + def can_render(self): return True def render(self): diff --git a/frappe/website/page_controllers/static_page.py b/frappe/website/page_controllers/static_page.py index b292a62922..0c75d6feb3 100644 --- a/frappe/website/page_controllers/static_page.py +++ b/frappe/website/page_controllers/static_page.py @@ -23,7 +23,7 @@ class StaticPage(WebPage): if os.path.isfile(file_path): self.file_path = file_path - def validate(self): + def can_render(self): return self.is_valid_file_path() and self.file_path def is_valid_file_path(self): diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index cd30fa02c8..c9797b88c9 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -36,7 +36,7 @@ class TemplatePage(BaseTemplatePage): self.basepath = os.path.dirname(file_path) return - def validate(self): + def can_render(self): return hasattr(self, 'template_path') and bool(self.template_path) def get_index_path_options(self, search_path): diff --git a/frappe/website/page_controllers/web_form.py b/frappe/website/page_controllers/web_form.py index d7ab02d880..c1afaafbe5 100644 --- a/frappe/website/page_controllers/web_form.py +++ b/frappe/website/page_controllers/web_form.py @@ -2,5 +2,5 @@ from frappe.website.page_controllers.web_page import WebPage import frappe class WebFormPage(WebPage): - def validate(self): + def can_render(self): return bool(frappe.get_all("Web Form", filters={'route': self.path})) diff --git a/frappe/website/page_controllers/web_page.py b/frappe/website/page_controllers/web_page.py index 4d9e642b4b..0407afe532 100644 --- a/frappe/website/page_controllers/web_page.py +++ b/frappe/website/page_controllers/web_page.py @@ -13,7 +13,7 @@ class WebPage(object): if self.validate(): return self.render() - def validate(self): + def can_render(self): pass def render(self): diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index 39edf0d9a8..854948740c 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -32,15 +32,14 @@ class PathResolver(): try: resolve_redirect(self.path, request.query_string) except frappe.Redirect: - return self.path, RedirectPage(self.path) + return frappe.flags.redirect_location, RedirectPage(self.path) endpoint = resolve_path(self.path) renderers = (StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage) for renderer in renderers: renderer_instance = renderer(endpoint, 200) - can_render = renderer_instance.validate() - if can_render: + if renderer_instance.can_render(): return endpoint, renderer_instance return endpoint, NotFoundPage(endpoint) From d0915a709bc9984bf205be66193bfd767c598944 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 08:22:45 +0530 Subject: [PATCH 152/868] fix: Make http_status_code non mandatory --- frappe/website/page_controllers/base_template_page.py | 2 +- frappe/website/serve.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_controllers/base_template_page.py index f06869fd5f..d7770ccd93 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_controllers/base_template_page.py @@ -5,7 +5,7 @@ from frappe.website.website_components.metatags import MetaTags class BaseTemplatePage(WebPage): - def __init__(self, path, http_status_code): + def __init__(self, path, http_status_code=None): super().__init__(path=path, http_status_code=http_status_code) self.template_path = '' diff --git a/frappe/website/serve.py b/frappe/website/serve.py index 95a49cef1a..a761f479f3 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -14,8 +14,7 @@ def get_response(path=None, http_status_code=200): try: path_resolver = PathResolver(path) endpoint, renderer_instance = path_resolver.resolve() - if renderer_instance: - response = renderer_instance.render() + response = renderer_instance.render() except frappe.Redirect: return RedirectPage(endpoint or path, http_status_code).render() except frappe.PermissionError as e: From bb68dd7323974771fec691c212a954e4f2683999 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 09:24:32 +0530 Subject: [PATCH 153/868] fix: Add comment properties back with deprecation warning --- .../website/page_controllers/template_page.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_controllers/template_page.py index c9797b88c9..69e9cceb9f 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_controllers/template_page.py @@ -1,5 +1,6 @@ import io import os +import click import frappe from frappe.website.page_controllers.base_template_page import BaseTemplatePage @@ -11,6 +12,17 @@ from frappe.website.utils import (extract_comment_tag, extract_title, WEBPAGE_PY_MODULE_PROPERTIES = ("base_template_path", "template", "no_cache", "sitemap", "condition_field") +COMMENT_PROPERTY_KEY_VALUE_MAP = { + "no-breadcrumbs": ("no_breadcrumbs", 1), + "show-sidebar": ("show_sidebar", 1), + "add-breadcrumbs": ("add_breadcrumbs", 1), + "no-header": ("no_header", 1), + "add-next-prev-links": ("add_next_prev_links", 1), + "no-cache": ("no_cache", 1), + "no-sitemap": ("sitemap", 0), + "sitemap": ("sitemap", 1) +} + class TemplatePage(BaseTemplatePage): def __init__(self, path, http_status_code=None): super().__init__(path=path, http_status_code=http_status_code) @@ -147,6 +159,15 @@ class TemplatePage(BaseTemplatePage): self.source = '''{{% extends "{0}" %}} {{% block page_content %}}{1}{{% endblock %}}'''.format(context.base_template, self.source) + self.set_properties_via_comments() + + def set_properties_via_comments(self): + for comment, (context_key, value) in COMMENT_PROPERTY_KEY_VALUE_MAP.items(): + comment_tag = f"" + if comment_tag in self.source: + self.context[context_key] = value + click.echo(f'⚠️ DEPRECATION WARNING: {comment_tag} will be deprecated on 2021-12-31.') + def run_pymodule_method(self, method): if hasattr(self.pymodule, method): try: From 8317e00712210a802e363c96d3f446f084ddb061 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 09:27:26 +0530 Subject: [PATCH 154/868] refactor: Rename page_controllers folder to page_renderers --- .../base_template_page.py | 2 +- .../document_page.py | 2 +- .../error_page.py | 2 +- .../list_page.py | 2 +- .../not_found_page.py | 2 +- .../not_permitted_page.py | 2 +- .../print_page.py | 2 +- .../redirect_page.py | 0 .../static_page.py | 2 +- .../template_page.py | 2 +- .../web_form.py | 2 +- .../web_page.py | 0 frappe/website/path_resolver.py | 16 ++++++++-------- frappe/website/serve.py | 6 +++--- 14 files changed, 21 insertions(+), 21 deletions(-) rename frappe/website/{page_controllers => page_renderers}/base_template_page.py (97%) rename frappe/website/{page_controllers => page_renderers}/document_page.py (96%) rename frappe/website/{page_controllers => page_renderers}/error_page.py (81%) rename frappe/website/{page_controllers => page_renderers}/list_page.py (77%) rename frappe/website/{page_controllers => page_renderers}/not_found_page.py (93%) rename frappe/website/{page_controllers => page_renderers}/not_permitted_page.py (89%) rename frappe/website/{page_controllers => page_renderers}/print_page.py (88%) rename frappe/website/{page_controllers => page_renderers}/redirect_page.py (100%) rename frappe/website/{page_controllers => page_renderers}/static_page.py (95%) rename frappe/website/{page_controllers => page_renderers}/template_page.py (99%) rename frappe/website/{page_controllers => page_renderers}/web_form.py (69%) rename frappe/website/{page_controllers => page_renderers}/web_page.py (100%) diff --git a/frappe/website/page_controllers/base_template_page.py b/frappe/website/page_renderers/base_template_page.py similarity index 97% rename from frappe/website/page_controllers/base_template_page.py rename to frappe/website/page_renderers/base_template_page.py index d7770ccd93..8405270a57 100644 --- a/frappe/website/page_controllers/base_template_page.py +++ b/frappe/website/page_renderers/base_template_page.py @@ -1,6 +1,6 @@ import frappe from frappe.website.doctype.website_settings.website_settings import get_website_settings -from frappe.website.page_controllers.web_page import WebPage +from frappe.website.page_renderers.web_page import WebPage from frappe.website.website_components.metatags import MetaTags diff --git a/frappe/website/page_controllers/document_page.py b/frappe/website/page_renderers/document_page.py similarity index 96% rename from frappe/website/page_controllers/document_page.py rename to frappe/website/page_renderers/document_page.py index 1a42b5debb..34dc42e203 100644 --- a/frappe/website/page_controllers/document_page.py +++ b/frappe/website/page_renderers/document_page.py @@ -1,6 +1,6 @@ import frappe from frappe.model.document import get_controller -from frappe.website.page_controllers.base_template_page import BaseTemplatePage +from frappe.website.page_renderers.base_template_page import BaseTemplatePage from frappe.website.render import build_response from frappe.website.router import (get_doctypes_with_web_view, get_page_info_from_web_page_with_dynamic_routes) diff --git a/frappe/website/page_controllers/error_page.py b/frappe/website/page_renderers/error_page.py similarity index 81% rename from frappe/website/page_controllers/error_page.py rename to frappe/website/page_renderers/error_page.py index 52903d076b..3501c77765 100644 --- a/frappe/website/page_controllers/error_page.py +++ b/frappe/website/page_renderers/error_page.py @@ -1,4 +1,4 @@ -from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_renderers.template_page import TemplatePage class ErrorPage(TemplatePage): def __init__(self, path=None, http_status_code=None, exception=None): diff --git a/frappe/website/page_controllers/list_page.py b/frappe/website/page_renderers/list_page.py similarity index 77% rename from frappe/website/page_controllers/list_page.py rename to frappe/website/page_renderers/list_page.py index e3b92a2771..61c781ea14 100644 --- a/frappe/website/page_controllers/list_page.py +++ b/frappe/website/page_renderers/list_page.py @@ -1,5 +1,5 @@ import frappe -from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_renderers.template_page import TemplatePage class ListPage(TemplatePage): def can_render(self): diff --git a/frappe/website/page_controllers/not_found_page.py b/frappe/website/page_renderers/not_found_page.py similarity index 93% rename from frappe/website/page_controllers/not_found_page.py rename to frappe/website/page_renderers/not_found_page.py index 1f687ddb98..af510fecfc 100644 --- a/frappe/website/page_controllers/not_found_page.py +++ b/frappe/website/page_renderers/not_found_page.py @@ -2,7 +2,7 @@ import os from urllib.parse import urlparse import frappe -from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_renderers.template_page import TemplatePage from frappe.website.utils import can_cache HOMEPAGE_PATHS = ('/', '/index', 'index') diff --git a/frappe/website/page_controllers/not_permitted_page.py b/frappe/website/page_renderers/not_permitted_page.py similarity index 89% rename from frappe/website/page_controllers/not_permitted_page.py rename to frappe/website/page_renderers/not_permitted_page.py index 75a8b756d8..e69299f5c5 100644 --- a/frappe/website/page_controllers/not_permitted_page.py +++ b/frappe/website/page_renderers/not_permitted_page.py @@ -1,6 +1,6 @@ import frappe from frappe import _ -from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_renderers.template_page import TemplatePage from frappe.utils import cstr class NotPermittedPage(TemplatePage): diff --git a/frappe/website/page_controllers/print_page.py b/frappe/website/page_renderers/print_page.py similarity index 88% rename from frappe/website/page_controllers/print_page.py rename to frappe/website/page_renderers/print_page.py index 790ee75585..05d4026e2b 100644 --- a/frappe/website/page_controllers/print_page.py +++ b/frappe/website/page_renderers/print_page.py @@ -1,5 +1,5 @@ import frappe -from frappe.website.page_controllers.template_page import TemplatePage +from frappe.website.page_renderers.template_page import TemplatePage class PrintPage(TemplatePage): ''' diff --git a/frappe/website/page_controllers/redirect_page.py b/frappe/website/page_renderers/redirect_page.py similarity index 100% rename from frappe/website/page_controllers/redirect_page.py rename to frappe/website/page_renderers/redirect_page.py diff --git a/frappe/website/page_controllers/static_page.py b/frappe/website/page_renderers/static_page.py similarity index 95% rename from frappe/website/page_controllers/static_page.py rename to frappe/website/page_renderers/static_page.py index 0c75d6feb3..fc3edbe216 100644 --- a/frappe/website/page_controllers/static_page.py +++ b/frappe/website/page_renderers/static_page.py @@ -5,7 +5,7 @@ from werkzeug.wrappers import Response from werkzeug.wsgi import wrap_file import frappe -from frappe.website.page_controllers.web_page import WebPage +from frappe.website.page_renderers.web_page import WebPage UNSUPPORTED_STATIC_PAGE_TYPES = ('html', 'md', 'js', 'xml', 'css', 'txt', 'py', 'json') diff --git a/frappe/website/page_controllers/template_page.py b/frappe/website/page_renderers/template_page.py similarity index 99% rename from frappe/website/page_controllers/template_page.py rename to frappe/website/page_renderers/template_page.py index 69e9cceb9f..467d74b283 100644 --- a/frappe/website/page_controllers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -3,7 +3,7 @@ import os import click import frappe -from frappe.website.page_controllers.base_template_page import BaseTemplatePage +from frappe.website.page_renderers.base_template_page import BaseTemplatePage from frappe.website.utils import get_sidebar_items from frappe.website.render import build_response from frappe.website.router import get_base_template diff --git a/frappe/website/page_controllers/web_form.py b/frappe/website/page_renderers/web_form.py similarity index 69% rename from frappe/website/page_controllers/web_form.py rename to frappe/website/page_renderers/web_form.py index c1afaafbe5..094ae78d71 100644 --- a/frappe/website/page_controllers/web_form.py +++ b/frappe/website/page_renderers/web_form.py @@ -1,4 +1,4 @@ -from frappe.website.page_controllers.web_page import WebPage +from frappe.website.page_renderers.web_page import WebPage import frappe class WebFormPage(WebPage): diff --git a/frappe/website/page_controllers/web_page.py b/frappe/website/page_renderers/web_page.py similarity index 100% rename from frappe/website/page_controllers/web_page.py rename to frappe/website/page_renderers/web_page.py diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index 854948740c..9816900677 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -3,14 +3,14 @@ import re from werkzeug.routing import Rule import frappe -from frappe.website.page_controllers.document_page import DocumentPage -from frappe.website.page_controllers.list_page import ListPage -from frappe.website.page_controllers.not_found_page import NotFoundPage -from frappe.website.page_controllers.print_page import PrintPage -from frappe.website.page_controllers.redirect_page import RedirectPage -from frappe.website.page_controllers.static_page import StaticPage -from frappe.website.page_controllers.template_page import TemplatePage -from frappe.website.page_controllers.web_form import WebFormPage +from frappe.website.page_renderers.document_page import DocumentPage +from frappe.website.page_renderers.list_page import ListPage +from frappe.website.page_renderers.not_found_page import NotFoundPage +from frappe.website.page_renderers.print_page import PrintPage +from frappe.website.page_renderers.redirect_page import RedirectPage +from frappe.website.page_renderers.static_page import StaticPage +from frappe.website.page_renderers.template_page import TemplatePage +from frappe.website.page_renderers.web_form import WebFormPage from frappe.website.router import evaluate_dynamic_routes from frappe.website.utils import can_cache, get_home_page diff --git a/frappe/website/serve.py b/frappe/website/serve.py index a761f479f3..fe7fc77064 100644 --- a/frappe/website/serve.py +++ b/frappe/website/serve.py @@ -1,7 +1,7 @@ import frappe -from frappe.website.page_controllers.error_page import ErrorPage -from frappe.website.page_controllers.not_permitted_page import NotPermittedPage -from frappe.website.page_controllers.redirect_page import RedirectPage +from frappe.website.page_renderers.error_page import ErrorPage +from frappe.website.page_renderers.not_permitted_page import NotPermittedPage +from frappe.website.page_renderers.redirect_page import RedirectPage from frappe.website.path_resolver import PathResolver From 86897c1808063efccbc8929250c3d2ca203b9c9c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 10:53:35 +0530 Subject: [PATCH 155/868] refactor: Remove render.py and move all utility functions to utils.py - Replace or remove all render imports --- frappe/cache_manager.py | 2 +- frappe/commands/utils.py | 8 +- frappe/core/doctype/comment/comment.py | 2 +- frappe/core/doctype/doctype/doctype.py | 9 +-- frappe/installer.py | 4 +- frappe/migrate.py | 4 +- frappe/patches.txt | 2 +- .../templates/includes/comments/comments.py | 2 +- .../about_us_settings/about_us_settings.py | 6 +- .../doctype/blog_category/blog_category.py | 2 +- frappe/website/doctype/blog_post/blog_post.py | 2 +- .../doctype/blog_settings/blog_settings.py | 4 +- .../contact_us_settings.py | 2 +- .../doctype/help_article/help_article.py | 2 +- .../portal_settings/portal_settings.py | 2 +- .../doctype/web_template/web_template.py | 2 +- .../doctype/website_script/website_script.py | 2 +- .../website_settings/website_settings.py | 2 +- .../website_slideshow/website_slideshow.py | 2 +- .../website/page_renderers/document_page.py | 2 +- .../website/page_renderers/redirect_page.py | 2 +- .../website/page_renderers/template_page.py | 6 +- frappe/website/page_renderers/web_page.py | 4 - frappe/website/render.py | 76 ------------------- frappe/website/router.py | 49 +----------- frappe/website/utils.py | 60 +++++++++++++++ frappe/website/website_generator.py | 2 +- .../_test/_test_folder/new.csv/__init__.py | 0 28 files changed, 96 insertions(+), 166 deletions(-) delete mode 100644 frappe/website/render.py create mode 100644 frappe/www/_test/_test_folder/new.csv/__init__.py diff --git a/frappe/cache_manager.py b/frappe/cache_manager.py index 7330c83102..516f13de39 100644 --- a/frappe/cache_manager.py +++ b/frappe/cache_manager.py @@ -55,7 +55,7 @@ def clear_domain_cache(user=None): cache.delete_value(domain_cache_keys) def clear_global_cache(): - from frappe.website.render import clear_cache as clear_website_cache + from frappe.website.utils import clear_cache as clear_website_cache clear_doctype_cache() clear_website_cache() diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index 4da0f6bb78..a6937a5dc4 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -69,14 +69,14 @@ def watch(apps=None): def clear_cache(context): "Clear cache, doctype cache and defaults" import frappe.sessions - import frappe.website.render + from frappe.website.utils import clear_cache as clear_website_cache from frappe.desk.notifications import clear_notifications for site in context.sites: try: frappe.connect(site) frappe.clear_cache() clear_notifications() - frappe.website.render.clear_cache() + clear_website_cache() finally: frappe.destroy() if not context.sites: @@ -86,12 +86,12 @@ def clear_cache(context): @pass_context def clear_website_cache(context): "Clear website cache" - import frappe.website.render + from frappe.website.utils import clear_cache as clear_website_cache for site in context.sites: try: frappe.init(site=site) frappe.connect() - frappe.website.render.clear_cache() + clear_website_cache() finally: frappe.destroy() if not context.sites: diff --git a/frappe/core/doctype/comment/comment.py b/frappe/core/doctype/comment/comment.py index ad5d60500b..6090947393 100644 --- a/frappe/core/doctype/comment/comment.py +++ b/frappe/core/doctype/comment/comment.py @@ -11,7 +11,7 @@ from frappe.core.doctype.user.user import extract_mentions from frappe.desk.doctype.notification_log.notification_log import enqueue_create_notification,\ get_title, get_title_html from frappe.utils import get_fullname -from frappe.website.render import clear_cache +from frappe.website.utils import clear_cache from frappe.database.schema import add_column from frappe.exceptions import ImplicitCommitError diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 84673f990a..8186aac2b0 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -13,7 +13,6 @@ from six import iteritems # imports - module imports import frappe -import frappe.website.render from frappe import _ from frappe.utils import now, cint from frappe.model import no_value_fields, default_fields, data_fieldtypes, table_fields, data_field_options @@ -27,6 +26,7 @@ from frappe.model.docfield import supports_translation from frappe.modules.import_file import get_file_path from frappe.model.meta import Meta from frappe.desk.utils import validate_route_conflict +from frappe.website.utils import clear_cache class InvalidFieldNameError(frappe.ValidationError): pass class UniqueFieldnameError(frappe.ValidationError): pass @@ -251,7 +251,7 @@ class DocType(Document): frappe.throw(_('Field "route" is mandatory for Web Views'), title='Missing Field') # clear website cache - frappe.website.render.clear_cache() + clear_cache() def change_modified_of_parent(self): """Change the timestamp of parent DocType if the current one is a child to clear caches.""" @@ -553,11 +553,6 @@ class DocType(Document): from frappe.modules.export_file import export_to_files export_to_files(record_list=[['DocType', self.name]], create_init=True) - def import_doc(self): - """Import from standard folder `[module]/doctype/[name]/[name].json`.""" - from frappe.modules.import_module import import_from_files - import_from_files(record_list=[[self.module, 'doctype', self.name]]) - def make_controller_template(self): """Make boilerplate controller template.""" make_boilerplate("controller._py", self) diff --git a/frappe/installer.py b/frappe/installer.py index d7d885d60e..138d5abc1b 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -282,10 +282,10 @@ def remove_app(app_name, dry_run=False, yes=False, no_backup=False, force=False) def post_install(rebuild_website=False): - from frappe.website import render + from frappe.website.utils import clear_cache as clear_website_cache if rebuild_website: - render.clear_cache() + clear_website_cache() init_singles() frappe.db.commit() diff --git a/frappe/migrate.py b/frappe/migrate.py index 619510fe5e..0fe7c2e034 100644 --- a/frappe/migrate.py +++ b/frappe/migrate.py @@ -15,7 +15,7 @@ from frappe.utils.connections import check_connection from frappe.utils.dashboard import sync_dashboards from frappe.cache_manager import clear_global_cache from frappe.desk.notifications import clear_notifications -from frappe.website import render +from frappe.website.utils import clear_cache as clear_website_cache from frappe.core.doctype.language.language import sync_languages from frappe.modules.utils import sync_customizations from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs @@ -78,7 +78,7 @@ Otherwise, check the server logs and ensure that all the required services are r frappe.get_doc('Portal Settings', 'Portal Settings').sync_menu() # syncs statics - render.clear_cache() + clear_website_cache() # updating installed applications data frappe.get_single('Installed Applications').update_versions() diff --git a/frappe/patches.txt b/frappe/patches.txt index e70be0a37b..a2a3f73592 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -93,7 +93,7 @@ frappe.patches.v4_0.create_custom_field_for_owner_match frappe.patches.v4_0.enable_scheduler_in_system_settings execute:frappe.db.sql("update tabReport set apply_user_permissions=1") #2014-06-03 frappe.patches.v4_0.replace_deprecated_timezones -execute:import frappe.website.render; frappe.website.render.clear_cache("login"); #2014-06-10 +execute:import frappe.website.utils; frappe.website.utils.clear_cache("login"); #2014-06-10 frappe.patches.v4_0.fix_attach_field_file_url execute:frappe.permissions.reset_perms("User") #2015-03-24 execute:frappe.db.sql("""delete from `tabUserRole` where ifnull(parentfield, '')='' or ifnull(`role`, '')=''""") #2014-08-18 diff --git a/frappe/templates/includes/comments/comments.py b/frappe/templates/includes/comments/comments.py index d08eb12ba8..b1cd98f2b9 100644 --- a/frappe/templates/includes/comments/comments.py +++ b/frappe/templates/includes/comments/comments.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe import re -from frappe.website.render import clear_cache +from frappe.website.utils import clear_cache from frappe.utils import add_to_date, now from frappe import _ diff --git a/frappe/website/doctype/about_us_settings/about_us_settings.py b/frappe/website/doctype/about_us_settings/about_us_settings.py index 5b93cdcede..1ef832ba99 100644 --- a/frappe/website/doctype/about_us_settings/about_us_settings.py +++ b/frappe/website/doctype/about_us_settings/about_us_settings.py @@ -9,11 +9,11 @@ import frappe from frappe.model.document import Document class AboutUsSettings(Document): - + def on_update(self): - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache("about") - + def get_args(): obj = frappe.get_doc("About Us Settings") return { diff --git a/frappe/website/doctype/blog_category/blog_category.py b/frappe/website/doctype/blog_category/blog_category.py index 375ba5b6a3..b8252c993f 100644 --- a/frappe/website/doctype/blog_category/blog_category.py +++ b/frappe/website/doctype/blog_category/blog_category.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from frappe.website.website_generator import WebsiteGenerator -from frappe.website.render import clear_cache +from frappe.website.utils import clear_cache class BlogCategory(WebsiteGenerator): def autoname(self): diff --git a/frappe/website/doctype/blog_post/blog_post.py b/frappe/website/doctype/blog_post/blog_post.py index 5671540682..b8a443525f 100644 --- a/frappe/website/doctype/blog_post/blog_post.py +++ b/frappe/website/doctype/blog_post/blog_post.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.website.website_generator import WebsiteGenerator -from frappe.website.render import clear_cache +from frappe.website.utils import clear_cache from frappe.utils import today, cint, global_date_format, get_fullname, strip_html_tags, markdown, sanitize_html from math import ceil from frappe.website.utils import (find_first_image, get_html_content_based_on_type, diff --git a/frappe/website/doctype/blog_settings/blog_settings.py b/frappe/website/doctype/blog_settings/blog_settings.py index 0ed98b9b87..2580806ef1 100644 --- a/frappe/website/doctype/blog_settings/blog_settings.py +++ b/frappe/website/doctype/blog_settings/blog_settings.py @@ -9,8 +9,8 @@ import frappe from frappe.model.document import Document class BlogSettings(Document): - + def on_update(self): - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache("blog") clear_cache("writers") \ No newline at end of file diff --git a/frappe/website/doctype/contact_us_settings/contact_us_settings.py b/frappe/website/doctype/contact_us_settings/contact_us_settings.py index 24e9811a47..c237a13bda 100644 --- a/frappe/website/doctype/contact_us_settings/contact_us_settings.py +++ b/frappe/website/doctype/contact_us_settings/contact_us_settings.py @@ -11,5 +11,5 @@ from frappe.model.document import Document class ContactUsSettings(Document): def on_update(self): - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache("contact") \ No newline at end of file diff --git a/frappe/website/doctype/help_article/help_article.py b/frappe/website/doctype/help_article/help_article.py index fa26cfef99..555d6c9268 100644 --- a/frappe/website/doctype/help_article/help_article.py +++ b/frappe/website/doctype/help_article/help_article.py @@ -93,7 +93,7 @@ def get_sidebar_items(): def clear_cache(): clear_website_cache() - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache() def clear_website_cache(path=None): diff --git a/frappe/website/doctype/portal_settings/portal_settings.py b/frappe/website/doctype/portal_settings/portal_settings.py index 1bfbc70d60..84ee678c1e 100644 --- a/frappe/website/doctype/portal_settings/portal_settings.py +++ b/frappe/website/doctype/portal_settings/portal_settings.py @@ -45,7 +45,7 @@ class PortalSettings(Document): # clear web cache (for menus!) frappe.clear_cache(user='Guest') - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache() # clears role based home pages diff --git a/frappe/website/doctype/web_template/web_template.py b/frappe/website/doctype/web_template/web_template.py index 2fd5bfa179..712cf3c1e4 100644 --- a/frappe/website/doctype/web_template/web_template.py +++ b/frappe/website/doctype/web_template/web_template.py @@ -9,7 +9,7 @@ from shutil import rmtree import frappe from frappe.model.document import Document -from frappe.website.render import clear_cache +from frappe.website.utils import clear_cache from frappe import _ from frappe.modules.export_file import ( write_document_file, diff --git a/frappe/website/doctype/website_script/website_script.py b/frappe/website/doctype/website_script/website_script.py index 5648c27fd6..d1f9f595ed 100644 --- a/frappe/website/doctype/website_script/website_script.py +++ b/frappe/website/doctype/website_script/website_script.py @@ -14,5 +14,5 @@ class WebsiteScript(Document): """clear cache""" frappe.clear_cache(user = 'Guest') - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache() \ No newline at end of file diff --git a/frappe/website/doctype/website_settings/website_settings.py b/frappe/website/doctype/website_settings/website_settings.py index ae8e6bd7e1..e5dec24fbb 100644 --- a/frappe/website/doctype/website_settings/website_settings.py +++ b/frappe/website/doctype/website_settings/website_settings.py @@ -68,7 +68,7 @@ class WebsiteSettings(Document): # clear web cache (for menus!) frappe.clear_cache(user = 'Guest') - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache() # clears role based home pages diff --git a/frappe/website/doctype/website_slideshow/website_slideshow.py b/frappe/website/doctype/website_slideshow/website_slideshow.py index 90f62d1bb1..5e6353c5cd 100644 --- a/frappe/website/doctype/website_slideshow/website_slideshow.py +++ b/frappe/website/doctype/website_slideshow/website_slideshow.py @@ -15,7 +15,7 @@ class WebsiteSlideshow(Document): def on_update(self): # a slide show can be in use and any change in it should get reflected - from frappe.website.render import clear_cache + from frappe.website.utils import clear_cache clear_cache() def validate_images(self): diff --git a/frappe/website/page_renderers/document_page.py b/frappe/website/page_renderers/document_page.py index 34dc42e203..2f272ffd15 100644 --- a/frappe/website/page_renderers/document_page.py +++ b/frappe/website/page_renderers/document_page.py @@ -1,7 +1,7 @@ import frappe from frappe.model.document import get_controller from frappe.website.page_renderers.base_template_page import BaseTemplatePage -from frappe.website.render import build_response +from frappe.website.utils import build_response from frappe.website.router import (get_doctypes_with_web_view, get_page_info_from_web_page_with_dynamic_routes) diff --git a/frappe/website/page_renderers/redirect_page.py b/frappe/website/page_renderers/redirect_page.py index 0bfa8897a3..2049c375e8 100644 --- a/frappe/website/page_renderers/redirect_page.py +++ b/frappe/website/page_renderers/redirect_page.py @@ -1,5 +1,5 @@ import frappe -from frappe.website.render import build_response +from frappe.website.utils import build_response class RedirectPage(object): def __init__(self, path, http_status_code=301): diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index 467d74b283..d8032c6b9c 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -4,11 +4,9 @@ import click import frappe from frappe.website.page_renderers.base_template_page import BaseTemplatePage -from frappe.website.utils import get_sidebar_items -from frappe.website.render import build_response from frappe.website.router import get_base_template -from frappe.website.utils import (extract_comment_tag, extract_title, - get_next_link, get_toc, get_frontmatter, cache_html) +from frappe.website.utils import (extract_comment_tag, extract_title, get_next_link, + get_toc, get_frontmatter, cache_html, get_sidebar_items, build_response) WEBPAGE_PY_MODULE_PROPERTIES = ("base_template_path", "template", "no_cache", "sitemap", "condition_field") diff --git a/frappe/website/page_renderers/web_page.py b/frappe/website/page_renderers/web_page.py index 0407afe532..5c3807c0ee 100644 --- a/frappe/website/page_renderers/web_page.py +++ b/frappe/website/page_renderers/web_page.py @@ -9,10 +9,6 @@ class WebPage(object): self.path = path.strip('/ ') self.basepath = '' - def get(self): - if self.validate(): - return self.render() - def can_render(self): pass diff --git a/frappe/website/render.py b/frappe/website/render.py deleted file mode 100644 index d5587ad98b..0000000000 --- a/frappe/website/render.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import json -import mimetypes -import re - -from six import iteritems -from werkzeug.wrappers import Response - -import frappe -import frappe.sessions - - -def build_response(path, data, http_status_code, headers=None): - # build response - response = Response() - response.data = set_content_type(response, data, path) - response.status_code = http_status_code - response.headers["X-Page-Name"] = path.encode("ascii", errors="xmlcharrefreplace") - response.headers["X-From-Cache"] = frappe.local.response.from_cache or False - - add_preload_headers(response) - if headers: - for key, val in iteritems(headers): - response.headers[key] = val.encode("ascii", errors="xmlcharrefreplace") - - return response - -def set_content_type(response, data, path): - if isinstance(data, dict): - response.mimetype = 'application/json' - response.charset = 'utf-8' - data = json.dumps(data) - return data - - response.mimetype = 'text/html' - response.charset = 'utf-8' - - # ignore paths ending with .com to avoid unnecessary download - # https://bugs.python.org/issue22347 - if "." in path and not path.endswith('.com'): - content_type, encoding = mimetypes.guess_type(path) - if content_type: - response.mimetype = content_type - if encoding: - response.charset = encoding - - return data - -def add_preload_headers(response): - from bs4 import BeautifulSoup - - try: - preload = [] - soup = BeautifulSoup(response.data, "lxml") - for elem in soup.find_all('script', src=re.compile(".*")): - preload.append(("script", elem.get("src"))) - - for elem in soup.find_all('link', rel="stylesheet"): - preload.append(("style", elem.get("href"))) - - links = [] - for _type, link in preload: - links.append("<{}>; rel=preload; as={}".format(link, _type)) - - if links: - response.headers["Link"] = ",".join(links) - except Exception: - import traceback - traceback.print_exc() - -def clear_cache(path=None): - # TODO: Remove this - from frappe.website.utils import clear_cache - return clear_cache(path) diff --git a/frappe/website/router.py b/frappe/website/router.py index 9922647ebf..23fd5cb21f 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -6,7 +6,7 @@ import os import re import frappe -from frappe.website.utils import extract_comment_tag, extract_title +from frappe.website.utils import extract_title from werkzeug.routing import Map, Rule, NotFound def get_page_info_from_web_page_with_dynamic_routes(path): @@ -143,14 +143,12 @@ def get_page_info(path, app, start, basepath=None, app_path=None, fname=None): # get the source setup_source(page_info) - # extract properties from HTML comments - load_properties_from_source(page_info) + if not page_info.title: + page_info.title = extract_title(page_info.source, page_info.route) # extract properties from controller attributes load_properties_from_controller(page_info) - page_info.build_version = frappe.utils.get_build_version() - return page_info def get_frontmatter(string): @@ -252,47 +250,6 @@ def setup_index(page_info): if os.path.exists(index_txt_path): page_info.index = open(index_txt_path, 'r').read().splitlines() -def load_properties_from_source(page_info): - '''Load properties like no_cache, title from source html''' - - if not page_info.title: - page_info.title = extract_title(page_info.source, page_info.route) - - base_template = extract_comment_tag(page_info.source, 'base_template') - if base_template: - page_info.base_template = base_template - - if (page_info.base_template - and "{%- extends" not in page_info.source - and "{% extends" not in page_info.source - and "" not in page_info.source): - page_info.source = '''{{% extends "{0}" %}} - {{% block page_content %}}{1}{{% endblock %}}'''.format(page_info.base_template, page_info.source) - - if "" in page_info.source: - page_info.no_breadcrumbs = 1 - - if "" in page_info.source: - page_info.show_sidebar = 1 - - if "" in page_info.source: - page_info.add_breadcrumbs = 1 - - if "" in page_info.source: - page_info.no_header = 1 - - if "" in page_info.source: - page_info.add_next_prev_links = 1 - - if "" in page_info.source: - page_info.no_cache = 1 - - if "" in page_info.source: - page_info.sitemap = 0 - - if "" in page_info.source: - page_info.sitemap = 1 - def load_properties_from_controller(page_info): if not page_info.controller: return diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 814bd0101e..f57cfa7ec5 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -2,6 +2,7 @@ # MIT License. See license.txt import functools import json +import mimetypes import os import re from functools import wraps @@ -9,6 +10,7 @@ from functools import wraps import yaml from past.builtins import cmp from six import iteritems +from werkzeug.wrappers import Response import frappe from frappe import _ @@ -446,3 +448,61 @@ def cache_html(func): return html return cache_html_decorator + +def build_response(path, data, http_status_code, headers=None): + # build response + response = Response() + response.data = set_content_type(response, data, path) + response.status_code = http_status_code + response.headers["X-Page-Name"] = path.encode("ascii", errors="xmlcharrefreplace") + response.headers["X-From-Cache"] = frappe.local.response.from_cache or False + + add_preload_headers(response) + if headers: + for key, val in iteritems(headers): + response.headers[key] = val.encode("ascii", errors="xmlcharrefreplace") + + return response + +def set_content_type(response, data, path): + if isinstance(data, dict): + response.mimetype = 'application/json' + response.charset = 'utf-8' + data = json.dumps(data) + return data + + response.mimetype = 'text/html' + response.charset = 'utf-8' + + # ignore paths ending with .com to avoid unnecessary download + # https://bugs.python.org/issue22347 + if "." in path and not path.endswith('.com'): + content_type, encoding = mimetypes.guess_type(path) + if content_type: + response.mimetype = content_type + if encoding: + response.charset = encoding + + return data + +def add_preload_headers(response): + from bs4 import BeautifulSoup + + try: + preload = [] + soup = BeautifulSoup(response.data, "lxml") + for elem in soup.find_all('script', src=re.compile(".*")): + preload.append(("script", elem.get("src"))) + + for elem in soup.find_all('link', rel="stylesheet"): + preload.append(("style", elem.get("href"))) + + links = [] + for _type, link in preload: + links.append("<{}>; rel=preload; as={}".format(link, _type)) + + if links: + response.headers["Link"] = ",".join(links) + except Exception: + import traceback + traceback.print_exc() diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index f2638fd86d..8b0a1bfd2d 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.website.utils import cleanup_page_name -from frappe.website.render import clear_cache +from frappe.website.utils import clear_cache from frappe.modules import get_module_name from frappe.search.website_search import update_index_for_path, remove_document_from_index diff --git a/frappe/www/_test/_test_folder/new.csv/__init__.py b/frappe/www/_test/_test_folder/new.csv/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 889e8aacb73f9c059cd5d39d88c3a612c44fbae8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 25 May 2021 12:51:10 +0530 Subject: [PATCH 156/868] ci(semgrep): false +ve translation on templates separated JS and python rules for granuarilty. Ignore matches with microtemplating that have this structure: `{{.*_.*}}` in string. --- .github/helper/semgrep_rules/ux.js | 9 +++++++++ .github/helper/semgrep_rules/ux.py | 18 +++++++++--------- .github/helper/semgrep_rules/ux.yml | 23 +++++++++++++++++++---- 3 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 .github/helper/semgrep_rules/ux.js diff --git a/.github/helper/semgrep_rules/ux.js b/.github/helper/semgrep_rules/ux.js new file mode 100644 index 0000000000..ae73f9cc60 --- /dev/null +++ b/.github/helper/semgrep_rules/ux.js @@ -0,0 +1,9 @@ + +// ok: frappe-missing-translate-function-js +frappe.msgprint('{{ _("Both login and password required") }}'); + +// ruleid: frappe-missing-translate-function-js +frappe.msgprint('What'); + +// ok: frappe-missing-translate-function-js +frappe.throw(' {{ _("Both login and password required") }}. '); diff --git a/.github/helper/semgrep_rules/ux.py b/.github/helper/semgrep_rules/ux.py index 4a74457435..a00d3cd8ae 100644 --- a/.github/helper/semgrep_rules/ux.py +++ b/.github/helper/semgrep_rules/ux.py @@ -2,30 +2,30 @@ import frappe from frappe import msgprint, throw, _ -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python throw("Error Occured") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python frappe.throw("Error Occured") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python frappe.msgprint("Useful message") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python msgprint("Useful message") -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python translatedmessage = _("Hello") -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python throw(translatedmessage) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python msgprint(translatedmessage) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python msgprint(_("Helpful message")) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python frappe.throw(_("Error occured")) diff --git a/.github/helper/semgrep_rules/ux.yml b/.github/helper/semgrep_rules/ux.yml index ed06a6a80c..dd667f36c0 100644 --- a/.github/helper/semgrep_rules/ux.yml +++ b/.github/helper/semgrep_rules/ux.yml @@ -1,15 +1,30 @@ rules: -- id: frappe-missing-translate-function +- id: frappe-missing-translate-function-python pattern-either: - patterns: - pattern: frappe.msgprint("...", ...) - pattern-not: frappe.msgprint(_("..."), ...) - - pattern-not: frappe.msgprint(__("..."), ...) - patterns: - pattern: frappe.throw("...", ...) - pattern-not: frappe.throw(_("..."), ...) - - pattern-not: frappe.throw(__("..."), ...) message: | All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations - languages: [python, javascript, json] + languages: [python] + severity: ERROR + +- id: frappe-missing-translate-function-js + pattern-either: + - patterns: + - pattern: frappe.msgprint("...", ...) + - pattern-not: frappe.msgprint(__("..."), ...) + # ignore microtemplating e.g. msgprint("{{ _("server side translation") }}") + - pattern-not: frappe.msgprint("=~/\{\{.*\_.*\}\}/i", ...) + - patterns: + - pattern: frappe.throw("...", ...) + - pattern-not: frappe.throw(__("..."), ...) + # ignore microtemplating + - pattern-not: frappe.throw("=~/\{\{.*\_.*\}\}/i", ...) + message: | + All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations + languages: [javascript] severity: ERROR From faa347461d7e09136803d82931f179b90aabcfb7 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 25 May 2021 13:00:02 +0530 Subject: [PATCH 157/868] chore: fix all findings flaged by ux rule --- frappe/desk/doctype/dashboard/dashboard.py | 2 +- frappe/desk/doctype/dashboard_chart/dashboard_chart.py | 2 +- frappe/templates/includes/contact.js | 10 ++++------ frappe/tests/ui_test_helpers.py | 3 ++- frappe/utils/jinja.py | 4 ++-- frappe/utils/password.py | 2 +- frappe/utils/safe_exec.py | 3 ++- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frappe/desk/doctype/dashboard/dashboard.py b/frappe/desk/doctype/dashboard/dashboard.py index 4e66318769..90620ed3c5 100644 --- a/frappe/desk/doctype/dashboard/dashboard.py +++ b/frappe/desk/doctype/dashboard/dashboard.py @@ -22,7 +22,7 @@ class Dashboard(Document): def validate(self): if not frappe.conf.developer_mode and self.is_standard: - frappe.throw('Cannot edit Standard Dashboards') + frappe.throw(_('Cannot edit Standard Dashboards')) if self.is_standard: non_standard_docs_map = { diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py index 48b34e6cd9..cd934c54e6 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py @@ -326,7 +326,7 @@ class DashboardChart(Document): def validate(self): if not frappe.conf.developer_mode and self.is_standard: - frappe.throw('Cannot edit Standard charts') + frappe.throw(_('Cannot edit Standard charts')) if self.chart_type != 'Custom' and self.chart_type != 'Report': self.check_required_field() self.check_document_type() diff --git a/frappe/templates/includes/contact.js b/frappe/templates/includes/contact.js index 130d8bfc0c..fb0b73ff80 100644 --- a/frappe/templates/includes/contact.js +++ b/frappe/templates/includes/contact.js @@ -12,14 +12,12 @@ frappe.ready(function() { var message = $('[name="message"]').val(); if(!(email && message)) { - frappe.msgprint("{{ _("Please enter both your email and message so that we \ - can get back to you. Thanks!") }}"); + frappe.msgprint('{{ _("Please enter both your email and message so that we can get back to you. Thanks!") }}'); return false; } if(!validate_email(email)) { - frappe.msgprint("{{ _("You seem to have written your name instead of your email. \ - Please enter a valid email address so that we can get back.") }}"); + frappe.msgprint('{{ _("You seem to have written your name instead of your email. Please enter a valid email address so that we can get back.") }}'); $('[name="email"]').focus(); return false; } @@ -31,9 +29,9 @@ frappe.ready(function() { message: message, callback: function(r) { if(r.message==="okay") { - frappe.msgprint("{{ _("Thank you for your message") }}"); + frappe.msgprint('{{ _("Thank you for your message") }}'); } else { - frappe.msgprint("{{ _("There were errors") }}"); + frappe.msgprint('{{ _("There were errors") }}'); console.log(r.exc); } $(':input').val(''); diff --git a/frappe/tests/ui_test_helpers.py b/frappe/tests/ui_test_helpers.py index f56311b2e3..7670f99698 100644 --- a/frappe/tests/ui_test_helpers.py +++ b/frappe/tests/ui_test_helpers.py @@ -1,4 +1,5 @@ import frappe +from frappe import _ from frappe.utils import add_to_date, now @frappe.whitelist() @@ -10,7 +11,7 @@ def create_if_not_exists(doc): ''' if not frappe.local.dev_server: - frappe.throw('This method can only be accessed in development', frappe.PermissionError) + frappe.throw(_('This method can only be accessed in development'), frappe.PermissionError) doc = frappe.parse_json(doc) diff --git a/frappe/utils/jinja.py b/frappe/utils/jinja.py index a77eca4977..c276526c52 100644 --- a/frappe/utils/jinja.py +++ b/frappe/utils/jinja.py @@ -67,7 +67,7 @@ def render_template(template, context, is_path=None, safe_render=True): :param safe_render: (optional) prevent server side scripting via jinja templating ''' - from frappe import get_traceback, throw + from frappe import get_traceback, throw, _ from jinja2 import TemplateError if not template: @@ -77,7 +77,7 @@ def render_template(template, context, is_path=None, safe_render=True): return get_jenv().get_template(template).render(context) else: if safe_render and ".__" in template: - throw("Illegal template") + throw(_("Illegal template")) try: return get_jenv().from_string(template).render(context) except TemplateError: diff --git a/frappe/utils/password.py b/frappe/utils/password.py index fbed3cd8e7..fef0bab8af 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -61,7 +61,7 @@ def set_encrypted_password(doctype, name, pwd, fieldname='password'): except frappe.db.DataError as e: if ((frappe.db.db_type == 'mariadb' and e.args[0] == DATA_TOO_LONG) or (frappe.db.db_type == 'postgres' and e.pgcode == STRING_DATA_RIGHT_TRUNCATION)): - frappe.throw("Most probably your password is too long.", exc=e) + frappe.throw(_("Most probably your password is too long."), exc=e) raise e diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index 643812b226..21508706c9 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -5,6 +5,7 @@ from html2text import html2text from RestrictedPython import compile_restricted, safe_globals import RestrictedPython.Guards import frappe +from frappe import _ import frappe.utils import frappe.utils.data from frappe.website.utils import (get_shade, get_toc, get_next_link) @@ -31,7 +32,7 @@ class NamespaceDict(frappe._dict): def safe_exec(script, _globals=None, _locals=None): # script reports must be enabled via site_config.json if not frappe.conf.server_script_enabled: - frappe.throw('Please Enable Server Scripts', ServerScriptNotEnabled) + frappe.throw(_('Please Enable Server Scripts'), ServerScriptNotEnabled) # build globals exec_globals = get_safe_globals() From d88ce8e807fe7acbc5e8c1cb9bec8fd6c52bb432 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 13:32:20 +0530 Subject: [PATCH 158/868] test: Add test to check replacement of {next} & {index} identifiers --- frappe/website/doctype/web_page/test_web_page.py | 16 +++++++++++----- frappe/www/_test/_test_folder/_test_page.html | 1 + frappe/www/_test/_test_folder/index.md | 3 +++ 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 frappe/www/_test/_test_folder/index.md diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index c5d250a4a0..b9bd425781 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -91,12 +91,18 @@ class TestWebPage(unittest.TestCase): self.assertTrue('Test Sidebar' in frappe.as_unicode(content)) frappe.flags.look_for_sidebar = False - def test_home_page(self): - content = get_response_content(path='/') - content = get_response_content(path='/index') + def test_index_and_next_comment(self): + content = get_response_content('/_test/_test_folder') + # test if {index} was rendered + self.assertTrue(' Test Page' \ + in frappe.as_unicode(content)) + self.assertTrue(' Test Toc' \ + in frappe.as_unicode(content)) - def test_table_of_content(self): - page = get_response(path='/_test/_test_folder/_test_toc') + content = get_response_content('/_test/_test_folder/_test_page') + # test if {next} was rendered + self.assertTrue('Next: Test Toc' \ + in frappe.as_unicode(content)) def test_meta_tags(self): pass diff --git a/frappe/www/_test/_test_folder/_test_page.html b/frappe/www/_test/_test_folder/_test_page.html index 900f07459d..123d619e38 100644 --- a/frappe/www/_test/_test_folder/_test_page.html +++ b/frappe/www/_test/_test_folder/_test_page.html @@ -1,4 +1,5 @@ {% block content %} {% include "templates/includes/web_sidebar.html" %}

Test content

+{next} {% endblock %} diff --git a/frappe/www/_test/_test_folder/index.md b/frappe/www/_test/_test_folder/index.md new file mode 100644 index 0000000000..d0b531a642 --- /dev/null +++ b/frappe/www/_test/_test_folder/index.md @@ -0,0 +1,3 @@ +# Index + +{index} \ No newline at end of file From ca56b21290b52a1fde8c34db718ee264756274ef Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 15:01:20 +0530 Subject: [PATCH 159/868] test: Check all cases of setting homepage --- frappe/tests/test_website.py | 63 ++++++++++++++++++++++++----- frappe/website/utils.py | 3 ++ frappe/www/_test/_test_home_page.py | 2 + 3 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 frappe/www/_test/_test_home_page.py diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index cc500d1c02..6b9530a8ce 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -4,7 +4,7 @@ import unittest import frappe from frappe.website.serve import get_response -from frappe.website.utils import get_home_page +from frappe.website.utils import get_home_page, clear_website_cache from frappe.utils import set_request class TestWebsite(unittest.TestCase): @@ -14,32 +14,29 @@ class TestWebsite(unittest.TestCase): def tearDown(self): frappe.set_user('Administrator') - def test_home_page_for_role(self): + def test_home_page(self): frappe.set_user('Administrator') - frappe.delete_doc_if_exists('User', 'test-user-for-home-page@example.com') - frappe.delete_doc_if_exists('Role', 'home-page-test') - frappe.delete_doc_if_exists('Web Page', 'home-page-test') + # test home page via role user = frappe.get_doc(dict( doctype='User', email='test-user-for-home-page@example.com', - first_name='test')).insert() + first_name='test')).insert(ignore_if_duplicate=True) role = frappe.get_doc(dict( doctype = 'Role', role_name = 'home-page-test', desk_access = 0, - home_page = '/home-page-test' - )).insert() + )).insert(ignore_if_duplicate=True) user.add_roles(role.name) user.save() + frappe.db.set_value('Role', 'home-page-test', 'home_page', 'home-page-test') frappe.set_user('test-user-for-home-page@example.com') self.assertEqual(get_home_page(), 'home-page-test') frappe.set_user('Administrator') - role.home_page = '' - role.save() + frappe.db.set_value('Role', 'home-page-test', 'home_page', '') # home page via portal settings frappe.db.set_value('Portal Settings', None, 'default_portal_home', 'test-portal-home') @@ -48,6 +45,42 @@ class TestWebsite(unittest.TestCase): frappe.cache().hdel('home_page', frappe.session.user) self.assertEqual(get_home_page(), 'test-portal-home') + frappe.db.set_value("Portal Settings", None, "default_portal_home", '') + clear_website_cache() + + # home page via website settings + frappe.db.set_value("Website Settings", None, "home_page", 'contact') + self.assertEqual(get_home_page(), 'contact') + + frappe.db.set_value("Website Settings", None, "home_page", None) + clear_website_cache() + + # fallback homepage + self.assertEqual(get_home_page(), 'me') + + # fallback homepage for guest + frappe.set_user('Guest') + self.assertEqual(get_home_page(), 'login') + frappe.set_user('Administrator') + + # test homepage via hooks + clear_website_cache() + set_home_page_hook('get_website_user_home_page', 'frappe.www._test._test_home_page.get_website_user_home_page') + self.assertEqual(get_home_page(), '_test/_test_folder') + + clear_website_cache() + set_home_page_hook('website_user_home_page', 'login') + self.assertEqual(get_home_page(), 'login') + + clear_website_cache() + set_home_page_hook('home_page', 'about') + self.assertEqual(get_home_page(), 'about') + + clear_website_cache() + set_home_page_hook('role_home_page', {'home-page-test': 'home-page-test'}) + self.assertEqual(get_home_page(), 'home-page-test') + + def test_page_load(self): set_request(method='POST', path='login') response = get_response() @@ -147,3 +180,13 @@ class TestWebsite(unittest.TestCase): delattr(frappe.hooks, 'website_redirects') frappe.cache().delete_key('app_hooks') + + +def set_home_page_hook(key, value): + from frappe import hooks + # reset home_page hooks + for hook in ('get_website_user_home_page','website_user_home_page','role_home_page','home_page'): + if hasattr(hooks, hook): + delattr(hooks, hook) + + setattr(hooks, key, value) diff --git a/frappe/website/utils.py b/frappe/website/utils.py index f57cfa7ec5..a6d9535ec6 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -328,6 +328,9 @@ def clear_cache(path=None): for method in frappe.get_hooks("website_clear_cache"): frappe.get_attr(method)(path) +def clear_website_cache(path=None): + clear_cache(path) + def clear_sitemap(): delete_page_cache("*") diff --git a/frappe/www/_test/_test_home_page.py b/frappe/www/_test/_test_home_page.py new file mode 100644 index 0000000000..936399c700 --- /dev/null +++ b/frappe/www/_test/_test_home_page.py @@ -0,0 +1,2 @@ +def get_website_user_home_page(user): + return '/_test/_test_folder' \ No newline at end of file From e6d701b038545fbdba72d7d968776bcb0f5f7356 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 15:02:18 +0530 Subject: [PATCH 160/868] refactor: Use clear_website_cache instead of clear_cache --- frappe/cache_manager.py | 2 +- frappe/commands/utils.py | 4 ++-- frappe/installer.py | 2 +- frappe/migrate.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frappe/cache_manager.py b/frappe/cache_manager.py index 516f13de39..6b937731b0 100644 --- a/frappe/cache_manager.py +++ b/frappe/cache_manager.py @@ -55,7 +55,7 @@ def clear_domain_cache(user=None): cache.delete_value(domain_cache_keys) def clear_global_cache(): - from frappe.website.utils import clear_cache as clear_website_cache + from frappe.website.utils import clear_website_cache clear_doctype_cache() clear_website_cache() diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index a6937a5dc4..b45f36ad0b 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -69,7 +69,7 @@ def watch(apps=None): def clear_cache(context): "Clear cache, doctype cache and defaults" import frappe.sessions - from frappe.website.utils import clear_cache as clear_website_cache + from frappe.website.utils import clear_website_cache from frappe.desk.notifications import clear_notifications for site in context.sites: try: @@ -86,7 +86,7 @@ def clear_cache(context): @pass_context def clear_website_cache(context): "Clear website cache" - from frappe.website.utils import clear_cache as clear_website_cache + from frappe.website.utils import clear_website_cache for site in context.sites: try: frappe.init(site=site) diff --git a/frappe/installer.py b/frappe/installer.py index 138d5abc1b..b81d0a03b4 100755 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -282,7 +282,7 @@ def remove_app(app_name, dry_run=False, yes=False, no_backup=False, force=False) def post_install(rebuild_website=False): - from frappe.website.utils import clear_cache as clear_website_cache + from frappe.website.utils import clear_website_cache if rebuild_website: clear_website_cache() diff --git a/frappe/migrate.py b/frappe/migrate.py index 0fe7c2e034..ada0860ae4 100644 --- a/frappe/migrate.py +++ b/frappe/migrate.py @@ -15,7 +15,7 @@ from frappe.utils.connections import check_connection from frappe.utils.dashboard import sync_dashboards from frappe.cache_manager import clear_global_cache from frappe.desk.notifications import clear_notifications -from frappe.website.utils import clear_cache as clear_website_cache +from frappe.website.utils import clear_website_cache from frappe.core.doctype.language.language import sync_languages from frappe.modules.utils import sync_customizations from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs From 2bbf71ade0c12ac931a898783a6e8fc330738083 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 25 May 2021 15:30:12 +0530 Subject: [PATCH 161/868] fix: refactor code --- frappe/public/js/frappe/form/grid.js | 2 +- frappe/public/js/frappe/form/grid_row.js | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index 00f9d6abca..aa3cf51314 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -348,7 +348,7 @@ export default class Grid { d.idx = ri + 1; } if (d.name === undefined) { - d.name = "row" + d.idx; + d.name = "row " + d.idx; } if (this.grid_rows[ri] && !append_row) { var grid_row = this.grid_rows[ri]; diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index bbcf0f707b..f6da88df57 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -93,11 +93,8 @@ export default class GridRow { } else { data = this.grid.df.data; } - let index = -1; - - if (me.doc.name) { - index = data.findIndex(d => d.name === me.doc.name); - } + + const index = data.findIndex(d => d.name === me.doc.name); if (index > -1) { // mutate array directly, From d30e6f6a43b371aadb9adddf019ba08549c1ec8a Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 25 May 2021 15:34:22 +0530 Subject: [PATCH 162/868] fix: refactor code --- frappe/public/js/frappe/form/grid.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index aa3cf51314..13b5ebe842 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -196,9 +196,7 @@ export default class Grid { tasks.push(() => { if (dirty) { this.refresh(); - if (this.frm) { - this.frm.script_manager.trigger(this.df.fieldname + "_delete", this.doctype); - } + this.frm && this.frm.script_manager.trigger(this.df.fieldname + "_delete", this.doctype); } }); From 78206bea8fb2894138f0c9b6076c2cedf976c827 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 25 May 2021 16:39:48 +0530 Subject: [PATCH 163/868] test: Clear hook cache after updating hook --- frappe/tests/test_website.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 6b9530a8ce..69425cdc45 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -146,9 +146,6 @@ class TestWebsite(unittest.TestCase): }) website_settings.save() - frappe.cache().delete_key('app_hooks') - frappe.cache().delete_key('website_redirects') - set_request(method='GET', path='/testfrom') response = get_response() self.assertEqual(response.status_code, 301) @@ -190,3 +187,5 @@ def set_home_page_hook(key, value): delattr(hooks, hook) setattr(hooks, key, value) + frappe.cache().delete_key('app_hooks') + From e79ce22d4d7070c814da333e166830f64ca16c07 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 25 May 2021 19:08:19 +0530 Subject: [PATCH 164/868] fix: double checkboxes showing in editable grid --- frappe/public/js/frappe/form/controls/check.js | 4 +++- frappe/public/scss/common/grid.scss | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/check.js b/frappe/public/js/frappe/form/controls/check.js index 658ef640a9..1209f52e6d 100644 --- a/frappe/public/js/frappe/form/controls/check.js +++ b/frappe/public/js/frappe/form/controls/check.js @@ -14,8 +14,10 @@ frappe.ui.form.ControlCheck = class ControlCheck extends frappe.ui.form.ControlD
`).appendTo(this.parent); } set_input_areas() { - this.label_area = this.label_span = this.$wrapper.find(".label-area").get(0); this.input_area = this.$wrapper.find(".input-area").get(0); + if (this.only_input) return; + + this.label_area = this.label_span = this.$wrapper.find(".label-area").get(0); this.disp_area = this.$wrapper.find(".disp-area").get(0); } make_input() { diff --git a/frappe/public/scss/common/grid.scss b/frappe/public/scss/common/grid.scss index 3cc5139d9e..aac949b1bf 100644 --- a/frappe/public/scss/common/grid.scss +++ b/frappe/public/scss/common/grid.scss @@ -140,7 +140,7 @@ .checkbox { margin: 0px; text-align: center; - margin-top: 9px; + margin-top: var(--padding-sm); } textarea { From 45b709906fc78a50d670d3b5a7901e7b72d6d22a Mon Sep 17 00:00:00 2001 From: leela Date: Tue, 25 May 2021 19:03:30 +0530 Subject: [PATCH 165/868] fix: display currency in auto email report Currently currency is always showed as INR(default) irrespective of what currency field option is. To get the field currency, the whole document(record) is needed. Fixed it by passing the document record. (cherry picked from commit 2e58d669e22e7fc8804ddfd759cdfe24f03d2916) --- .../email/doctype/auto_email_report/auto_email_report.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.py b/frappe/email/doctype/auto_email_report/auto_email_report.py index 6f1cd8eebd..91ca518e67 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/auto_email_report.py @@ -245,6 +245,7 @@ def send_monthly(): def make_links(columns, data): for row in data: + doc_name = row.get('name') for col in columns: if col.fieldtype == "Link" and col.options != "Currency": if col.options and row.get(col.fieldname): @@ -253,8 +254,9 @@ def make_links(columns, data): if col.options and row.get(col.fieldname) and row.get(col.options): row[col.fieldname] = get_link_to_form(row[col.options], row[col.fieldname]) elif col.fieldtype == "Currency" and row.get(col.fieldname): - row[col.fieldname] = frappe.format_value(row[col.fieldname], col) - + doc = frappe.get_doc(col.parent, doc_name) if doc_name else None + # Pass the Document to get the currency based on docfield option + row[col.fieldname] = frappe.format_value(row[col.fieldname], col, doc=doc) return columns, data def update_field_types(columns): @@ -262,4 +264,4 @@ def update_field_types(columns): if col.fieldtype in ("Link", "Dynamic Link", "Currency") and col.options != "Currency": col.fieldtype = "Data" col.options = "" - return columns \ No newline at end of file + return columns From 3112d6d8431a6aa60d126fce23b892288769f61d Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 25 May 2021 20:42:55 +0530 Subject: [PATCH 166/868] fix: Sidebar Child Item Draggable & minor fixes --- .../internal_wiki_page/internal_wiki_page.py | 6 +- frappe/public/icons/timeless/symbol-defs.svg | 3 + frappe/public/js/frappe/views/wiki.js | 168 ++++++++---------- frappe/public/scss/desk/wiki.scss | 19 +- package.json | 2 +- yarn.lock | 8 +- 6 files changed, 104 insertions(+), 102 deletions(-) diff --git a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py index 3fba588343..a53473e1fe 100644 --- a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py +++ b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py @@ -35,10 +35,12 @@ def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, doc.save() if json.loads(sb_items): - for d in json.loads(sb_items): + for seq, d in enumerate(json.loads(sb_items)): doc = frappe.get_doc('Internal Wiki Page', d.get('name')) - doc.sequence_id = d.get('sequence_id') + doc.sequence_id = seq + 1 + doc.parent_page = d.get('parent_page') or "" doc.save() + doc.title = title if json.loads(deleted_pages): for d in json.loads(deleted_pages): diff --git a/frappe/public/icons/timeless/symbol-defs.svg b/frappe/public/icons/timeless/symbol-defs.svg index 5e52336bfa..87d80eef03 100644 --- a/frappe/public/icons/timeless/symbol-defs.svg +++ b/frappe/public/icons/timeless/symbol-defs.svg @@ -57,6 +57,9 @@ + + + diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index 22036a8d2d..b0ec3c1882 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -86,11 +86,25 @@ frappe.views.Wiki = class Wiki { if (this.sidebar.find('.standard-sidebar-section')[0]) { this.sidebar.find('.standard-sidebar-section')[0].remove(); } - let sidebar_section = $(`
`); + let sidebar_section = $(`
`); + this.prepare_sidebar(items, sidebar_section, this.sidebar); + } - const get_sidebar_item = function (item) { + prepare_sidebar(items, child_container, item_container) { + items.forEach(item => this.append_item(item, child_container)); + child_container.appendTo(item_container); + } + + append_item(item, container) { + let is_current_page = frappe.router.slug(item.name) == frappe.router.slug(this.get_page_to_show()) || item.name == this.new_page; + if (is_current_page) { + item.selected = true; + this.current_page_name = item.name; + } + + const item_container = function (item) { return $(` -
+ `); }; - const make_sidebar_category_item = item => { - if (item.name == this.get_page_to_show()) { - item.selected = true; - this.current_page_name = item.name; - } + let $item_container = item_container(item); + let sidebar_control = $item_container.find('.sidebar-item-control'); - const get_child_item = function (item) { - return $(` - - `); - }; - - const make_sidebar_child_item = item => { + this.add_sidebar_actions(item, sidebar_control); - if (frappe.router.slug(item.name) == this.get_page_to_show() || item.name == this.new_page) { - child_item_section.classList.toggle("hidden"); - } + let child_items = this.all_pages.filter(page => page.parent_page == item.name); + if (child_items.length > 0) { + let child_container = $(``); + this.prepare_sidebar(child_items, child_container, $item_container); + } - let $child_item = get_child_item(item); - let sidebar_control = $child_item.find('.sidebar-item-control'); - this.add_sidebar_actions(item, sidebar_control); - $child_item.appendTo(child_item_section); - this.sidebar_items[item.name] = $child_item; - }; + $item_container.appendTo(container); + this.sidebar_items[item.name] = $item_container; - let $item = get_sidebar_item(item); - let sidebar_control = $item.find('.sidebar-item-control'); - this.add_sidebar_actions(item, sidebar_control); - let $drop_icon = $(``); - $drop_icon.appendTo(sidebar_control); - let drop_icon = $item.find('.drop-icon').get(0); - let child_item_section = $item.find('.sidebar-child-item').get(0); - if (this.all_pages.some(e => e.parent_page == item.name)) { - drop_icon.classList.remove('hidden'); - drop_icon.addEventListener('click', () => { - child_item_section.classList.toggle("hidden"); - }); - } + if ($item_container.parent().hasClass('hidden') && is_current_page) { + $item_container.parent().toggleClass('hidden'); + } - let child_items = this.all_pages.filter(page => page.parent_page == item.name); - child_items.forEach(item => make_sidebar_child_item(item)); - - $item.appendTo(sidebar_section); - this.sidebar_items[item.name] = $item; - }; - - items.forEach(item => make_sidebar_category_item(item)); - - sidebar_section.appendTo(this.sidebar); + let $drop_icon = $(``); + $drop_icon.appendTo(sidebar_control); + let drop_icon = $item_container.find('.drop-icon').get(0); + let child_item_section = $item_container.find('.sidebar-child-item').get(0); + if (this.all_pages.some(e => e.parent_page == item.name)) { + drop_icon.classList.remove('hidden'); + drop_icon.addEventListener('click', () => { + child_item_section.classList.toggle("hidden"); + let icon = $(drop_icon).find("use").attr("href")==="#icon-small-down" ? "#icon-small-up" : "#icon-small-down"; + $(drop_icon).find("use").attr("href", icon); + }); + } } show() { @@ -275,6 +258,7 @@ frappe.views.Wiki = class Wiki { .then(() => { this.undo = new Undo({ editor: this.editor }); this.undo.initialize({blocks: JSON.parse(this.content)}); + this.undo.readOnly = false; this.setup_customization_buttons(); this.show_sidebar_actions(); this.make_sidebar_sortable(); @@ -334,27 +318,28 @@ frappe.views.Wiki = class Wiki { make_sidebar_sortable() { let me = this; - this.sidebar_sortable = Sortable.create(this.page.sidebar.find(".standard-sidebar-section").get(0), { - handle: ".drag-handle", - draggable: ".standard-sidebar-item-container", - animation: 150, - onEnd: function (evt) { - let new_sb_items = []; - let old_sb_items = me.all_pages.filter(page => page.parent_page == '' || page.parent_page == null); - for (let page of evt.srcElement.childNodes) { - new_sb_items.push({ - name: page.attributes['item-name'].value, - sequence_id: parseInt(page.attributes['item-sequence'].value) - }); - } - me.sorted_sidebar_items = []; - new_sb_items.forEach((old, index) => { - if (old.sequence_id != old_sb_items[index].sequence_id) { - old.sequence_id = old_sb_items[index].sequence_id; - me.sorted_sidebar_items.push(old); + $('.nested-container').each( function() { + new Sortable(this, { + handle: ".drag-handle", + draggable: ".sidebar-item-container", + group: 'nested', + animation: 150, + fallbackOnBody: true, + swapThreshold: 0.65, + onEnd: function (evt) { + me.sorted_sidebar_items = []; + for (let page of $('.standard-sidebar-section').find('.sidebar-item-container')) { + let parent_page = ""; + if (page.closest('.nested-container').classList.contains('sidebar-child-item')) { + parent_page = page.parentElement.parentElement.attributes["item-name"].value; + } + me.sorted_sidebar_items.push({ + name: page.attributes['item-name'].value, + parent_page: parent_page + }); } - }); - } + } + }); }); } @@ -383,11 +368,10 @@ frappe.views.Wiki = class Wiki { () => { this.page.clear_primary_action(); this.page.clear_secondary_action(); + this.undo.readOnly = true; this.save_page(); this.editor.readOnly.toggle(); this.isReadOnly = true; - this.page_sortable.option("disabled", true); - this.sidebar_sortable.option("disabled", true); }, null, __("Saving") @@ -400,8 +384,6 @@ frappe.views.Wiki = class Wiki { this.page.clear_secondary_action(); this.editor.readOnly.toggle(); this.isReadOnly = true; - this.page_sortable.option("disabled", true); - this.sidebar_sortable.option("disabled", true); this.deleted_sidebar_items = []; this.reload(); frappe.show_alert({ message: __("Customizations Discarded"), indicator: "info" }); @@ -413,8 +395,17 @@ frappe.views.Wiki = class Wiki { const d = new frappe.ui.Dialog({ title: __('Set Title'), fields: [ - { label: __('Title'), fieldtype: 'Data', fieldname: 'title'}, - { label: __('Parent'), fieldtype: 'Select', fieldname: 'parent', options: this.all_pages.map(pages => pages.name)} + { + label: __('Title'), + fieldtype: 'Data', + fieldname: 'title' + }, + { + label: __('Parent'), + fieldtype: 'Select', + fieldname: 'parent', + options: this.all_pages.filter(page => !page.parent_page).map(page => page.name) + } ], primary_action_label: __('Create'), primary_action: (values) => { @@ -439,7 +430,6 @@ frappe.views.Wiki = class Wiki { } this.make_sidebar_sortable(); this.make_blocks_sortable(); - this.dirty = false; }); } }); @@ -447,7 +437,6 @@ frappe.views.Wiki = class Wiki { } initialize_editorjs(blocks) { - this.dirty = false; const data = { blocks: blocks || [] }; @@ -456,9 +445,6 @@ frappe.views.Wiki = class Wiki { autofocus: false, data, tunes: ['spacingTune'], - onChange: () => { - this.dirty = true; - }, readOnly: true, logLevel: 'ERROR' }); @@ -516,6 +502,6 @@ frappe.views.Wiki = class Wiki { reload() { this.setup_wiki_pages(); - this.dirty = false; + this.undo.readOnly = true; } }; diff --git a/frappe/public/scss/desk/wiki.scss b/frappe/public/scss/desk/wiki.scss index cb911611d8..e9dcb63c4e 100644 --- a/frappe/public/scss/desk/wiki.scss +++ b/frappe/public/scss/desk/wiki.scss @@ -14,8 +14,11 @@ .standard-sidebar-item { justify-content: space-between; + padding: 0px; .sidebar-item-control { + margin-right: 8px; + > * { align-self: center; margin-left: 3px; @@ -32,6 +35,11 @@ display: none; } + .drop-icon { + padding: 10px 12px 10px 0px; + margin-right: -8px; + } + svg { margin-right: 0; } @@ -44,15 +52,18 @@ .item-anchor { display: flex; overflow: hidden; + padding: 8px 0px 8px 12px; flex: 1; } } - .sidebar-child-item-container { - margin-left: 10px; + .sidebar-item-container { + .sidebar-item-container{ + margin-left: 10px; - .standard-sidebar-item { - justify-content: start; + .standard-sidebar-item { + justify-content: start; + } } } diff --git a/package.json b/package.json index 17f5a7b588..7a54c81149 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@editorjs/list": "^1.6.2", "babel-runtime": "^6.26.0", "chalk": "^2.3.2", - "editorjs-undo": "^0.1.5", + "editorjs-undo": "^0.1.6", "graphlib": "^2.1.8", "less": "^3.11.1", "rollup": "^1.2.2", diff --git a/yarn.lock b/yarn.lock index 8d0b04c622..0c3909dfb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2265,10 +2265,10 @@ "jsbn" "~0.1.0" "safer-buffer" "^2.1.0" -"editorjs-undo@^0.1.5": - "integrity" "sha512-+qRmTe7Asn9KrsYHMCtNQi6rCBa+qrinJx/p7/Hj8K62HFzhMEuy7aMRbADd/KqcV2AsPVzgCj3PMHPmb6ZAkA==" - "resolved" "https://registry.npmjs.org/editorjs-undo/-/editorjs-undo-0.1.5.tgz" - "version" "0.1.5" +"editorjs-undo@^0.1.6": + "integrity" "sha512-zVHPnBf2mcI8hWT9Eu8H3bGDEcMj4gppXbQjJW11Aa8Kdy2SVBGhM6fS59OUlBsm8iHWLxuoG2NUIfy9Rd30sw==" + "resolved" "https://registry.npmjs.org/editorjs-undo/-/editorjs-undo-0.1.6.tgz" + "version" "0.1.6" "ee-first@1.1.1": "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" From b215921a971e3b95ff6f93d63da3ffc70a10766f Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Tue, 25 May 2021 21:44:54 +0530 Subject: [PATCH 167/868] fix: Convert only as_dict and debug values to bool Given the scope of its usage at this point, this becomes a problem when you'd have a field named y,n, true, false and order_by that field, or have the same values for a document name that parent parameter would accept out of all those that Frappe REST allows. --- frappe/api.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frappe/api.py b/frappe/api.py index c69f76a755..6427cbfbd8 100644 --- a/frappe/api.py +++ b/frappe/api.py @@ -119,10 +119,11 @@ def handle(): frappe.local.form_dict.limit or frappe.local.form_dict.limit_page_length or 20, ) - # convert strings to native types - frappe.local.form_dict.update( - {x: sbool(y) for x, y in frappe.local.form_dict.items()} - ) + # convert strings to native types - only as_dict and debug accept bool + for param in ["as_dict", "debug"]: + param_val = frappe.local.form_dict.get(param) + if param_val is not None: + frappe.local.form_dict[param] = sbool(param_val) # evaluate frappe.get_list data = frappe.call(frappe.client.get_list, doctype, **frappe.local.form_dict) From 886d16c87177d4a2954616ae6dcd1799be1db876 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 25 May 2021 19:45:53 +0200 Subject: [PATCH 168/868] feat: add context to confirm dailog --- frappe/public/js/frappe/ui/messages.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index 2e8ba7d206..f465250af9 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -26,13 +26,13 @@ frappe.throw = function(msg) { frappe.confirm = function(message, confirm_action, reject_action) { var d = new frappe.ui.Dialog({ - title: __("Confirm"), - primary_action_label: __("Yes"), + title: __("Confirm", null, "Title of confirmation dialog"), + primary_action_label: __("Yes", null, "Approve confirmation dialog"), primary_action: () => { confirm_action && confirm_action(); d.hide(); }, - secondary_action_label: __("No"), + secondary_action_label: __("No", null, "Dismiss confirmation dialog"), secondary_action: () => d.hide(), }); From d3121d753ead5511ecc6a0e57e6e6825901c68ad Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 25 May 2021 19:47:15 +0200 Subject: [PATCH 169/868] feat: add context to prompt dialog --- frappe/public/js/frappe/ui/messages.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/ui/messages.js b/frappe/public/js/frappe/ui/messages.js index f465250af9..067fed233c 100644 --- a/frappe/public/js/frappe/ui/messages.js +++ b/frappe/public/js/frappe/ui/messages.js @@ -88,9 +88,9 @@ frappe.prompt = function(fields, callback, title, primary_label) { if(!$.isArray(fields)) fields = [fields]; var d = new frappe.ui.Dialog({ fields: fields, - title: title || __("Enter Value"), + title: title || __("Enter Value", null, "Title of prompt dialog"), }); - d.set_primary_action(primary_label || __("Submit"), function() { + d.set_primary_action(primary_label || __("Submit", null, "Primary action of prompt dialog"), function() { var values = d.get_values(); if(!values) { return; From d7d0ddf6adee391714e5b4f31ab559fe61c322c5 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 26 May 2021 02:54:04 +0000 Subject: [PATCH 170/868] fix: package.json & yarn.lock to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-NORMALIZEURL-1296539 --- package.json | 2 +- yarn.lock | 1022 ++++++++++++++++++++------------------------------ 2 files changed, 418 insertions(+), 606 deletions(-) diff --git a/package.json b/package.json index e666a2e1ce..25bf0b0695 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "bootstrap": "4.5.0", "cliui": "^7.0.4", "cookie": "^0.4.0", - "cssnano": "^4.1.10", + "cssnano": "^5.0.0", "driver.js": "^0.9.8", "express": "^4.17.1", "fast-deep-equal": "^2.0.1", diff --git a/yarn.lock b/yarn.lock index 86719d81f4..96a6059ecc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,27 @@ resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.10.1.tgz#70e45678f06c72fa2e350e8553ec4a4d72b92e06" integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg== +"@babel/code-frame@^7.0.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" + integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== + dependencies: + "@babel/highlight" "^7.12.13" + +"@babel/helper-validator-identifier@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" + integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== + +"@babel/highlight@^7.12.13": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf" + integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg== + dependencies: + "@babel/helper-validator-identifier" "^7.14.0" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@deepcode/dcignore@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@deepcode/dcignore/-/dcignore-1.0.2.tgz#39e4a3df7dde8811925330506e4bb3fbf3c288d8" @@ -361,6 +382,11 @@ dependencies: defer-to-connect "^2.0.0" +"@trysound/sax@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669" + integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow== + "@types/babel-types@*", "@types/babel-types@^7.0.0": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.9.tgz#01d7b86949f455402a94c788883fe4ba574cad41" @@ -463,10 +489,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.4.tgz#76c3cb3a12909510f52e5dc04a6298cdf9504ffd" integrity sha512-oVeL12C6gQS/GAExndigSaLxTrKpQPxewx9bOcwfvJiJge4rr7wNaph4J+ns5hrmIV2as5qxqN8YKthn9qh0jw== -"@types/q@^1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" - integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" @@ -595,7 +621,7 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" -alphanum-sort@^1.0.0: +alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= @@ -958,7 +984,7 @@ body-parser@1.19.0: raw-body "2.4.0" type-is "~1.6.17" -boolbase@^1.0.0, boolbase@~1.0.0: +boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= @@ -1009,7 +1035,7 @@ browserify-zlib@^0.1.4: dependencies: pako "~0.2.0" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.3: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.0, browserslist@^4.16.3: version "4.16.6" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== @@ -1077,24 +1103,10 @@ call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase-keys@^2.0.0: version "2.1.0" @@ -1166,7 +1178,7 @@ chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1313,21 +1325,12 @@ clone@^2.1.1, clone@^2.1.2: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -color-convert@^1.9.0, color-convert@^1.9.1: +color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -1346,26 +1349,15 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0, color-name@~1.1.4: +color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.0.tgz#d8e9fb096732875774c84bf922815df0308d0ffc" - integrity sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" +colord@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.0.0.tgz#f8c19f2526b7dc5b22d6e57ef102f03a2a43a3d8" + integrity sha512-WMDFJfoY3wqPZNpKUFdse3HhD5BHCbE9JCdxRzoVH+ywRITGOeWAHNkGEmyxLlErEpN9OLMWgdM9dWQtDk5dog== colorette@^1.2.1, colorette@^1.2.2: version "1.2.2" @@ -1379,6 +1371,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" @@ -1492,16 +1489,16 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.1.0.tgz#6c5c35e97f37f985061cdf653f114784231185cf" - integrity sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q== +cosmiconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" + integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.9.0" - lodash.get "^4.4.2" - parse-json "^4.0.0" + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" cross-spawn@^3.0.0: version "3.0.1" @@ -1532,17 +1529,21 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-color-names@0.0.4, css-color-names@^0.0.4: +css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== +css-color-names@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-1.0.1.tgz#6ff7ee81a823ad46e020fa2fd6ab40a887e2ba67" + integrity sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA== + +css-declaration-sorter@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.0.3.tgz#9dfd8ea0df4cc7846827876fafb52314890c21a9" + integrity sha512-52P95mvW1SMzuRZegvpluT6yEv0FqQusydKQPZsNN5Q7hh8EwQvN8E2nwuJ16BBvNN6LcoIZXu/Bk58DAhrrxw== dependencies: - postcss "^7.0.1" timsort "^0.3.0" css-parse@~2.0.0: @@ -1552,20 +1553,16 @@ css-parse@~2.0.0: dependencies: css "^2.0.0" -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== +css-select@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-3.1.2.tgz#d52cbdc6fee379fba97fb0d3925abbd18af2d9d8" + integrity sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA== dependencies: boolbase "^1.0.0" - css-what "^2.1.2" - domutils "^1.7.0" - nth-check "^1.0.2" + css-what "^4.0.0" + domhandler "^4.0.0" + domutils "^2.4.3" + nth-check "^2.0.0" css-selector-tokenizer@^0.7.0: version "0.7.1" @@ -1576,36 +1573,18 @@ css-selector-tokenizer@^0.7.0: fastparse "^1.1.1" regexpu-core "^1.0.0" -css-tree@1.0.0-alpha.28: - version "1.0.0-alpha.28" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" - integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== +css-tree@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" + mdn-data "2.0.14" + source-map "^0.6.1" -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= - -css-url-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= - -css-what@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== +css-what@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233" + integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A== css@^2.0.0: version "2.2.4" @@ -1622,90 +1601,66 @@ cssesc@^0.1.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q= -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== - cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-default@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== +cssnano-preset-default@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.1.tgz#5cd783caed942cc94159aeb10583af4691445b8c" + integrity sha512-kAhR71Tascmnjlhl4UegGA3KGGbMLXHkkqVpA9idsRT1JmIhIsz1C3tDpBeQMUw5EX5Rfb1HGc/PRqD2AFk3Vg== dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.2" - postcss-unique-selectors "^4.0.1" + css-declaration-sorter "^6.0.3" + cssnano-utils "^2.0.1" + postcss-calc "^8.0.0" + postcss-colormin "^5.1.1" + postcss-convert-values "^5.0.1" + postcss-discard-comments "^5.0.1" + postcss-discard-duplicates "^5.0.1" + postcss-discard-empty "^5.0.1" + postcss-discard-overridden "^5.0.1" + postcss-merge-longhand "^5.0.2" + postcss-merge-rules "^5.0.1" + postcss-minify-font-values "^5.0.1" + postcss-minify-gradients "^5.0.1" + postcss-minify-params "^5.0.1" + postcss-minify-selectors "^5.1.0" + postcss-normalize-charset "^5.0.1" + postcss-normalize-display-values "^5.0.1" + postcss-normalize-positions "^5.0.1" + postcss-normalize-repeat-style "^5.0.1" + postcss-normalize-string "^5.0.1" + postcss-normalize-timing-functions "^5.0.1" + postcss-normalize-unicode "^5.0.1" + postcss-normalize-url "^5.0.1" + postcss-normalize-whitespace "^5.0.1" + postcss-ordered-values "^5.0.1" + postcss-reduce-initial "^5.0.1" + postcss-reduce-transforms "^5.0.1" + postcss-svgo "^5.0.1" + postcss-unique-selectors "^5.0.1" -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= +cssnano-utils@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.1.tgz#8660aa2b37ed869d2e2f22918196a9a8b6498ce2" + integrity sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ== -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== +cssnano@^5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.4.tgz#5ca90729c94c71c4bc3d45abb543be10740bf381" + integrity sha512-I+fDW74CJ4yb31765ov9xXe70XLZvFTXjwhmA//VgAAuSAU34Oblbe94Q9zffiCX1VhcSfQWARQnwhz+Nqgb4Q== dependencies: - postcss "^7.0.0" + cosmiconfig "^7.0.0" + cssnano-preset-default "^5.1.1" + is-resolvable "^1.1.0" -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.10" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== +csso@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" + integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.7" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== - dependencies: - css-tree "1.0.0-alpha.29" + css-tree "^1.1.2" currently-unhandled@^0.4.1: version "0.4.1" @@ -1928,33 +1883,35 @@ doctypes@^1.1.0: resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= -dom-serializer@0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== +dom-serializer@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" + integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" -domelementtype@1, domelementtype@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== -domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" + integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== dependencies: - dom-serializer "0" - domelementtype "1" + domelementtype "^2.2.0" -dot-prop@^4.1.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" - integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== +domutils@^2.4.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7" + integrity sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA== dependencies: - is-obj "^1.0.0" + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" dot-prop@^5.2.0: version "5.2.0" @@ -2102,10 +2059,10 @@ engine.io@~3.5.0: engine.io-parser "~2.2.0" ws "~7.4.2" -entities@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== errno@^0.1.1: version "0.1.7" @@ -2121,18 +2078,6 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.12.0, es-abstract@^1.5.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - es-abstract@^1.17.0-next.1, es-abstract@^1.17.4, es-abstract@^1.17.5: version "1.17.5" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" @@ -2163,15 +2108,6 @@ es-get-iterator@^1.1.0: is-string "^1.0.5" isarray "^2.0.5" -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -2914,7 +2850,7 @@ has-yarn@^2.1.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== -has@^1.0.0, has@^1.0.1, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -2993,11 +2929,6 @@ hsla-regex@^1.0.0: resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - http-cache-semantics@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -3084,13 +3015,13 @@ immediate@~3.0.5: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" + parent-module "^1.0.0" + resolve-from "^4.0.0" import-lazy@^2.1.0: version "2.1.0" @@ -3162,10 +3093,10 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== is-arguments@^1.0.4: version "1.0.4" @@ -3177,11 +3108,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - is-bigint@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" @@ -3221,7 +3147,7 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-color-stop@^1.0.0: +is-color-stop@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= @@ -3255,11 +3181,6 @@ is-deflate@^1.0.0: resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14" integrity sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ= -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - is-docker@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" @@ -3350,11 +3271,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" @@ -3378,13 +3294,6 @@ is-regex@^1.0.3: call-bind "^1.0.2" has-symbols "^1.0.1" -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - is-regex@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" @@ -3392,7 +3301,7 @@ is-regex@^1.0.5: dependencies: has-symbols "^1.0.1" -is-resolvable@^1.0.0: +is-resolvable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== @@ -3412,13 +3321,6 @@ is-string@^1.0.4, is-string@^1.0.5: resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" @@ -3543,7 +3445,12 @@ js-stringify@^1.0.1: resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= -js-yaml@^3.12.0, js-yaml@^3.13.1, js-yaml@^3.9.0: +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -3576,10 +3483,10 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" @@ -3740,6 +3647,11 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -4129,10 +4041,10 @@ md5@^2.3.0: crypt "0.0.2" is-buffer "~1.1.6" -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== media-typer@0.3.0: version "0.3.0" @@ -4248,11 +4160,6 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - minimist@^1.1.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -4290,13 +4197,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - moment-timezone@^0.5.28: version "0.5.28" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.28.tgz#f093d789d091ed7b055d82aa81a82467f72e4338" @@ -4505,16 +4405,16 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - normalize-url@^4.1.0: version "4.5.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== +normalize-url@^4.5.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -4532,12 +4432,12 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== +nth-check@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.0.tgz#1bb4f6dac70072fc313e8c9cd1417b5074c0a125" + integrity sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q== dependencies: - boolbase "~1.0.0" + boolbase "^1.0.0" num2fraction@^1.2.2: version "1.2.2" @@ -4597,24 +4497,6 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.12.0" - function-bind "^1.1.1" - has "^1.0.3" - omggif@^1.0.5: version "1.0.10" resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" @@ -4765,6 +4647,13 @@ parchment@^1.1.4: resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5" integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-data-uri@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/parse-data-uri/-/parse-data-uri-0.2.0.tgz#bf04d851dd5c87b0ab238e5d01ace494b604b4c9" @@ -4779,13 +4668,15 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: + "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" parse-link-header@^1.0.1: version "1.0.1" @@ -4860,6 +4751,11 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + peek-stream@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67" @@ -4938,124 +4834,104 @@ popper.js@^1.16.0: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== -postcss-calc@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" - integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== +postcss-calc@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a" + integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g== dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.5" - postcss-selector-parser "^5.0.0-rc.4" - postcss-value-parser "^3.3.1" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== +postcss-colormin@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.1.1.tgz#834d262f6021f832d9085e355f08ade288a92a1d" + integrity sha512-SyTmqKKN6PyYNeeKEC0hqIP5CDuprO1hHurdW1aezDyfofDUOn7y7MaxcolbsW3oazPwFiGiY30XRiW1V4iZpA== dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + browserslist "^4.16.0" + colord "^2.0.0" + postcss-value-parser "^4.1.0" -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== +postcss-convert-values@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz#4ec19d6016534e30e3102fdf414e753398645232" + integrity sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" +postcss-discard-comments@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz#9eae4b747cf760d31f2447c27f0619d5718901fe" + integrity sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg== -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" +postcss-discard-duplicates@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz#68f7cc6458fe6bab2e46c9f55ae52869f680e66d" + integrity sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA== -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" +postcss-discard-empty@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz#ee136c39e27d5d2ed4da0ee5ed02bc8a9f8bf6d8" + integrity sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw== -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" +postcss-discard-overridden@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz#454b41f707300b98109a75005ca4ab0ff2743ac6" + integrity sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q== -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== +postcss-merge-longhand@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz#277ada51d9a7958e8ef8cf263103c9384b322a41" + integrity sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw== dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" + css-color-names "^1.0.1" + postcss-value-parser "^4.1.0" + stylehacks "^5.0.1" -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== +postcss-merge-rules@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.1.tgz#4ff61c5089d86845184a0f149e88d687028bef7e" + integrity sha512-UR6R5Ph0c96QB9TMBH3ml8/kvPCThPHepdhRqAbvMRDRHQACPC8iM5NpfIC03+VRMZTGXy4L/BvFzcDFCgb+fA== dependencies: - browserslist "^4.0.0" + browserslist "^4.16.0" caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" + cssnano-utils "^2.0.1" + postcss-selector-parser "^6.0.5" + vendors "^1.0.3" -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== +postcss-minify-font-values@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz#a90cefbfdaa075bd3dbaa1b33588bb4dc268addf" + integrity sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== +postcss-minify-gradients@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.1.tgz#2dc79fd1a1afcb72a9e727bc549ce860f93565d2" + integrity sha512-odOwBFAIn2wIv+XYRpoN2hUV3pPQlgbJ10XeXPq8UY2N+9ZG42xu45lTn/g9zZ+d70NKSQD6EOi6UiCMu3FN7g== dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + is-color-stop "^1.1.0" + postcss-value-parser "^4.1.0" -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== +postcss-minify-params@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz#371153ba164b9d8562842fdcd929c98abd9e5b6c" + integrity sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw== dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + alphanum-sort "^1.0.2" + browserslist "^4.16.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" uniqs "^2.0.0" -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== +postcss-minify-selectors@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz#4385c845d3979ff160291774523ffa54eafd5a54" + integrity sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og== dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" + alphanum-sort "^1.0.2" + postcss-selector-parser "^6.0.5" postcss-modules-extract-imports@^3.0.0: version "3.0.0" @@ -5127,133 +5003,96 @@ postcss-modules@^4.0.0: postcss-modules-values "^4.0.0" string-hash "^1.1.1" -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" +postcss-normalize-charset@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz#121559d1bebc55ac8d24af37f67bd4da9efd91d0" + integrity sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg== -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== +postcss-normalize-display-values@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz#62650b965981a955dffee83363453db82f6ad1fd" + integrity sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ== dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== +postcss-normalize-positions@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz#868f6af1795fdfa86fbbe960dceb47e5f9492fe5" + integrity sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg== dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== +postcss-normalize-repeat-style@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz#cbc0de1383b57f5bb61ddd6a84653b5e8665b2b5" + integrity sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w== dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== +postcss-normalize-string@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz#d9eafaa4df78c7a3b973ae346ef0e47c554985b0" + integrity sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA== dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== +postcss-normalize-timing-functions@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz#8ee41103b9130429c6cbba736932b75c5e2cb08c" + integrity sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q== dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== +postcss-normalize-unicode@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz#82d672d648a411814aa5bf3ae565379ccd9f5e37" + integrity sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA== dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + browserslist "^4.16.0" + postcss-value-parser "^4.1.0" -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== +postcss-normalize-url@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.1.tgz#ffa9fe545935d8b57becbbb7934dd5e245513183" + integrity sha512-hkbG0j58Z1M830/CJ73VsP7gvlG1yF+4y7Fd1w4tD2c7CaA2Psll+pQ6eQhth9y9EaqZSLzamff/D0MZBMbYSg== dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + is-absolute-url "^3.0.3" + normalize-url "^4.5.0" + postcss-value-parser "^4.1.0" -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== +postcss-normalize-whitespace@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz#b0b40b5bcac83585ff07ead2daf2dcfbeeef8e9a" + integrity sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA== dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + postcss-value-parser "^4.1.0" -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== +postcss-ordered-values@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.1.tgz#79ef6e2bd267ccad3fc0c4f4a586dfd01c131f64" + integrity sha512-6mkCF5BQ25HvEcDfrMHCLLFHlraBSlOXFnQMHYhSpDO/5jSR1k8LdEXOkv+7+uzW6o6tBYea1Km0wQSRkPJkwA== dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== +postcss-reduce-initial@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz#9d6369865b0f6f6f6b165a0ef5dc1a4856c7e946" + integrity sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw== dependencies: - browserslist "^4.0.0" + browserslist "^4.16.0" caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== +postcss-reduce-transforms@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz#93c12f6a159474aa711d5269923e2383cedcf640" + integrity sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA== dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-selector-parser@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= - dependencies: - dot-prop "^4.1.1" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" + cssnano-utils "^2.0.1" + postcss-value-parser "^4.1.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.4" @@ -5265,31 +5104,32 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: uniq "^1.0.1" util-deprecate "^1.0.2" -postcss-svgo@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== +postcss-selector-parser@^6.0.5: + version "6.0.6" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" + integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" + cssesc "^3.0.0" + util-deprecate "^1.0.2" -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== +postcss-svgo@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.1.tgz#6ed5e01e164e59204978994d844c653a331a8100" + integrity sha512-cD7DFo6tF9i5eWvwtI4irKOHCpmASFS0xvZ5EQIgEdA1AWfM/XiHHY/iss0gcKHhkqwgYmuo2M0KhJLd5Us6mg== dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" + postcss-value-parser "^4.1.0" + svgo "^2.3.0" + +postcss-unique-selectors@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz#3be5c1d7363352eff838bd62b0b07a0abad43bfc" + integrity sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w== + dependencies: + alphanum-sort "^1.0.2" + postcss-selector-parser "^6.0.5" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - -postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== @@ -5322,7 +5162,7 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^5.4.0" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.5: +postcss@^7.0.14: version "7.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== @@ -5554,11 +5394,6 @@ pupa@^2.0.1: dependencies: escape-goat "^2.0.0" -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - qs@6.7.0, qs@^6.5.1: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -5924,10 +5759,10 @@ resolve-file@^0.3.0: lazy-cache "^2.0.2" resolve "^1.2.0" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-url@^0.2.1: version "0.2.1" @@ -6217,13 +6052,6 @@ signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - snyk-config@4.0.0, snyk-config@^4.0.0-rc.2: version "4.0.0" resolved "https://registry.yarnpkg.com/snyk-config/-/snyk-config-4.0.0.tgz#21d459f19087991246cc07a7ffb4501dce6f4159" @@ -6677,7 +6505,7 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: +source-map@^0.5.6, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -6935,14 +6763,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== +stylehacks@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.1.tgz#323ec554198520986806388c7fdaebc38d2c06fb" + integrity sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA== dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" + browserslist "^4.16.0" + postcss-selector-parser "^6.0.4" stylus@^0.54.5, stylus@^0.x: version "0.54.8" @@ -7007,25 +6834,18 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -svgo@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.0.tgz#305a8fc0f4f9710828c65039bb93d5793225ffc3" - integrity sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw== +svgo@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.3.0.tgz#6b3af81d0cbd1e19c83f5f63cec2cb98c70b5373" + integrity sha512-fz4IKjNO6HDPgIQxu4IxwtubtbSfGEAJUq/IXyTPIkGhWck/faiiwfkvsB8LnBkKLvSoyNNIY6d13lZprJMc9Q== dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.28" - css-url-regex "^1.1.0" - csso "^3.5.1" - js-yaml "^3.12.0" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" + "@trysound/sax" "0.1.1" + chalk "^4.1.0" + commander "^7.1.0" + css-select "^3.1.2" + css-tree "^1.1.2" + csso "^4.2.0" stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" tar-stream@^2.1.0: version "2.1.0" @@ -7332,11 +7152,6 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - update-notifier@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.1.tgz#895fc8562bbe666179500f9f2cebac4f26323746" @@ -7390,14 +7205,6 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -7436,10 +7243,10 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -vendors@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" - integrity sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ== +vendors@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== verror@1.10.0: version "1.10.0" @@ -7672,6 +7479,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yaml@^1.9.2: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" From 8764134309907f8c89336a90b1edb51ef1b23dff Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 26 May 2021 10:02:12 +0530 Subject: [PATCH 171/868] ci: Run mariadb tests after PR merge for coverage badge --- .github/workflows/server-mariadb-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/server-mariadb-tests.yml b/.github/workflows/server-mariadb-tests.yml index 1742e813c6..1c7655528c 100644 --- a/.github/workflows/server-mariadb-tests.yml +++ b/.github/workflows/server-mariadb-tests.yml @@ -3,6 +3,8 @@ name: Server on: pull_request: workflow_dispatch: + push: + branches: [ develop ] jobs: test: From b0f1bbc37812daa2f4212401374e8317b200750c Mon Sep 17 00:00:00 2001 From: Akshay Kumar Tripathi <50769001+AkshayKumarTripathi@users.noreply.github.com> Date: Wed, 26 May 2021 10:37:50 +0530 Subject: [PATCH 172/868] fix: corrected the function get_url (#13330) * Removed /Form from the function get_url As per issue #12820, I think /Form was causing a problem so I removed it. Now the get_url returns URL in the format: "app/doctype/name". * fix: Change to f-strings * Implement slug on get_url * Removed slug for names --- frappe/model/document.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frappe/model/document.py b/frappe/model/document.py index 623916597e..a3f8ad0cfa 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -17,6 +17,7 @@ from frappe.model.workflow import set_workflow_state_on_action from frappe.utils.global_search import update_global_search from frappe.integrations.doctype.webhook import run_webhooks from frappe.desk.form.document_follow import follow_document +from frappe.desk.utils import slug from frappe.core.doctype.server_script.server_script_utils import run_server_script_for_doc_event # once_only validation @@ -1202,8 +1203,8 @@ class Document(BaseDocument): doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.parentfield))) def get_url(self): - """Returns Desk URL for this document. `/app/Form/{doctype}/{name}`""" - return "/app/Form/{doctype}/{name}".format(doctype=self.doctype, name=self.name) + """Returns Desk URL for this document. `/app/{doctype}/{name}`""" + return f"/app/{slug(self.doctype)}/{self.name}" def add_comment(self, comment_type='Comment', text=None, comment_email=None, link_doctype=None, link_name=None, comment_by=None): """Add a comment to this document. From 646612be09439eed5d05a3d66ac081553f139733 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 26 May 2021 10:40:16 +0530 Subject: [PATCH 173/868] fix: Colocated asset load --- frappe/templates/test/_test_base.html | 13 ++++++++++++- frappe/website/doctype/web_page/test_web_page.py | 15 ++++++--------- frappe/website/page_renderers/template_page.py | 6 ++++-- frappe/www/_test/_test_folder/_test_page.css | 3 +++ frappe/www/_test/_test_folder/_test_page.js | 1 + 5 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 frappe/www/_test/_test_folder/_test_page.css create mode 100644 frappe/www/_test/_test_folder/_test_page.js diff --git a/frappe/templates/test/_test_base.html b/frappe/templates/test/_test_base.html index a0b1a83c97..5a88584a5d 100644 --- a/frappe/templates/test/_test_base.html +++ b/frappe/templates/test/_test_base.html @@ -1,8 +1,19 @@ - + + {%- block style %} + {% if colocated_css -%} + + {%- endif %} + {%- endblock -%} +

This is for testing

{% block content %}{% endblock %} + {%- block script %} + {% if colocated_js -%} + + {%- endif %} + {%- endblock %} diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index b9bd425781..b5da51cca6 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -104,18 +104,15 @@ class TestWebPage(unittest.TestCase): self.assertTrue('Next: Test Toc' \ in frappe.as_unicode(content)) - def test_meta_tags(self): - pass + def test_colocated_assets(self): + content = get_response_content('/_test/_test_folder/_test_page') + self.assertTrue("" \ + in frappe.as_unicode(content)) + self.assertTrue("background-color: var(--bg-color);" \ + in frappe.as_unicode(content)) def test_breadcrumbs(self): pass def test_downloadable_file(self): pass - - - - -# breadcrumb -# validate -# page context caching diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index d8032c6b9c..682c3cda39 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -42,6 +42,7 @@ class TemplatePage(BaseTemplatePage): if os.path.exists(file_path) and not os.path.isdir(file_path): self.app = app self.app_path = app_path + self.basename = os.path.splitext(file_path)[0] self.template_path = os.path.relpath(file_path, self.app_path) self.basepath = os.path.dirname(file_path) return @@ -110,6 +111,7 @@ class TemplatePage(BaseTemplatePage): def update_context(self): self.context.base_template = self.context.base_template or get_base_template(self.path) self.context.basepath = self.basepath + self.context.basename = self.basename self.context.path = self.path self.set_page_properties() self.set_properties_from_source() @@ -197,11 +199,11 @@ class TemplatePage(BaseTemplatePage): def load_colocated_files(self): '''load co-located css/js files with the same name''' - js_path = self.basepath + '.js' + js_path = self.basename + '.js' if os.path.exists(js_path) and '{% block script %}' not in self.source: self.context.colocated_js = self.get_colocated_file(js_path) - css_path = self.basepath + '.css' + css_path = self.basename + '.css' if os.path.exists(css_path) and '{% block style %}' not in self.source: self.context.colocated_css = self.get_colocated_file(css_path) diff --git a/frappe/www/_test/_test_folder/_test_page.css b/frappe/www/_test/_test_folder/_test_page.css new file mode 100644 index 0000000000..e42b809085 --- /dev/null +++ b/frappe/www/_test/_test_folder/_test_page.css @@ -0,0 +1,3 @@ +body { + background-color: var(--bg-color); +} \ No newline at end of file diff --git a/frappe/www/_test/_test_folder/_test_page.js b/frappe/www/_test/_test_folder/_test_page.js new file mode 100644 index 0000000000..6e0c1f3a87 --- /dev/null +++ b/frappe/www/_test/_test_folder/_test_page.js @@ -0,0 +1 @@ +console.log('test data'); \ No newline at end of file From 40bd818c0b6e29c3b682db45fe083d1abd60d42c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 26 May 2021 10:40:43 +0530 Subject: [PATCH 174/868] test: Add attributes via frontmatter --- frappe/www/_test/_test_folder/_test_toc.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frappe/www/_test/_test_folder/_test_toc.md b/frappe/www/_test/_test_folder/_test_toc.md index 8d05b120a5..02cc3c82be 100644 --- a/frappe/www/_test/_test_folder/_test_toc.md +++ b/frappe/www/_test/_test_folder/_test_toc.md @@ -1,3 +1,13 @@ +--- +title: Test TOC +add_breadcrumbs: 1 +show_sidebar: 0 + +metatags: + description: Test Description. + keywords: Frappe Framework. +--- + # Level 1 ## Level 1.1 From e19c18e5a9840ed68c4c29ccf5ecb09df03af137 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 26 May 2021 11:03:33 +0530 Subject: [PATCH 175/868] refactor: Move context value setting code to a separate function --- frappe/website/page_renderers/template_page.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index 682c3cda39..2b326d7383 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -45,6 +45,8 @@ class TemplatePage(BaseTemplatePage): self.basename = os.path.splitext(file_path)[0] self.template_path = os.path.relpath(file_path, self.app_path) self.basepath = os.path.dirname(file_path) + self.filename = os.path.basename(file_path) + self.name = os.path.splitext(self.filename)[0] return def can_render(self): @@ -109,10 +111,6 @@ class TemplatePage(BaseTemplatePage): self.convert_from_markdown() def update_context(self): - self.context.base_template = self.context.base_template or get_base_template(self.path) - self.context.basepath = self.basepath - self.context.basename = self.basename - self.context.path = self.path self.set_page_properties() self.set_properties_from_source() self.load_colocated_files() @@ -138,8 +136,15 @@ class TemplatePage(BaseTemplatePage): self.context[prop] = getattr(self.pymodule, prop) def set_page_properties(self): + self.context.base_template = self.context.base_template \ + or get_base_template(self.path) \ + or 'templates/web.html' + self.context.basepath = self.basepath + self.context.basename = self.basename + self.context.name = self.name + self.context.path = self.path + self.context.route = self.path self.context.template = self.template_path - self.context.base_template = self.context.base_template or 'templates/web.html' def set_properties_from_source(self): if not self.source: From 38fdfc369a1a1dd0b22bda2f2eb03e10543e2b6a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 26 May 2021 11:51:12 +0530 Subject: [PATCH 176/868] test: Use assertIn for better error message --- .../website/doctype/web_page/test_web_page.py | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index b5da51cca6..d213fd57a8 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -28,10 +28,10 @@ class TestWebPage(unittest.TestCase): content = get_page_content('/_test/_test_custom_base.html') # assert the text in base template is rendered - self.assertTrue('

This is for testing

' in frappe.as_unicode(content)) + self.assertIn('

This is for testing

', frappe.as_unicode(content)) # assert template block rendered - self.assertTrue('

Test content

' in frappe.as_unicode(content)) + self.assertIn('

Test content

', frappe.as_unicode(content)) def test_content_type(self): web_page = frappe.get_doc(dict( @@ -44,15 +44,15 @@ class TestWebPage(unittest.TestCase): main_section_html = '
html content
' )).insert() - self.assertTrue('rich text' in get_page_content('/test-content-type')) + self.assertIn('rich text', get_page_content('/test-content-type')) web_page.content_type = 'Markdown' web_page.save() - self.assertTrue('markdown content' in get_page_content('/test-content-type')) + self.assertIn('markdown content', get_page_content('/test-content-type')) web_page.content_type = 'HTML' web_page.save() - self.assertTrue('html content' in get_page_content('/test-content-type')) + self.assertIn('html content', get_page_content('/test-content-type')) web_page.delete() @@ -70,46 +70,47 @@ class TestWebPage(unittest.TestCase): try: content = get_page_content('/doctype-view/DocField') - self.assertTrue('
DocField
' in content) + self.assertIn('
DocField
', content) finally: web_page.delete() def test_custom_base_template_path(self): content = get_response_content('/_test/_test_folder/_test_page') # assert the text in base template is rendered - self.assertTrue('

This is for testing

' in frappe.as_unicode(content)) + self.assertIn('

This is for testing

', frappe.as_unicode(content)) # assert template block rendered - self.assertTrue('

Test content

' in frappe.as_unicode(content)) + self.assertIn('

Test content

', frappe.as_unicode(content)) def test_json_sidebar_data(self): frappe.flags.look_for_sidebar = False content = get_response_content('/_test/_test_folder/_test_page') - self.assertTrue('Test Sidebar' not in frappe.as_unicode(content)) + self.assertNotIn('Test Sidebar', frappe.as_unicode(content)) frappe.flags.look_for_sidebar = True content = get_response_content('/_test/_test_folder/_test_page') - self.assertTrue('Test Sidebar' in frappe.as_unicode(content)) + self.assertIn('Test Sidebar', frappe.as_unicode(content)) frappe.flags.look_for_sidebar = False def test_index_and_next_comment(self): content = get_response_content('/_test/_test_folder') # test if {index} was rendered - self.assertTrue(' Test Page' \ - in frappe.as_unicode(content)) - self.assertTrue(' Test Toc' \ - in frappe.as_unicode(content)) + self.assertIn(' Test Page', + frappe.as_unicode(content)) + + self.assertIn('Test TOC', + frappe.as_unicode(content)) content = get_response_content('/_test/_test_folder/_test_page') # test if {next} was rendered - self.assertTrue('Next: Test Toc' \ - in frappe.as_unicode(content)) + self.assertIn('Next: Test TOC', + frappe.as_unicode(content)) def test_colocated_assets(self): content = get_response_content('/_test/_test_folder/_test_page') - self.assertTrue("" \ - in frappe.as_unicode(content)) - self.assertTrue("background-color: var(--bg-color);" \ - in frappe.as_unicode(content)) + self.assertIn("", + frappe.as_unicode(content)) + self.assertIn("background-color: var(--bg-color);", + frappe.as_unicode(content)) def test_breadcrumbs(self): pass From 33a97196e141e42bf99116f336fe8f65c7672a30 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 26 May 2021 11:51:34 +0530 Subject: [PATCH 177/868] fix: Init page properties in webpage --- frappe/website/page_renderers/web_page.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frappe/website/page_renderers/web_page.py b/frappe/website/page_renderers/web_page.py index 5c3807c0ee..6e738e8df9 100644 --- a/frappe/website/page_renderers/web_page.py +++ b/frappe/website/page_renderers/web_page.py @@ -8,6 +8,9 @@ class WebPage(object): path = frappe.local.request.path self.path = path.strip('/ ') self.basepath = '' + self.basename = '' + self.name = '' + self.route = '' def can_render(self): pass From e8cf96d1d3718a874fabed676f07be20703c7876 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 13:21:37 +0530 Subject: [PATCH 178/868] fix: Replace cmp with different logic cmp was being used from past.builtins library since it was deprecated in PY2. It's hard to understand behaviour of their usages, so this is an attempt to replicate behaviour with simpler logic, making this more readable. Also, removed usages of iteritems and string_types, compatibility imports --- frappe/__init__.py | 1 - frappe/contacts/doctype/address/address.py | 17 +++++++---------- frappe/contacts/doctype/contact/contact.py | 15 +++++++-------- frappe/website/utils.py | 9 ++------- 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 9b208f7c2d..c915ce70a0 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -21,7 +21,6 @@ if _dev_server: from werkzeug.local import Local, release_local import sys, importlib, inspect, json import typing -from past.builtins import cmp import click # Local application imports diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index 84b925d50e..9aced0dacb 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import throw, _ @@ -10,15 +9,10 @@ from frappe.utils import cstr from frappe.model.document import Document 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, string_types -from past.builtins import cmp from frappe.contacts.address_and_contact import set_link_title -import functools - class Address(Document): def __setup__(self): @@ -112,10 +106,13 @@ def get_default_address(doctype, name, sort_key='is_primary_address'): WHERE dl.parent = addr.name and dl.link_doctype = %s and dl.link_name = %s and ifnull(addr.disabled, 0) = 0 - """ %(sort_key, '%s', '%s'), (doctype, name)) + """ %(sort_key, '%s', '%s'), (doctype, name), as_dict=True) if out: - return sorted(out, key = functools.cmp_to_key(lambda x,y: cmp(y[1], x[1])))[0][0] + for contact in out: + if contact.get(sort_key): + return contact.parent + return out[0].parent else: return None @@ -141,7 +138,7 @@ def get_territory_from_address(address): if not address: return - if isinstance(address, string_types): + if isinstance(address, str): address = frappe.get_cached_doc("Address", address) territory = None @@ -214,7 +211,7 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): condition = "" meta = frappe.get_meta("Address") - for fieldname, value in iteritems(filters): + for fieldname, value in filters.items(): if meta.get_field(fieldname) or fieldname in frappe.db.DEFAULT_COLUMNS: condition += " and {field}={value}".format( field=fieldname, diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index b3d4c6fc5c..c8af99bebc 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -1,18 +1,14 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe -from frappe.utils import cstr, has_gravatar, cint +from frappe.utils import cstr, has_gravatar from frappe import _ from frappe.model.document import Document from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links -from six import iteritems -from past.builtins import cmp from frappe.model.naming import append_number_if_name_exists from frappe.contacts.address_and_contact import set_link_title -import functools class Contact(Document): def autoname(self): @@ -120,7 +116,7 @@ class Contact(Document): if len(is_primary) > 1: frappe.throw(_("Only one {0} can be set as primary.").format(frappe.bold(frappe.unscrub(fieldname)))) - primary_number_exists = False + primary_number_exists = False for d in self.phone_nos: if d.get(field_name) == 1: primary_number_exists = True @@ -140,10 +136,13 @@ def get_default_contact(doctype, name): where dl.link_doctype=%s and dl.link_name=%s and - dl.parenttype = "Contact"''', (doctype, name)) + dl.parenttype = "Contact"''', (doctype, name), as_dict=True) if out: - return sorted(out, key = functools.cmp_to_key(lambda x,y: cmp(cint(y[1]), cint(x[1]))))[0][0] + for contact in out: + if contact.is_primary_contact: + return contact.parent + return out[0].parent else: return None diff --git a/frappe/website/utils.py b/frappe/website/utils.py index efa15bdb14..0738c836f3 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -1,14 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals -import functools import re import os import frappe -from six import iteritems -from past.builtins import cmp from frappe.utils import md_to_html @@ -293,7 +289,7 @@ def get_full_index(route=None, app=None): pages = get_pages(app=app) # make children map - for route, page_info in iteritems(pages): + for route, page_info in pages.items(): parent_route = os.path.dirname(route) if parent_route not in added: children_map.setdefault(parent_route, []).append(page_info) @@ -316,8 +312,7 @@ def get_full_index(route=None, app=None): added.append(child_route) # add remaining pages not in index.txt - _children = sorted(children, key = functools.cmp_to_key(lambda a, b: cmp( - os.path.basename(a.route), os.path.basename(b.route)))) + _children = sorted(children, key=lambda x: os.path.basename(x.route)) for child_route in _children: if child_route not in new_children: From e407b785065873c2566a5f07ffde6d6e806079b1 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 15:31:29 +0530 Subject: [PATCH 179/868] chore: Drop dead and deprecated code * Remove six for PY2 compatability since our dependencies are not, PY2 is legacy. * Removed usages of utils from future/past libraries since they are deprecated. This includes 'from __future__ ...' and 'from past...' statements. * Removed compatibility imports for PY2, switched from six imports to standard library imports. * Removed utils code blocks that handle operations depending on PY2/3 versions. * Removed 'from __future__ ...' lines from templates/code generators * Used PY3 syntaxes in place of PY2 compatible blocks. eg: metaclass --- frappe/api.py | 1 - frappe/app.py | 7 ++- frappe/auth.py | 6 +-- .../assignment_rule/assignment_rule.py | 2 - .../assignment_rule/test_assignment_rule.py | 2 - .../assignment_rule_day.py | 1 - .../assignment_rule_user.py | 1 - .../doctype/auto_repeat/auto_repeat.py | 1 - .../doctype/auto_repeat/test_auto_repeat.py | 2 - .../auto_repeat_day/auto_repeat_day.py | 1 - .../automation/doctype/milestone/milestone.py | 2 - .../doctype/milestone/test_milestone.py | 2 - .../milestone_tracker/milestone_tracker.py | 2 - .../test_milestone_tracker.py | 2 - frappe/boot.py | 9 +--- frappe/build.py | 4 +- frappe/cache_manager.py | 2 - frappe/chat/__init__.py | 2 +- .../chat/doctype/chat_message/chat_message.py | 2 - .../chat/doctype/chat_profile/chat_profile.py | 2 - frappe/chat/doctype/chat_room/chat_room.py | 2 - .../doctype/chat_room_user/chat_room_user.py | 2 - frappe/chat/doctype/chat_token/chat_token.py | 1 - frappe/chat/util/__init__.py | 2 - frappe/chat/util/test_util.py | 5 +-- frappe/chat/util/util.py | 2 - frappe/chat/website/__init__.py | 2 +- frappe/client.py | 19 ++++---- frappe/commands/__init__.py | 3 +- frappe/commands/scheduler.py | 1 - frappe/commands/translate.py | 1 - frappe/commands/utils.py | 2 +- frappe/config/__init__.py | 3 -- frappe/contacts/address_and_contact.py | 1 - .../contacts/doctype/address/test_address.py | 2 - .../address_template/address_template.py | 1 - .../address_template/test_address_template.py | 4 +- frappe/contacts/doctype/contact/contact.py | 1 - .../contacts/doctype/contact/test_contact.py | 2 - .../doctype/contact_email/contact_email.py | 1 - .../doctype/contact_phone/contact_phone.py | 1 - frappe/contacts/doctype/gender/gender.py | 1 - frappe/contacts/doctype/gender/test_gender.py | 2 - .../contacts/doctype/salutation/salutation.py | 1 - .../doctype/salutation/test_salutation.py | 2 - .../addresses_and_contacts.py | 5 +-- .../test_addresses_and_contacts.py | 2 +- frappe/core/__init__.py | 2 - frappe/core/doctype/__init__.py | 1 - frappe/core/doctype/access_log/access_log.py | 2 - .../core/doctype/activity_log/activity_log.py | 1 - frappe/core/doctype/activity_log/feed.py | 4 +- .../doctype/activity_log/test_activity_log.py | 2 - .../core/doctype/block_module/block_module.py | 1 - frappe/core/doctype/comment/comment.py | 2 - frappe/core/doctype/comment/test_comment.py | 2 - .../doctype/communication/communication.py | 3 +- frappe/core/doctype/communication/email.py | 11 ++--- .../communication/test_communication.py | 4 +- .../communication_link/communication_link.py | 1 - .../doctype/custom_docperm/custom_docperm.py | 1 - .../custom_docperm/test_custom_docperm.py | 2 - .../core/doctype/custom_role/custom_role.py | 1 - .../doctype/custom_role/test_custom_role.py | 2 - .../core/doctype/data_export/data_export.py | 1 - frappe/core/doctype/data_export/exporter.py | 5 +-- frappe/core/doctype/data_import/importer.py | 1 - .../doctype/data_import/test_data_import.py | 2 - .../core/doctype/data_import/test_exporter.py | 2 - .../core/doctype/data_import/test_importer.py | 2 - .../doctype/data_import_legacy/importer.py | 8 +--- .../test_data_import_legacy.py | 2 - frappe/core/doctype/defaultvalue/__init__.py | 1 - .../core/doctype/defaultvalue/defaultvalue.py | 1 - .../deleted_document/deleted_document.py | 1 - .../deleted_document/test_deleted_document.py | 2 - frappe/core/doctype/docfield/__init__.py | 1 - frappe/core/doctype/docfield/docfield.py | 2 - frappe/core/doctype/docperm/__init__.py | 1 - frappe/core/doctype/docperm/docperm.py | 1 - frappe/core/doctype/docshare/docshare.py | 1 - frappe/core/doctype/docshare/test_docshare.py | 1 - frappe/core/doctype/doctype/__init__.py | 1 - frappe/core/doctype/doctype/doctype.py | 9 +--- frappe/core/doctype/doctype/test_doctype.py | 2 - .../doctype/doctype_action/doctype_action.py | 1 - .../core/doctype/doctype_link/doctype_link.py | 1 - .../document_naming_rule.py | 1 - .../test_document_naming_rule.py | 2 - .../document_naming_rule_condition.py | 1 - .../test_document_naming_rule_condition.py | 2 - frappe/core/doctype/domain/domain.py | 1 - frappe/core/doctype/domain/test_domain.py | 2 - .../domain_settings/domain_settings.py | 1 - .../core/doctype/dynamic_link/dynamic_link.py | 1 - frappe/core/doctype/error_log/error_log.py | 1 - .../core/doctype/error_log/test_error_log.py | 2 - .../doctype/error_snapshot/error_snapshot.py | 1 - .../error_snapshot/test_error_snapshot.py | 2 - frappe/core/doctype/file/file.py | 42 ++++++++--------- frappe/core/doctype/file/test_file.py | 2 - frappe/core/doctype/has_domain/has_domain.py | 1 - frappe/core/doctype/has_role/has_role.py | 1 - .../installed_application.py | 1 - .../installed_applications.py | 1 - .../test_installed_applications.py | 2 - frappe/core/doctype/language/language.py | 1 - frappe/core/doctype/language/test_language.py | 2 - .../log_setting_user/log_setting_user.py | 1 - .../log_setting_user/test_log_setting_user.py | 2 - .../core/doctype/log_settings/log_settings.py | 1 - .../doctype/log_settings/test_log_settings.py | 2 - frappe/core/doctype/module_def/__init__.py | 1 - frappe/core/doctype/module_def/module_def.py | 1 - .../doctype/module_def/test_module_def.py | 2 - .../doctype/module_profile/module_profile.py | 1 - .../module_profile/test_module_profile.py | 1 - .../core/doctype/navbar_item/navbar_item.py | 1 - .../doctype/navbar_item/test_navbar_item.py | 2 - .../navbar_settings/navbar_settings.py | 1 - .../navbar_settings/test_navbar_settings.py | 2 - frappe/core/doctype/page/__init__.py | 1 - frappe/core/doctype/page/page.py | 2 - frappe/core/doctype/page/test_page.py | 2 - frappe/core/doctype/patch_log/patch_log.py | 1 - .../core/doctype/patch_log/test_patch_log.py | 2 - .../payment_gateway/payment_gateway.py | 1 - .../payment_gateway/test_payment_gateway.py | 2 - .../prepared_report/prepared_report.py | 2 - .../prepared_report/test_prepared_report.py | 2 - frappe/core/doctype/report/__init__.py | 1 - frappe/core/doctype/report/report.py | 5 +-- frappe/core/doctype/report/test_report.py | 1 - .../doctype/report_column/report_column.py | 1 - .../doctype/report_filter/report_filter.py | 1 - frappe/core/doctype/role/__init__.py | 1 - frappe/core/doctype/role/role.py | 1 - frappe/core/doctype/role/test_role.py | 2 - .../role_permission_for_page_and_report.py | 1 - .../core/doctype/role_profile/role_profile.py | 1 - .../doctype/role_profile/test_role_profile.py | 1 - .../scheduled_job_log/scheduled_job_log.py | 1 - .../test_scheduled_job_log.py | 2 - .../test_scheduled_job_type.py | 2 - .../doctype/server_script/server_script.py | 2 - .../server_script/test_server_script.py | 2 - .../session_default/session_default.py | 1 - .../session_default_settings.py | 1 - .../test_session_default_settings.py | 2 - frappe/core/doctype/sms_parameter/__init__.py | 2 +- .../doctype/sms_parameter/sms_parameter.py | 1 - frappe/core/doctype/sms_settings/__init__.py | 2 +- .../core/doctype/sms_settings/sms_settings.py | 11 ++--- .../doctype/sms_settings/test_sms_settings.py | 2 - .../doctype/success_action/success_action.py | 1 - .../system_settings/system_settings.py | 1 - .../system_settings/test_system_settings.py | 2 - frappe/core/doctype/test/test.py | 1 - frappe/core/doctype/test/test_test.py | 2 - .../transaction_log/test_transaction_log.py | 4 +- .../transaction_log/transaction_log.py | 1 - .../doctype/translation/test_translation.py | 2 - .../core/doctype/translation/translation.py | 1 - frappe/core/doctype/user/test_user.py | 2 - frappe/core/doctype/user/user.py | 4 -- .../user_document_type/user_document_type.py | 1 - frappe/core/doctype/user_email/user_email.py | 1 - .../doctype/user_group/test_user_group.py | 2 - frappe/core/doctype/user_group/user_group.py | 1 - .../test_user_group_member.py | 2 - .../user_group_member/user_group_member.py | 1 - .../user_permission/test_user_permission.py | 1 - .../user_permission/user_permission.py | 1 - .../user_select_document_type.py | 1 - .../user_social_login/user_social_login.py | 1 - .../core/doctype/user_type/test_user_type.py | 2 - frappe/core/doctype/user_type/user_type.py | 4 +- .../doctype/user_type/user_type_dashboard.py | 2 +- .../user_type_module/user_type_module.py | 1 - frappe/core/doctype/version/test_version.py | 2 - frappe/core/doctype/version/version.py | 1 - frappe/core/doctype/view_log/test_view_log.py | 6 +-- frappe/core/doctype/view_log/view_log.py | 1 - frappe/core/notifications.py | 1 - frappe/core/page/__init__.py | 1 - .../permission_manager/permission_manager.py | 1 - .../permitted_documents_for_user.py | 1 - .../transaction_log_report.py | 1 - frappe/core/utils.py | 1 - .../web_form/edit_profile/edit_profile.py | 2 - .../custom/doctype/client_script/__init__.py | 1 - .../doctype/client_script/client_script.py | 1 - .../client_script/test_client_script.py | 2 - .../custom/doctype/custom_field/__init__.py | 1 - .../doctype/custom_field/custom_field.py | 1 - .../doctype/custom_field/test_custom_field.py | 2 - .../custom/doctype/customize_form/__init__.py | 1 - .../doctype/customize_form/customize_form.py | 1 - .../customize_form/test_customize_form.py | 1 - .../doctype/customize_form_field/__init__.py | 1 - .../customize_form_field.py | 1 - .../doctype/doctype_layout/doctype_layout.py | 2 - .../doctype_layout/test_doctype_layout.py | 2 - .../doctype_layout_field.py | 1 - .../doctype/property_setter/__init__.py | 1 - .../property_setter/property_setter.py | 1 - .../property_setter/test_property_setter.py | 2 - .../test_rename_new/test_rename_new.py | 1 - .../test_rename_new/test_test_rename_new.py | 2 - .../connectors/base.py | 5 +-- .../connectors/frappe_connection.py | 2 +- .../data_migration_connector.py | 4 +- .../test_data_migration_connector.py | 1 - .../data_migration_mapping.py | 1 - .../test_data_migration_mapping.py | 1 - .../data_migration_mapping_detail.py | 1 - .../data_migration_plan.py | 1 - .../test_data_migration_plan.py | 1 - .../data_migration_plan_mapping.py | 1 - .../data_migration_run/data_migration_run.py | 1 - .../test_data_migration_run.py | 1 - frappe/database/__init__.py | 2 - frappe/database/database.py | 27 ++++------- frappe/database/mariadb/schema.py | 2 - frappe/database/mariadb/setup_db.py | 2 - frappe/database/postgres/database.py | 3 +- frappe/database/postgres/setup_db.py | 1 - frappe/database/schema.py | 2 - frappe/defaults.py | 1 - frappe/desk/__init__.py | 1 - frappe/desk/calendar.py | 2 - frappe/desk/desk_page.py | 1 - frappe/desk/desktop.py | 4 +- .../desk/doctype/bulk_update/bulk_update.py | 1 - .../doctype/calendar_view/calendar_view.py | 1 - .../desk/doctype/console_log/console_log.py | 1 - .../doctype/console_log/test_console_log.py | 2 - frappe/desk/doctype/dashboard/dashboard.py | 1 - .../desk/doctype/dashboard/test_dashboard.py | 2 - .../dashboard_chart/dashboard_chart.py | 1 - .../dashboard_chart/test_dashboard_chart.py | 2 - .../dashboard_chart_field.py | 1 - .../dashboard_chart_link.py | 1 - .../dashboard_chart_source.py | 1 - .../test_dashboard_chart_source.py | 2 - .../dashboard_settings/dashboard_settings.py | 1 - .../desk/doctype/desktop_icon/desktop_icon.py | 9 ++-- frappe/desk/doctype/event/__init__.py | 1 - frappe/desk/doctype/event/event.py | 8 ++-- frappe/desk/doctype/event/test_event.py | 2 - .../event_participants/event_participants.py | 1 - .../global_search_doctype.py | 1 - .../global_search_settings.py | 1 - .../desk/doctype/kanban_board/kanban_board.py | 4 +- .../doctype/kanban_board/test_kanban_board.py | 2 - .../kanban_board_column.py | 1 - .../desk/doctype/list_filter/list_filter.py | 1 - .../list_view_settings/list_view_settings.py | 1 - .../test_list_view_settings.py | 2 - .../module_onboarding/module_onboarding.py | 1 - .../test_module_onboarding.py | 2 - frappe/desk/doctype/note/note.py | 1 - frappe/desk/doctype/note/test_note.py | 1 - .../desk/doctype/note_seen_by/note_seen_by.py | 1 - .../notification_log/notification_log.py | 1 - .../notification_log/test_notification_log.py | 2 - .../notification_settings.py | 1 - .../notification_subscribed_document.py | 1 - .../desk/doctype/number_card/number_card.py | 1 - .../doctype/number_card/test_number_card.py | 2 - .../number_card_link/number_card_link.py | 1 - .../onboarding_permission.py | 1 - .../test_onboarding_permission.py | 2 - .../onboarding_step/onboarding_step.py | 1 - .../onboarding_step/test_onboarding_step.py | 2 - .../onboarding_step_map.py | 1 - .../doctype/route_history/route_history.py | 1 - .../doctype/system_console/system_console.py | 2 - .../system_console/test_system_console.py | 2 - frappe/desk/doctype/tag/tag.py | 1 - frappe/desk/doctype/tag/test_tag.py | 2 - frappe/desk/doctype/tag_link/tag_link.py | 1 - frappe/desk/doctype/tag_link/test_tag_link.py | 2 - frappe/desk/doctype/todo/__init__.py | 1 - frappe/desk/doctype/todo/test_todo.py | 2 - frappe/desk/doctype/todo/todo.py | 5 +-- .../desk/doctype/workspace/test_workspace.py | 2 - frappe/desk/doctype/workspace/workspace.py | 1 - .../workspace_chart/workspace_chart.py | 1 - .../doctype/workspace_link/workspace_link.py | 1 - .../workspace_shortcut/workspace_shortcut.py | 1 - frappe/desk/form/__init__.py | 1 - frappe/desk/form/assign_to.py | 1 - frappe/desk/form/document_follow.py | 1 - frappe/desk/form/linked_with.py | 8 ++-- frappe/desk/form/load.py | 3 +- frappe/desk/form/meta.py | 9 +--- frappe/desk/form/save.py | 1 - frappe/desk/form/test_form.py | 1 - frappe/desk/form/utils.py | 4 +- frappe/desk/gantt.py | 2 - frappe/desk/leaderboard.py | 2 - frappe/desk/like.py | 2 - frappe/desk/listview.py | 2 - frappe/desk/moduleview.py | 1 - frappe/desk/notifications.py | 7 +-- frappe/desk/page/activity/__init__.py | 2 +- frappe/desk/page/activity/activity.py | 1 - frappe/desk/page/backups/backups.py | 2 +- frappe/desk/page/leaderboard/leaderboard.py | 2 - .../page/setup_wizard/install_fixtures.py | 2 - frappe/desk/page/setup_wizard/setup_wizard.py | 9 ++-- frappe/desk/query_report.py | 21 ++++----- frappe/desk/report/todo/todo.py | 1 - frappe/desk/report_dump.py | 3 +- frappe/desk/reportview.py | 22 +++++---- frappe/desk/search.py | 4 +- frappe/desk/treeview.py | 1 - frappe/email/__init__.py | 1 - .../auto_email_report/auto_email_report.py | 2 - .../test_auto_email_report.py | 2 - .../document_follow/document_follow.py | 1 - .../document_follow/test_document_follow.py | 2 - .../doctype/email_account/email_account.py | 2 - .../email_account/test_email_account.py | 1 - .../doctype/email_domain/email_domain.py | 1 - .../doctype/email_domain/test_email_domain.py | 2 - .../email_flag_queue/email_flag_queue.py | 1 - .../email_flag_queue/test_email_flag_queue.py | 2 - .../email/doctype/email_group/email_group.py | 1 - .../doctype/email_group/test_email_group.py | 2 - .../email_group_member/email_group_member.py | 1 - .../test_email_group_member.py | 2 - .../doctype/email_queue/test_email_queue.py | 2 - .../email_queue_recipient.py | 1 - frappe/email/doctype/email_rule/email_rule.py | 1 - .../doctype/email_rule/test_email_rule.py | 2 - .../doctype/email_template/email_template.py | 6 +-- .../email_template/test_email_template.py | 2 - .../email_unsubscribe/email_unsubscribe.py | 1 - .../test_email_unsubscribe.py | 2 - frappe/email/doctype/newsletter/newsletter.py | 2 - .../doctype/newsletter/test_newsletter.py | 2 - .../newsletter_email_group.py | 1 - .../doctype/notification/notification.py | 8 +--- .../doctype/notification/test_notification.py | 2 - .../notification_recipient.py | 1 - .../unhandled_email/test_unhandled_email.py | 2 - .../unhandled_email/unhandled_email.py | 1 - frappe/email/email_body.py | 12 +++-- frappe/email/inbox.py | 2 +- frappe/email/queue.py | 10 ++--- frappe/email/receive.py | 10 ++--- frappe/email/smtp.py | 1 - frappe/email/test_email_body.py | 18 ++------ frappe/email/utils.py | 2 - .../document_type_field_mapping.py | 1 - .../document_type_mapping.py | 9 ++-- .../test_document_type_mapping.py | 2 - .../doctype/event_consumer/event_consumer.py | 3 +- .../event_consumer/test_event_consumer.py | 2 - .../event_consumer_document_type.py | 1 - .../event_producer/test_event_producer.py | 6 +-- .../event_producer_document_type.py | 1 - .../event_producer_last_update.py | 1 - .../test_event_producer_last_update.py | 2 - .../doctype/event_sync_log/event_sync_log.py | 1 - .../event_sync_log/test_event_sync_log.py | 2 - .../event_update_log/event_update_log.py | 3 +- .../event_update_log/test_event_update_log.py | 2 - .../event_update_log_consumer.py | 1 - frappe/exceptions.py | 1 - frappe/frappeclient.py | 6 +-- frappe/geo/country_info.py | 2 - frappe/geo/doctype/country/__init__.py | 2 +- frappe/geo/doctype/country/country.py | 1 - frappe/geo/doctype/country/test_country.py | 1 - frappe/geo/doctype/currency/__init__.py | 2 +- frappe/geo/doctype/currency/currency.py | 1 - frappe/geo/doctype/currency/test_currency.py | 1 - frappe/geo/utils.py | 2 - frappe/handler.py | 2 - frappe/hooks.py | 2 +- .../braintree_settings/braintree_settings.py | 3 +- .../test_braintree_settings.py | 2 - .../connected_app/test_connected_app.py | 2 - .../dropbox_settings/test_dropbox_settings.py | 2 - .../doctype/google_drive/test_google_drive.py | 2 - .../google_settings/google_settings.py | 1 - .../integration_request.py | 6 +-- .../test_integration_request.py | 2 - .../ldap_group_mapping/ldap_group_mapping.py | 1 - .../doctype/ldap_settings/ldap_settings.py | 1 - .../ldap_settings/test_ldap_settings.py | 2 - .../oauth_authorization_code.py | 1 - .../test_oauth_authorization_code.py | 2 - .../oauth_bearer_token/oauth_bearer_token.py | 1 - .../test_oauth_bearer_token.py | 2 - .../doctype/oauth_client/oauth_client.py | 1 - .../doctype/oauth_client/test_oauth_client.py | 2 - .../oauth_provider_settings.py | 1 - .../doctype/oauth_scope/oauth_scope.py | 1 - .../paypal_settings/paypal_settings.py | 3 +- .../doctype/paytm_settings/paytm_settings.py | 5 +-- .../paytm_settings/test_paytm_settings.py | 2 - .../query_parameters/query_parameters.py | 1 - .../razorpay_settings/razorpay_settings.py | 3 +- .../s3_backup_settings/s3_backup_settings.py | 2 - .../test_s3_backup_settings.py | 2 - .../slack_webhook_url/slack_webhook_url.py | 1 - .../test_slack_webhook_url.py | 2 - .../social_login_key/social_login_key.py | 1 - .../social_login_key/test_social_login_key.py | 2 - .../social_login_keys/social_login_keys.py | 1 - .../stripe_settings/stripe_settings.py | 3 +- .../stripe_settings/test_stripe_settings.py | 2 - .../doctype/token_cache/test_token_cache.py | 2 - .../doctype/token_cache/token_cache.py | 1 - .../integrations/doctype/webhook/__init__.py | 4 +- .../doctype/webhook/test_webhook.py | 6 +-- .../integrations/doctype/webhook/webhook.py | 4 +- .../doctype/webhook_data/webhook_data.py | 1 - .../doctype/webhook_header/webhook_header.py | 1 - frappe/integrations/oauth2_logins.py | 3 +- frappe/integrations/offsite_backup_utils.py | 1 - frappe/integrations/utils.py | 10 ++--- frappe/middlewares.py | 2 - frappe/migrate.py | 2 - frappe/model/__init__.py | 1 - frappe/model/base_document.py | 20 ++++----- frappe/model/create_new.py | 1 - frappe/model/db_query.py | 23 ++++------ frappe/model/delete_doc.py | 4 +- frappe/model/docfield.py | 1 - frappe/model/document.py | 11 ++--- frappe/model/dynamic_links.py | 1 - frappe/model/mapper.py | 4 +- frappe/model/meta.py | 3 -- frappe/model/naming.py | 14 +++--- frappe/model/rename_doc.py | 3 -- frappe/model/sync.py | 2 - frappe/model/utils/__init__.py | 5 --- frappe/model/utils/link_count.py | 5 +-- frappe/model/utils/rename_field.py | 3 -- frappe/model/utils/user_settings.py | 7 ++- frappe/model/workflow.py | 4 +- frappe/modules/__init__.py | 2 +- frappe/modules/export_file.py | 2 - frappe/modules/import_file.py | 3 -- frappe/modules/patch_handler.py | 5 --- frappe/modules/utils.py | 2 - frappe/monitor.py | 2 - ..._chat_by_default_within_system_settings.py | 2 +- frappe/patches/v10_0/enhance_security.py | 2 - .../increase_single_table_column_length.py | 2 +- .../v10_0/migrate_passwords_passlib.py | 2 +- .../v10_0/modify_naming_series_table.py | 2 - .../modify_smallest_currency_fraction.py | 1 - .../v10_0/refactor_social_login_keys.py | 2 - .../v10_0/reload_countries_and_currencies.py | 2 +- ...remove_custom_field_for_disabled_domain.py | 2 +- .../patches/v10_0/set_default_locking_time.py | 1 - .../v10_0/set_no_copy_to_workflow_state.py | 2 +- .../v11_0/change_email_signature_fieldtype.py | 1 - .../v11_0/copy_fetch_data_from_options.py | 2 +- .../patches/v11_0/create_contact_for_user.py | 2 +- .../v11_0/delete_all_prepared_reports.py | 2 +- .../delete_duplicate_user_permissions.py | 2 +- .../drop_column_apply_user_permissions.py | 2 +- .../v11_0/fix_order_by_in_reports_json.py | 2 +- ...all_prepared_report_attachments_private.py | 2 +- ...igrate_report_settings_for_new_listview.py | 2 +- .../v11_0/multiple_references_in_events.py | 2 +- .../v11_0/reload_and_rename_view_log.py | 2 +- ...pe_user_permissions_for_page_and_report.py | 1 - .../patches/v11_0/remove_skip_for_doctype.py | 2 +- .../rename_email_alert_to_notification.py | 2 +- .../v11_0/rename_google_maps_doctype.py | 2 +- ...rename_standard_reply_to_email_template.py | 2 +- ...rkflow_action_to_workflow_action_master.py | 2 +- .../v11_0/replicate_old_user_permissions.py | 2 +- .../set_allow_self_approval_in_workflow.py | 2 +- .../v11_0/set_default_letter_head_source.py | 2 - .../patches/v11_0/set_dropbox_file_backup.py | 2 +- .../sync_stripe_settings_before_migrate.py | 2 +- ..._user_permission_doctype_before_migrate.py | 2 +- .../v11_0/update_list_user_settings.py | 2 +- .../create_notification_settings_for_user.py | 2 +- frappe/patches/v12_0/init_desk_settings.py | 2 - .../move_timeline_links_to_dynamic_links.py | 2 - .../setup_comments_from_communications.py | 2 - frappe/patches/v12_0/setup_email_linking.py | 2 - ..._auto_repeat_status_and_not_submittable.py | 2 +- .../v13_0/add_standard_navbar_items.py | 2 +- .../add_switch_theme_to_navbar_settings.py | 2 +- .../add_toggle_width_in_navbar_settings.py | 2 +- frappe/patches/v13_0/cleanup_desk_cards.py | 13 +++--- ...delete_event_producer_and_consumer_keys.py | 1 - .../v13_0/delete_package_publish_tool.py | 1 - frappe/patches/v13_0/enable_custom_script.py | 1 - .../generate_theme_files_in_public_folder.py | 1 - frappe/patches/v13_0/jinja_hook.py | 1 - frappe/patches/v13_0/queryreport_columns.py | 1 - .../v13_0/remove_duplicate_navbar_items.py | 2 +- .../remove_tailwind_from_page_builder.py | 1 - ...list_view_setting_to_list_view_settings.py | 1 - .../v13_0/rename_notification_fields.py | 1 - frappe/patches/v13_0/rename_onboarding.py | 1 - .../patches/v13_0/replace_old_data_import.py | 1 - .../update_date_filters_in_user_settings.py | 2 +- .../patches/v13_0/update_duration_options.py | 1 - .../update_icons_in_customized_desk_pages.py | 2 +- .../v13_0/update_newsletter_content_type.py | 1 - .../update_notification_channel_if_empty.py | 1 - .../patches/v13_0/web_template_set_module.py | 1 - frappe/patches/v4_0/add_delete_permission.py | 8 ++-- frappe/patches/v4_0/change_varchar_length.py | 1 - .../create_custom_field_for_owner_match.py | 2 - .../patches/v4_0/deprecate_control_panel.py | 1 - frappe/patches/v4_0/deprecate_link_selects.py | 1 - .../enable_scheduler_in_system_settings.py | 1 - frappe/patches/v4_0/file_manager_hooks.py | 4 -- .../patches/v4_0/fix_attach_field_file_url.py | 1 - frappe/patches/v4_0/private_backups.py | 1 - frappe/patches/v4_0/remove_index_sitemap.py | 2 +- frappe/patches/v4_0/remove_old_parent.py | 1 - .../v4_0/remove_user_owner_custom_field.py | 1 - frappe/patches/v4_0/rename_profile_to_user.py | 2 +- .../patches/v4_0/rename_sitemap_to_route.py | 2 +- .../v4_0/replace_deprecated_timezones.py | 1 - frappe/patches/v4_0/set_module_in_report.py | 1 - .../v4_0/set_todo_checked_as_closed.py | 2 +- frappe/patches/v4_0/set_user_gravatar.py | 1 - frappe/patches/v4_0/set_user_permissions.py | 1 - frappe/patches/v4_0/set_website_route_idx.py | 2 +- .../v4_0/update_custom_field_insert_after.py | 1 - frappe/patches/v4_0/update_datetime.py | 2 +- frappe/patches/v4_0/webnotes_to_frappe.py | 2 +- .../patches/v4_0/website_sitemap_hierarchy.py | 2 - .../v4_1/enable_outgoing_email_settings.py | 1 - frappe/patches/v4_1/enable_print_as_pdf.py | 1 - frappe/patches/v4_1/file_manager_fix.py | 8 +--- frappe/patches/v4_2/print_with_letterhead.py | 1 - .../patches/v4_2/refactor_website_routing.py | 2 +- frappe/patches/v4_2/set_assign_in_doc.py | 2 +- .../remove_allow_on_submit_customization.py | 1 - frappe/patches/v5_0/bookmarks_to_stars.py | 5 +-- .../clear_website_group_and_notifications.py | 2 +- frappe/patches/v5_0/communication_parent.py | 2 +- .../v5_0/convert_to_barracuda_and_utf8mb4.py | 2 +- .../patches/v5_0/expire_old_scheduler_logs.py | 2 +- frappe/patches/v5_0/fix_email_alert.py | 2 - frappe/patches/v5_0/fix_null_date_datetime.py | 2 +- .../patches/v5_0/fix_text_editor_file_urls.py | 1 - frappe/patches/v5_0/force_sync_website.py | 2 +- frappe/patches/v5_0/modify_session.py | 2 +- ...scheduler_last_event_to_system_settings.py | 2 +- .../patches/v5_0/remove_shopping_cart_app.py | 2 - .../v5_0/rename_ref_type_fieldnames.py | 1 - .../patches/v5_0/rename_table_fieldnames.py | 1 - .../v5_0/style_settings_to_website_theme.py | 2 +- frappe/patches/v5_0/update_shared.py | 2 +- frappe/patches/v5_0/v4_to_v5.py | 1 - .../patches/v5_2/change_checks_to_not_null.py | 2 +- .../patches/v5_3/rename_chinese_languages.py | 1 - .../communication_status_and_permission.py | 2 +- frappe/patches/v6_0/document_type_rename.py | 4 +- frappe/patches/v6_0/fix_ghana_currency.py | 2 - frappe/patches/v6_0/make_task_log_folder.py | 2 +- frappe/patches/v6_1/rename_file_data.py | 1 - .../v6_11/rename_field_in_email_account.py | 2 +- ...move_property_setter_for_previous_field.py | 1 - frappe/patches/v6_15/set_username.py | 2 +- frappe/patches/v6_16/feed_doc_owner.py | 2 +- frappe/patches/v6_16/star_to_like.py | 2 +- .../v6_19/comment_feed_communication.py | 2 +- .../ignore_user_permissions_if_missing.py | 2 +- frappe/patches/v6_2/rename_backup_manager.py | 2 +- .../v6_20x/remove_roles_from_website_user.py | 2 +- .../v6_20x/set_allow_draft_for_print.py | 2 +- frappe/patches/v6_20x/update_insert_after.py | 2 +- .../print_settings_repeat_header_footer.py | 2 +- frappe/patches/v6_24/set_language_as_code.py | 2 +- frappe/patches/v6_4/reduce_varchar_length.py | 1 - .../patches/v6_4/rename_bengali_language.py | 1 - frappe/patches/v6_6/fix_file_url.py | 2 +- frappe/patches/v6_6/rename_slovak_language.py | 1 - frappe/patches/v6_6/user_last_active.py | 2 +- frappe/patches/v6_9/int_float_not_null.py | 2 +- .../patches/v6_9/rename_burmese_language.py | 1 - .../patches/v7_0/add_communication_in_doc.py | 2 +- frappe/patches/v7_0/cleanup_list_settings.py | 12 ++--- .../v7_0/create_private_file_folder.py | 2 +- frappe/patches/v7_0/re_route.py | 2 +- .../v7_0/rename_bulk_email_to_email_queue.py | 2 +- .../rename_newsletter_list_to_email_group.py | 2 +- frappe/patches/v7_0/set_email_group.py | 3 +- frappe/patches/v7_0/set_user_fullname.py | 4 +- frappe/patches/v7_0/update_auth.py | 2 +- .../v7_0/update_report_builder_json.py | 1 - .../v7_0/update_send_after_in_bulk_email.py | 2 +- ..._print_settings_for_custom_print_format.py | 13 +++--- .../v7_1/refactor_integration_broker.py | 9 ++-- .../v7_1/rename_chinese_language_codes.py | 2 +- .../v7_1/rename_scheduler_log_to_error_log.py | 2 +- frappe/patches/v7_1/set_backup_limit.py | 2 +- .../v7_1/setup_integration_services.py | 2 +- frappe/patches/v7_1/sync_language_doctype.py | 2 +- .../patches/v7_2/fix_email_queue_recipient.py | 2 +- frappe/patches/v7_2/merge_knowledge_base.py | 2 +- frappe/patches/v7_2/remove_in_filter.py | 2 +- frappe/patches/v7_2/set_doctype_engine.py | 2 +- .../v7_2/set_in_standard_filter_property.py | 2 +- frappe/patches/v7_2/setup_custom_perms.py | 2 +- frappe/patches/v7_2/setup_ldap_config.py | 2 +- frappe/patches/v7_2/update_communications.py | 2 +- .../patches/v7_2/update_feedback_request.py | 2 +- .../v8_0/deprecate_integration_broker.py | 6 +-- frappe/patches/v8_0/drop_in_dialog.py | 2 +- .../v8_0/drop_is_custom_from_docperm.py | 2 +- frappe/patches/v8_0/drop_unwanted_indexes.py | 5 +-- .../install_new_build_system_requirements.py | 1 - .../v8_0/newsletter_childtable_migrate.py | 3 +- .../rename_listsettings_to_usersettings.py | 5 +-- .../v8_0/rename_page_role_to_has_role.py | 3 +- .../patches/v8_0/rename_print_to_printing.py | 4 +- frappe/patches/v8_0/set_allow_traceback.py | 2 +- .../v8_0/set_currency_field_precision.py | 1 - .../v8_0/set_doctype_values_in_custom_role.py | 5 +-- ...set_user_permission_for_page_and_report.py | 9 ++-- frappe/patches/v8_0/setup_email_inbox.py | 2 +- .../v8_0/update_gender_and_salutation.py | 1 - .../v8_0/update_global_search_table.py | 2 +- .../v8_0/update_published_in_global_search.py | 2 +- .../v8_0/update_records_in_global_search.py | 4 +- ...te_custom_docperm_if_doctype_not_exists.py | 2 +- ...llow_error_traceback_in_system_settings.py | 1 - ...ate_format_options_in_auto_email_report.py | 1 - ...lete_static_web_page_from_global_search.py | 2 +- ..._email_group_member_with_invalid_emails.py | 1 - frappe/patches/v8_5/patch_event_colors.py | 2 +- frappe/patches/v8_x/update_user_permission.py | 2 +- frappe/patches/v9_1/__init__.py | 2 +- .../v9_1/add_sms_sender_name_as_parameters.py | 1 - .../patches/v9_1/move_feed_to_activity_log.py | 2 +- frappe/patches/v9_1/resave_domain_settings.py | 2 +- frappe/patches/v9_1/revert_domain_settings.py | 2 +- frappe/permissions.py | 12 +++-- .../doctype/letter_head/letter_head.py | 3 +- .../doctype/letter_head/test_letter_head.py | 2 - .../doctype/print_format/print_format.py | 1 - .../doctype/print_format/test_print_format.py | 2 - .../doctype/print_heading/print_heading.py | 1 - .../print_heading/test_print_heading.py | 2 - .../doctype/print_settings/print_settings.py | 1 - .../print_settings/test_print_settings.py | 2 - .../doctype/print_style/print_style.py | 1 - .../doctype/print_style/test_print_style.py | 2 - frappe/pythonrc.py | 2 - frappe/rate_limiter.py | 2 - frappe/recorder.py | 2 - frappe/sessions.py | 7 +-- frappe/share.py | 1 - .../energy_point_log/energy_point_log.py | 1 - .../energy_point_log/test_energy_point_log.py | 2 - .../energy_point_rule/energy_point_rule.py | 1 - .../energy_point_settings.py | 1 - frappe/social/doctype/post/post.py | 1 - .../doctype/post_comment/post_comment.py | 1 - .../doctype/review_level/review_level.py | 1 - .../templates/includes/comments/comments.py | 2 - .../pages/integrations/braintree_checkout.py | 1 - .../pages/integrations/payment_cancel.py | 1 - .../pages/integrations/payment_success.py | 2 - .../pages/integrations/paytm_checkout.py | 1 - .../pages/integrations/razorpay_checkout.py | 4 +- .../pages/integrations/stripe_checkout.py | 1 - frappe/test_runner.py | 9 ++-- frappe/tests/test_assign.py | 2 - frappe/tests/test_auth.py | 2 - frappe/tests/test_bot.py | 1 - frappe/tests/test_client.py | 2 - frappe/tests/test_cors.py | 2 - frappe/tests/test_db.py | 2 - frappe/tests/test_db_query.py | 2 - frappe/tests/test_defaults.py | 2 - frappe/tests/test_document.py | 2 - frappe/tests/test_document_locks.py | 2 - frappe/tests/test_domainification.py | 2 - frappe/tests/test_dynamic_links.py | 2 - frappe/tests/test_email.py | 8 +--- frappe/tests/test_exporter_fixtures.py | 2 - frappe/tests/test_fmt_datetime.py | 2 - frappe/tests/test_fmt_money.py | 2 - frappe/tests/test_form_load.py | 2 - frappe/tests/test_geo_ip.py | 2 - frappe/tests/test_global_search.py | 1 - frappe/tests/test_goal.py | 1 - frappe/tests/test_hooks.py | 5 +-- frappe/tests/test_listview.py | 2 - frappe/tests/test_monitor.py | 1 - frappe/tests/test_naming.py | 1 - frappe/tests/test_password.py | 1 - frappe/tests/test_patches.py | 2 +- frappe/tests/test_pdf.py | 6 +-- frappe/tests/test_permissions.py | 2 - frappe/tests/test_query_report.py | 2 - frappe/tests/test_rate_limiter.py | 2 - frappe/tests/test_recorder.py | 1 - frappe/tests/test_safe_exec.py | 2 +- frappe/tests/test_scheduler.py | 2 - frappe/tests/test_search.py | 1 - frappe/tests/test_seen.py | 2 - frappe/tests/test_sitemap.py | 2 - frappe/tests/test_translate.py | 2 - frappe/tests/test_translation.py | 2 - frappe/tests/test_twofactor.py | 2 - frappe/tests/test_utils.py | 24 +++++----- frappe/tests/test_website.py | 2 - frappe/tests/tests_geo_utils.py | 2 - frappe/translate.py | 37 +++++---------- frappe/twofactor.py | 12 ++--- frappe/utils/__init__.py | 2 +- frappe/utils/background_jobs.py | 7 +-- frappe/utils/bench_helper.py | 1 - frappe/utils/boilerplate.py | 3 -- frappe/utils/bot.py | 2 - frappe/utils/change_log.py | 1 - frappe/utils/connections.py | 2 +- frappe/utils/csvutils.py | 18 +++----- frappe/utils/dashboard.py | 1 - frappe/utils/data.py | 45 +++++++++---------- frappe/utils/dateutils.py | 4 +- frappe/utils/doctor.py | 4 +- frappe/utils/error.py | 8 ++-- frappe/utils/file_lock.py | 2 - frappe/utils/file_manager.py | 38 +++++++--------- frappe/utils/formatters.py | 4 +- frappe/utils/global_search.py | 7 +-- frappe/utils/goal.py | 1 - frappe/utils/html_utils.py | 9 ++-- frappe/utils/identicon.py | 4 +- frappe/utils/image.py | 8 ++-- frappe/utils/install.py | 3 -- frappe/utils/jinja.py | 2 - frappe/utils/jinja_globals.py | 1 - frappe/utils/logger.py | 8 +--- frappe/utils/make_random.py | 6 +-- frappe/utils/minify.py | 4 +- frappe/utils/momentjs.py | 1 - frappe/utils/nestedset.py | 2 - frappe/utils/oauth.py | 6 +-- frappe/utils/password.py | 1 - frappe/utils/password_strength.py | 2 - frappe/utils/pdf.py | 5 --- frappe/utils/print_format.py | 2 - frappe/utils/redis_wrapper.py | 12 +++-- frappe/utils/reset_doc.py | 4 +- frappe/utils/response.py | 8 ++-- frappe/utils/scheduler.py | 2 - frappe/utils/testutils.py | 2 - frappe/utils/user.py | 2 - frappe/utils/verified_command.py | 7 +-- frappe/website/context.py | 1 - frappe/website/doctype/__init__.py | 2 +- .../about_us_settings/about_us_settings.py | 5 +-- .../test_about_us_settings.py | 2 - .../about_us_team_member.py | 1 - .../doctype/blog_category/blog_category.py | 1 - .../blog_category/test_blog_category.py | 2 - frappe/website/doctype/blog_post/blog_post.py | 2 - .../doctype/blog_post/test_blog_post.py | 1 - .../doctype/blog_settings/blog_settings.py | 3 +- .../blog_settings/test_blog_settings.py | 2 - frappe/website/doctype/blogger/blogger.py | 1 - .../website/doctype/blogger/test_blogger.py | 2 - frappe/website/doctype/color/color.py | 1 - frappe/website/doctype/color/test_color.py | 2 - .../company_history/company_history.py | 1 - .../contact_us_settings.py | 1 - .../doctype/help_article/help_article.py | 1 - .../doctype/help_article/test_help_article.py | 2 - .../doctype/help_category/help_category.py | 1 - .../help_category/test_help_category.py | 2 - .../test_personal_data_deletion_request.py | 2 - .../personal_data_deletion_step.py | 1 - .../personal_data_download_request.py | 1 - .../test_personal_data_download_request.py | 2 - .../portal_menu_item/portal_menu_item.py | 1 - .../portal_settings/portal_settings.py | 1 - .../portal_settings/test_portal_settings.py | 2 - .../social_link_settings.py | 1 - .../website/doctype/top_bar_item/__init__.py | 2 +- .../doctype/top_bar_item/top_bar_item.py | 1 - .../website/doctype/web_form/test_web_form.py | 2 - frappe/website/doctype/web_form/web_form.py | 12 +---- .../doctype/web_form_field/web_form_field.py | 1 - frappe/website/doctype/web_page/__init__.py | 2 +- .../website/doctype/web_page/test_web_page.py | 2 +- frappe/website/doctype/web_page/web_page.py | 2 - .../doctype/web_page_block/web_page_block.py | 2 - .../web_page_view/test_web_page_view.py | 2 - .../doctype/web_page_view/web_page_view.py | 1 - .../doctype/web_template/test_web_template.py | 2 - .../doctype/web_template/web_template.py | 2 - .../test_web_template_field.py | 2 - .../web_template_field/web_template_field.py | 1 - .../website_meta_tag/website_meta_tag.py | 1 - .../test_website_route_meta.py | 2 - .../website_route_meta/website_route_meta.py | 1 - .../website_route_redirect.py | 1 - .../doctype/website_script/website_script.py | 1 - .../doctype/website_settings/__init__.py | 2 +- .../website_settings/test_website_settings.py | 2 - .../website_settings/website_settings.py | 3 +- .../website_sidebar/test_website_sidebar.py | 2 - .../website_sidebar/website_sidebar.py | 1 - .../website_sidebar_item.py | 1 - .../test_website_slideshow.py | 2 - .../website_slideshow/website_slideshow.py | 1 - .../website_slideshow_item.py | 1 - .../website_theme/test_website_theme.py | 2 - .../doctype/website_theme/website_theme.py | 1 - .../website_theme_ignore_app.py | 1 - frappe/website/page/__init__.py | 2 +- frappe/website/purifycss.py | 1 - frappe/website/redirect.py | 2 - frappe/website/render.py | 7 +-- .../website_analytics/website_analytics.py | 1 - frappe/website/router.py | 2 - frappe/website/utils.py | 1 - .../web_form/request_data/request_data.py | 2 - .../request_to_delete_data.py | 2 - frappe/website/website_generator.py | 1 - .../doctype/workflow/test_workflow.py | 2 - frappe/workflow/doctype/workflow/workflow.py | 1 - .../workflow_action/workflow_action.py | 1 - .../workflow_action_master.py | 1 - .../workflow_document_state.py | 1 - .../workflow_state/test_workflow_state.py | 2 - .../doctype/workflow_state/workflow_state.py | 1 - .../workflow_transition.py | 1 - frappe/www/404.py | 2 - frappe/www/__init__.py | 2 +- frappe/www/about.py | 1 - frappe/www/app.py | 3 -- frappe/www/complete_signup.py | 2 - frappe/www/contact.py | 2 - frappe/www/error.py | 2 - frappe/www/list.py | 1 - frappe/www/login.py | 1 - frappe/www/me.py | 1 - frappe/www/message.py | 1 - frappe/www/printview.py | 17 +++---- frappe/www/profile.py | 2 - frappe/www/qrcode.py | 4 +- frappe/www/robots.py | 2 +- frappe/www/rss.py | 3 +- frappe/www/search.py | 2 +- frappe/www/sitemap.py | 9 ++-- frappe/www/third_party_apps.py | 2 +- frappe/www/unsubscribe.py | 2 +- frappe/www/update_password.py | 2 - frappe/www/website_script.py | 1 - setup.py | 2 - 865 files changed, 527 insertions(+), 1718 deletions(-) diff --git a/frappe/api.py b/frappe/api.py index 6427cbfbd8..36d51e894c 100644 --- a/frappe/api.py +++ b/frappe/api.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - import base64 import binascii import json diff --git a/frappe/app.py b/frappe/app.py index 64befdf531..6f5023be93 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -1,10 +1,8 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import os -from six import iteritems import logging from werkzeug.local import LocalManager @@ -191,8 +189,9 @@ def make_form_dict(request): frappe.throw(_("Invalid request arguments")) try: - frappe.local.form_dict = frappe._dict({ k:v[0] if isinstance(v, (list, tuple)) else v \ - for k, v in iteritems(args) }) + frappe.local.form_dict = frappe._dict({ + k: v[0] if isinstance(v, (list, tuple)) else v for k, v in args.items() + }) except IndexError: frappe.local.form_dict = frappe._dict(args) diff --git a/frappe/auth.py b/frappe/auth.py index 73cb8e8c15..ef79d96ddb 100644 --- a/frappe/auth.py +++ b/frappe/auth.py @@ -1,9 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals import datetime - from frappe import _ import frappe import frappe.database @@ -19,8 +16,7 @@ from frappe.core.doctype.activity_log.activity_log import add_authentication_log from frappe.twofactor import (should_run_2fa, authenticate_for_2factor, confirm_otp_token, get_cached_user_pass) from frappe.website.utils import get_home_page - -from six.moves.urllib.parse import quote +from urllib.parse import quote class HTTPRequest: diff --git a/frappe/automation/doctype/assignment_rule/assignment_rule.py b/frappe/automation/doctype/assignment_rule/assignment_rule.py index c673d5ceeb..ef579aca01 100644 --- a/frappe/automation/doctype/assignment_rule/assignment_rule.py +++ b/frappe/automation/doctype/assignment_rule/assignment_rule.py @@ -2,8 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import frappe from frappe.model.document import Document from frappe.desk.form import assign_to diff --git a/frappe/automation/doctype/assignment_rule/test_assignment_rule.py b/frappe/automation/doctype/assignment_rule/test_assignment_rule.py index cb1e0ff8f4..e287b83965 100644 --- a/frappe/automation/doctype/assignment_rule/test_assignment_rule.py +++ b/frappe/automation/doctype/assignment_rule/test_assignment_rule.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.utils import random_string diff --git a/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py b/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py index 27f9aa40e1..c734495c39 100644 --- a/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py +++ b/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py b/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py index ee8081c6d8..4d65efd5c1 100644 --- a/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py +++ b/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py index bf05baf5b6..998e73a42c 100644 --- a/frappe/automation/doctype/auto_repeat/auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from datetime import timedelta diff --git a/frappe/automation/doctype/auto_repeat/test_auto_repeat.py b/frappe/automation/doctype/auto_repeat/test_auto_repeat.py index 6ceb4dba72..567c1161af 100644 --- a/frappe/automation/doctype/auto_repeat/test_auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/test_auto_repeat.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest import frappe diff --git a/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py b/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py index 3a7ced1370..8af3284cde 100644 --- a/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py +++ b/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/milestone/milestone.py b/frappe/automation/doctype/milestone/milestone.py index 64c073a378..6ea6d7544a 100644 --- a/frappe/automation/doctype/milestone/milestone.py +++ b/frappe/automation/doctype/milestone/milestone.py @@ -2,8 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import frappe from frappe.model.document import Document diff --git a/frappe/automation/doctype/milestone/test_milestone.py b/frappe/automation/doctype/milestone/test_milestone.py index 75602d48db..175c56e552 100644 --- a/frappe/automation/doctype/milestone/test_milestone.py +++ b/frappe/automation/doctype/milestone/test_milestone.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - #import frappe import unittest diff --git a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py index 388620bfb4..125cad7fa8 100644 --- a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py @@ -2,8 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import frappe from frappe.model.document import Document import frappe.cache_manager diff --git a/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py index 05db3b025e..21b2779018 100644 --- a/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import frappe.cache_manager import unittest diff --git a/frappe/boot.py b/frappe/boot.py index 0dfcb8d1b4..0589e32ac8 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -1,10 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals - -from six import iteritems, text_type - """ bootstrap client session """ @@ -75,7 +70,7 @@ def get_bootinfo(): frappe.get_attr(method)(bootinfo) if bootinfo.lang: - bootinfo.lang = text_type(bootinfo.lang) + bootinfo.lang = str(bootinfo.lang) bootinfo.versions = {k: v['version'] for k, v in get_versions().items()} bootinfo.error_report_email = frappe.conf.error_report_email @@ -220,7 +215,7 @@ def load_translations(bootinfo): messages[name] = frappe._(name) # only untranslated - messages = {k:v for k, v in iteritems(messages) if k!=v} + messages = {k: v for k, v in messages.items() if k!=v} bootinfo["__messages"] = messages diff --git a/frappe/build.py b/frappe/build.py index c970ae3a28..6e4bf2b533 100644 --- a/frappe/build.py +++ b/frappe/build.py @@ -1,11 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - import os import re import json import shutil import subprocess +from io import StringIO from tempfile import mkdtemp, mktemp from distutils.spawn import find_executable @@ -402,8 +402,6 @@ def get_build_maps(): def pack(target, sources, no_compress, verbose): - from six import StringIO - outtype, outtxt = target.split(".")[-1], "" jsm = JavascriptMinify() diff --git a/frappe/cache_manager.py b/frappe/cache_manager.py index 7330c83102..52fba4568d 100644 --- a/frappe/cache_manager.py +++ b/frappe/cache_manager.py @@ -1,8 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, json from frappe.model.document import Document from frappe.desk.notifications import (delete_notification_count_for, diff --git a/frappe/chat/__init__.py b/frappe/chat/__init__.py index dea0030839..4c9b1c5db7 100644 --- a/frappe/chat/__init__.py +++ b/frappe/chat/__init__.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe import _ diff --git a/frappe/chat/doctype/chat_message/chat_message.py b/frappe/chat/doctype/chat_message/chat_message.py index 5549aaa657..bc470a5e9c 100644 --- a/frappe/chat/doctype/chat_message/chat_message.py +++ b/frappe/chat/doctype/chat_message/chat_message.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - standard imports import json diff --git a/frappe/chat/doctype/chat_profile/chat_profile.py b/frappe/chat/doctype/chat_profile/chat_profile.py index 698d992d35..da10a836c4 100644 --- a/frappe/chat/doctype/chat_profile/chat_profile.py +++ b/frappe/chat/doctype/chat_profile/chat_profile.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - module imports from frappe.model.document import Document from frappe import _ diff --git a/frappe/chat/doctype/chat_room/chat_room.py b/frappe/chat/doctype/chat_room/chat_room.py index 609acaef7d..bdbee44d7a 100644 --- a/frappe/chat/doctype/chat_room/chat_room.py +++ b/frappe/chat/doctype/chat_room/chat_room.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - module imports from frappe.model.document import Document from frappe import _ diff --git a/frappe/chat/doctype/chat_room_user/chat_room_user.py b/frappe/chat/doctype/chat_room_user/chat_room_user.py index f8e13add82..f6dbdc7659 100644 --- a/frappe/chat/doctype/chat_room_user/chat_room_user.py +++ b/frappe/chat/doctype/chat_room_user/chat_room_user.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - module imports from frappe.model.document import Document import frappe diff --git a/frappe/chat/doctype/chat_token/chat_token.py b/frappe/chat/doctype/chat_token/chat_token.py index 30a76ef5bd..63d69a58be 100644 --- a/frappe/chat/doctype/chat_token/chat_token.py +++ b/frappe/chat/doctype/chat_token/chat_token.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/chat/util/__init__.py b/frappe/chat/util/__init__.py index 15977af566..383df581cd 100644 --- a/frappe/chat/util/__init__.py +++ b/frappe/chat/util/__init__.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - module imports from frappe.chat.util.util import ( get_user_doc, diff --git a/frappe/chat/util/test_util.py b/frappe/chat/util/test_util.py index 6d44a63d31..e2d05a4024 100644 --- a/frappe/chat/util/test_util.py +++ b/frappe/chat/util/test_util.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - standard imports import unittest @@ -9,7 +7,6 @@ from frappe.chat.util import ( safe_json_loads ) import frappe -import six class TestChatUtil(unittest.TestCase): def test_safe_json_loads(self): @@ -20,7 +17,7 @@ class TestChatUtil(unittest.TestCase): self.assertEqual(type(number), float) string = safe_json_loads("foobar") - self.assertEqual(type(string), six.text_type) + self.assertEqual(type(string), str) array = safe_json_loads('[{ "foo": "bar" }]') self.assertEqual(type(array), list) diff --git a/frappe/chat/util/util.py b/frappe/chat/util/util.py index 82df6dd127..b7e7991c2b 100644 --- a/frappe/chat/util/util.py +++ b/frappe/chat/util/util.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - standard imports import json from collections.abc import MutableMapping, MutableSequence, Sequence diff --git a/frappe/chat/website/__init__.py b/frappe/chat/website/__init__.py index f33f531cbf..12affd2782 100644 --- a/frappe/chat/website/__init__.py +++ b/frappe/chat/website/__init__.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.chat.util import filter_dict, safe_json_loads diff --git a/frappe/client.py b/frappe/client.py index a2e04452ff..66c457e893 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals import frappe from frappe import _ import frappe.model @@ -11,7 +9,6 @@ from frappe.utils import get_safe_filters from frappe.desk.reportview import validate_args from frappe.model.db_query import check_parent_permission -from six import iteritems, string_types, integer_types ''' Handle RESTful requests that are mapped to the `/api/resource` route. @@ -86,7 +83,7 @@ def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False, paren frappe.throw(_("No permission for {0}").format(doctype), frappe.PermissionError) filters = get_safe_filters(filters) - if isinstance(filters, string_types): + if isinstance(filters, str): filters = {"name": filters} try: @@ -135,7 +132,7 @@ def set_value(doctype, name, fieldname, value=None): if not value: values = fieldname - if isinstance(fieldname, string_types): + if isinstance(fieldname, str): try: values = json.loads(fieldname) except ValueError: @@ -161,7 +158,7 @@ def insert(doc=None): '''Insert a document :param doc: JSON or dict object to be inserted''' - if isinstance(doc, string_types): + if isinstance(doc, str): doc = json.loads(doc) if doc.get("parent") and doc.get("parenttype"): @@ -179,7 +176,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, string_types): + if isinstance(docs, str): docs = json.loads(docs) out = [] @@ -205,7 +202,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, string_types): + if isinstance(doc, str): doc = json.loads(doc) doc = frappe.get_doc(doc) @@ -228,7 +225,7 @@ def submit(doc): '''Submit a document :param doc: JSON or dict object to be submitted remotely''' - if isinstance(doc, string_types): + if isinstance(doc, str): doc = json.loads(doc) doc = frappe.get_doc(doc) @@ -266,7 +263,7 @@ def make_width_property_setter(doc): '''Set width Property Setter :param doc: Property Setter document with `width` property''' - if isinstance(doc, string_types): + if isinstance(doc, str): doc = json.loads(doc) if doc["doctype"]=="Property Setter" and doc["property"]=="width": frappe.get_doc(doc).insert(ignore_permissions = True) @@ -280,7 +277,7 @@ def bulk_update(docs): failed_docs = [] for doc in docs: try: - ddoc = {key: val for key, val in iteritems(doc) if key not in ['doctype', 'docname']} + ddoc = {key: val for key, val in doc.items() if key not in ['doctype', 'docname']} doctype = doc['doctype'] docname = doc['docname'] doc = frappe.get_doc(doctype, docname) diff --git a/frappe/commands/__init__.py b/frappe/commands/__init__.py index e521acc9ad..be9d107025 100644 --- a/frappe/commands/__init__.py +++ b/frappe/commands/__init__.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals, absolute_import, print_function import sys import click import cProfile @@ -10,7 +9,7 @@ import frappe import frappe.utils import subprocess # nosec from functools import wraps -from six import StringIO +from io import StringIO from os import environ click.disable_unicode_literals_warning = True diff --git a/frappe/commands/scheduler.py b/frappe/commands/scheduler.py index e9638800cd..d69ebb3024 100755 --- a/frappe/commands/scheduler.py +++ b/frappe/commands/scheduler.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals, absolute_import, print_function import click import sys import frappe diff --git a/frappe/commands/translate.py b/frappe/commands/translate.py index 48a7fd1db7..68d210eaaa 100644 --- a/frappe/commands/translate.py +++ b/frappe/commands/translate.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals, absolute_import, print_function import click from frappe.commands import pass_context, get_site from frappe.exceptions import SiteNotSpecifiedError diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index 4da0f6bb78..bcb1749644 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -222,7 +222,7 @@ def execute(context, method, args=None, kwargs=None, profile=False): if profile: import pstats - from six import StringIO + from io import StringIO pr.disable() s = StringIO() diff --git a/frappe/config/__init__.py b/frappe/config/__init__.py index 30be82d0df..62a877be24 100644 --- a/frappe/config/__init__.py +++ b/frappe/config/__init__.py @@ -1,6 +1,3 @@ -from __future__ import unicode_literals -import json -from six import iteritems import frappe from frappe import _ from frappe.desk.moduleview import (get_data, get_onboard_items, config_exists, get_module_link_items_from_list) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 3ca9547188..f21819ad98 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/contacts/doctype/address/test_address.py b/frappe/contacts/doctype/address/test_address.py index d6d4e50491..ed61b6f0ee 100644 --- a/frappe/contacts/doctype/address/test_address.py +++ b/frappe/contacts/doctype/address/test_address.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe, unittest from frappe.contacts.doctype.address.address import get_address_display diff --git a/frappe/contacts/doctype/address_template/address_template.py b/frappe/contacts/doctype/address_template/address_template.py index 2ca9aebff5..2d69a792ab 100644 --- a/frappe/contacts/doctype/address_template/address_template.py +++ b/frappe/contacts/doctype/address_template/address_template.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import cint diff --git a/frappe/contacts/doctype/address_template/test_address_template.py b/frappe/contacts/doctype/address_template/test_address_template.py index f40b56e7d9..6b519a3bb7 100644 --- a/frappe/contacts/doctype/address_template/test_address_template.py +++ b/frappe/contacts/doctype/address_template/test_address_template.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe, unittest class TestAddressTemplate(unittest.TestCase): @@ -42,4 +40,4 @@ class TestAddressTemplate(unittest.TestCase): "doctype": "Address Template", "country": 'Brazil', "template": template - }).insert() \ No newline at end of file + }).insert() \ No newline at end of file diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index c8af99bebc..d1dd1f1010 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt - import frappe from frappe.utils import cstr, has_gravatar from frappe import _ diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index b131428696..6c6089edeb 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/contacts/doctype/contact_email/contact_email.py b/frappe/contacts/doctype/contact_email/contact_email.py index 04e8b22989..5fc2fef316 100644 --- a/frappe/contacts/doctype/contact_email/contact_email.py +++ b/frappe/contacts/doctype/contact_email/contact_email.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.py b/frappe/contacts/doctype/contact_phone/contact_phone.py index fe2f86a4bd..63f5f73cf1 100644 --- a/frappe/contacts/doctype/contact_phone/contact_phone.py +++ b/frappe/contacts/doctype/contact_phone/contact_phone.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/contacts/doctype/gender/gender.py b/frappe/contacts/doctype/gender/gender.py index bfca5830c1..319800de7e 100644 --- a/frappe/contacts/doctype/gender/gender.py +++ b/frappe/contacts/doctype/gender/gender.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class Gender(Document): diff --git a/frappe/contacts/doctype/gender/test_gender.py b/frappe/contacts/doctype/gender/test_gender.py index fbe3473bc3..071ed47df0 100644 --- a/frappe/contacts/doctype/gender/test_gender.py +++ b/frappe/contacts/doctype/gender/test_gender.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestGender(unittest.TestCase): diff --git a/frappe/contacts/doctype/salutation/salutation.py b/frappe/contacts/doctype/salutation/salutation.py index d9e4528c7d..d79ad66845 100644 --- a/frappe/contacts/doctype/salutation/salutation.py +++ b/frappe/contacts/doctype/salutation/salutation.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class Salutation(Document): diff --git a/frappe/contacts/doctype/salutation/test_salutation.py b/frappe/contacts/doctype/salutation/test_salutation.py index 63d603e6a4..e2e9075855 100644 --- a/frappe/contacts/doctype/salutation/test_salutation.py +++ b/frappe/contacts/doctype/salutation/test_salutation.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestSalutation(unittest.TestCase): diff --git a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py index 1b3982f251..bf48b6b185 100644 --- a/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/addresses_and_contacts.py @@ -1,8 +1,5 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt - -from __future__ import unicode_literals -from six import iteritems import frappe from frappe import _ @@ -58,7 +55,7 @@ def get_reference_addresses_and_contact(reference_doctype, reference_name): reference_details = get_reference_details(reference_doctype, "Address", reference_list, reference_details) reference_details = get_reference_details(reference_doctype, "Contact", reference_list, reference_details) - for reference_name, details in iteritems(reference_details): + for reference_name, details in reference_details.items(): addresses = details.get("address", []) contacts = details.get("contact", []) if not any([addresses, contacts]): diff --git a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py index 9e98dcf6f6..f539722175 100644 --- a/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py +++ b/frappe/contacts/report/addresses_and_contacts/test_addresses_and_contacts.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe import frappe.defaults import unittest diff --git a/frappe/core/__init__.py b/frappe/core/__init__.py index 998a299158..f064a66c17 100644 --- a/frappe/core/__init__.py +++ b/frappe/core/__init__.py @@ -1,4 +1,2 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals \ No newline at end of file diff --git a/frappe/core/doctype/__init__.py b/frappe/core/doctype/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/__init__.py +++ b/frappe/core/doctype/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/access_log/access_log.py b/frappe/core/doctype/access_log/access_log.py index 43381e7f2e..d2fbee108b 100644 --- a/frappe/core/doctype/access_log/access_log.py +++ b/frappe/core/doctype/access_log/access_log.py @@ -3,8 +3,6 @@ # For license information, please see license.txt # imports - standard imports -from __future__ import unicode_literals - # imports - module imports import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/activity_log/activity_log.py b/frappe/core/doctype/activity_log/activity_log.py index 98dc91806d..efec0dc217 100644 --- a/frappe/core/doctype/activity_log/activity_log.py +++ b/frappe/core/doctype/activity_log/activity_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe import _ from frappe.utils import get_fullname, now from frappe.model.document import Document diff --git a/frappe/core/doctype/activity_log/feed.py b/frappe/core/doctype/activity_log/feed.py index f51692fe9f..caa3cae613 100644 --- a/frappe/core/doctype/activity_log/feed.py +++ b/frappe/core/doctype/activity_log/feed.py @@ -1,13 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals import frappe import frappe.permissions from frappe.utils import get_fullname from frappe import _ from frappe.core.doctype.activity_log.activity_log import add_authentication_log -from six import string_types def update_feed(doc, method=None): if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_import: @@ -23,7 +21,7 @@ def update_feed(doc, method=None): feed = doc.get_feed() if feed: - if isinstance(feed, string_types): + if isinstance(feed, str): feed = {"subject": feed} feed = frappe._dict(feed) diff --git a/frappe/core/doctype/activity_log/test_activity_log.py b/frappe/core/doctype/activity_log/test_activity_log.py index f33c7a1c85..ed7b70cca1 100644 --- a/frappe/core/doctype/activity_log/test_activity_log.py +++ b/frappe/core/doctype/activity_log/test_activity_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import time diff --git a/frappe/core/doctype/block_module/block_module.py b/frappe/core/doctype/block_module/block_module.py index e7bb3cf045..d9723f9170 100644 --- a/frappe/core/doctype/block_module/block_module.py +++ b/frappe/core/doctype/block_module/block_module.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/comment/comment.py b/frappe/core/doctype/comment/comment.py index ad5d60500b..e29bae25a2 100644 --- a/frappe/core/doctype/comment/comment.py +++ b/frappe/core/doctype/comment/comment.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt - -from __future__ import unicode_literals, absolute_import import frappe from frappe import _ import json diff --git a/frappe/core/doctype/comment/test_comment.py b/frappe/core/doctype/comment/test_comment.py index 3cf8fbaa3f..13db92e7a8 100644 --- a/frappe/core/doctype/comment/test_comment.py +++ b/frappe/core/doctype/comment/test_comment.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe, json import unittest diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 5ebf714645..ed17ffc0aa 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals, absolute_import from collections import Counter import frappe from frappe import _ @@ -13,7 +12,7 @@ from frappe.utils.bot import BotReply from frappe.utils import parse_addr from frappe.core.doctype.comment.comment import update_comment_in_doc from email.utils import parseaddr -from six.moves.urllib.parse import unquote +from urllib.parse import unquote from frappe.utils.user import is_system_user from frappe.contacts.doctype.contact.contact import get_contact_name from frappe.automation.doctype.assignment_rule.assignment_rule import apply as apply_assignment_rule diff --git a/frappe/core/doctype/communication/email.py b/frappe/core/doctype/communication/email.py index d3017055cf..c28956b41f 100755 --- a/frappe/core/doctype/communication/email.py +++ b/frappe/core/doctype/communication/email.py @@ -1,9 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -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 @@ -77,7 +74,7 @@ def make(doctype=None, name=None, content=None, subject=None, sent_or_received = comm.save(ignore_permissions=True) - if isinstance(attachments, string_types): + if isinstance(attachments, str): attachments = json.loads(attachments) # if not committed, delayed task doesn't find the communication @@ -249,11 +246,11 @@ def prepare_to_notify(doc, print_html=None, print_format=None, attachments=None) "name":doc.reference_name, "print_format":print_format, "html":print_html}) if attachments: - if isinstance(attachments, string_types): + if isinstance(attachments, str): attachments = json.loads(attachments) for a in attachments: - if isinstance(a, string_types): + if isinstance(a, str): # is it a filename? try: # check for both filename and file id @@ -355,7 +352,7 @@ def add_attachments(name, attachments): '''Add attachments to the given Communication''' # loop through attachments for a in attachments: - if isinstance(a, string_types): + if isinstance(a, str): attach = frappe.db.get_value("File", {"name":a}, ["file_name", "file_url", "is_private"], as_dict=1) diff --git a/frappe/core/doctype/communication/test_communication.py b/frappe/core/doctype/communication/test_communication.py index 6df90baaae..5b400398a5 100644 --- a/frappe/core/doctype/communication/test_communication.py +++ b/frappe/core/doctype/communication/test_communication.py @@ -1,10 +1,8 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest -from six.moves.urllib.parse import quote +from urllib.parse import quote test_records = frappe.get_test_records('Communication') diff --git a/frappe/core/doctype/communication_link/communication_link.py b/frappe/core/doctype/communication_link/communication_link.py index d1612ef57e..d3307d1d32 100644 --- a/frappe/core/doctype/communication_link/communication_link.py +++ b/frappe/core/doctype/communication_link/communication_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.py b/frappe/core/doctype/custom_docperm/custom_docperm.py index cce9788b73..225f5db79b 100644 --- a/frappe/core/doctype/custom_docperm/custom_docperm.py +++ b/frappe/core/doctype/custom_docperm/custom_docperm.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/custom_docperm/test_custom_docperm.py b/frappe/core/doctype/custom_docperm/test_custom_docperm.py index bd6e17ccc9..6e0c82d1db 100644 --- a/frappe/core/doctype/custom_docperm/test_custom_docperm.py +++ b/frappe/core/doctype/custom_docperm/test_custom_docperm.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/custom_role/custom_role.py b/frappe/core/doctype/custom_role/custom_role.py index 25257e1a23..89e478dd38 100644 --- a/frappe/core/doctype/custom_role/custom_role.py +++ b/frappe/core/doctype/custom_role/custom_role.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/custom_role/test_custom_role.py b/frappe/core/doctype/custom_role/test_custom_role.py index 670b494b10..0ad77524fa 100644 --- a/frappe/core/doctype/custom_role/test_custom_role.py +++ b/frappe/core/doctype/custom_role/test_custom_role.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/data_export/data_export.py b/frappe/core/doctype/data_export/data_export.py index fb4fae26d5..c376b25230 100644 --- a/frappe/core/doctype/data_export/data_export.py +++ b/frappe/core/doctype/data_export/data_export.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class DataExport(Document): diff --git a/frappe/core/doctype/data_export/exporter.py b/frappe/core/doctype/data_export/exporter.py index 5d600cc0db..389948449e 100644 --- a/frappe/core/doctype/data_export/exporter.py +++ b/frappe/core/doctype/data_export/exporter.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe import _ import frappe.permissions @@ -10,7 +8,6 @@ import re, csv, os from frappe.utils.csvutils import UnicodeWriter from frappe.utils import cstr, formatdate, format_datetime, parse_json, cint, format_duration from frappe.core.doctype.data_import_legacy.importer import get_data_keys -from six import string_types from frappe.core.doctype.access_log.access_log import make_access_log reflags = { @@ -57,7 +54,7 @@ class DataExporter: self.docs_to_export = {} if self.doctype: - if isinstance(self.doctype, string_types): + if isinstance(self.doctype, str): self.doctype = [self.doctype] if len(self.doctype) > 1: diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index d3f981add4..fed90b75ce 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import os import io import frappe diff --git a/frappe/core/doctype/data_import/test_data_import.py b/frappe/core/doctype/data_import/test_data_import.py index 15fd57744a..c9366a97ba 100644 --- a/frappe/core/doctype/data_import/test_data_import.py +++ b/frappe/core/doctype/data_import/test_data_import.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/data_import/test_exporter.py b/frappe/core/doctype/data_import/test_exporter.py index 8415af2e63..dfe9926906 100644 --- a/frappe/core/doctype/data_import/test_exporter.py +++ b/frappe/core/doctype/data_import/test_exporter.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest import frappe from frappe.core.doctype.data_import.exporter import Exporter diff --git a/frappe/core/doctype/data_import/test_importer.py b/frappe/core/doctype/data_import/test_importer.py index f76d4504a4..54a7788a2d 100644 --- a/frappe/core/doctype/data_import/test_importer.py +++ b/frappe/core/doctype/data_import/test_importer.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest import frappe from frappe.core.doctype.data_import.importer import Importer diff --git a/frappe/core/doctype/data_import_legacy/importer.py b/frappe/core/doctype/data_import_legacy/importer.py index 35569c7186..4080e70418 100644 --- a/frappe/core/doctype/data_import_legacy/importer.py +++ b/frappe/core/doctype/data_import_legacy/importer.py @@ -3,9 +3,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals, print_function - -from six.moves import range import requests import frappe, json import frappe.permissions @@ -16,7 +13,6 @@ from frappe.utils.csvutils import getlink from frappe.utils.dateutils import parse_date from frappe.utils import cint, cstr, flt, getdate, get_datetime, get_url, get_absolute_url, duration_to_seconds -from six import string_types @frappe.whitelist() @@ -42,7 +38,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, frappe.cache().hdel("lang", user) frappe.set_user_lang(user) - if data_import_doc and isinstance(data_import_doc, string_types): + if data_import_doc and isinstance(data_import_doc, str): data_import_doc = frappe.get_doc("Data Import Legacy", data_import_doc) if data_import_doc and from_data_import == "Yes": no_email = data_import_doc.no_email @@ -152,7 +148,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], string_types): + if d[fieldname] and isinstance(d[fieldname], str): d[fieldname] = getdate(parse_date(d[fieldname])) elif fieldtype == "Datetime": if d[fieldname]: diff --git a/frappe/core/doctype/data_import_legacy/test_data_import_legacy.py b/frappe/core/doctype/data_import_legacy/test_data_import_legacy.py index e5b244e6a0..6f9964e8f5 100644 --- a/frappe/core/doctype/data_import_legacy/test_data_import_legacy.py +++ b/frappe/core/doctype/data_import_legacy/test_data_import_legacy.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/defaultvalue/__init__.py b/frappe/core/doctype/defaultvalue/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/defaultvalue/__init__.py +++ b/frappe/core/doctype/defaultvalue/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/defaultvalue/defaultvalue.py b/frappe/core/doctype/defaultvalue/defaultvalue.py index d9cc145053..0ae088ee96 100644 --- a/frappe/core/doctype/defaultvalue/defaultvalue.py +++ b/frappe/core/doctype/defaultvalue/defaultvalue.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/deleted_document/deleted_document.py b/frappe/core/doctype/deleted_document/deleted_document.py index 116fc5caf5..f4109c8197 100644 --- a/frappe/core/doctype/deleted_document/deleted_document.py +++ b/frappe/core/doctype/deleted_document/deleted_document.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import json from frappe.desk.doctype.bulk_update.bulk_update import show_progress diff --git a/frappe/core/doctype/deleted_document/test_deleted_document.py b/frappe/core/doctype/deleted_document/test_deleted_document.py index c45a2bd180..d9dc2bb2d1 100644 --- a/frappe/core/doctype/deleted_document/test_deleted_document.py +++ b/frappe/core/doctype/deleted_document/test_deleted_document.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/docfield/__init__.py b/frappe/core/doctype/docfield/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/docfield/__init__.py +++ b/frappe/core/doctype/docfield/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/docfield/docfield.py b/frappe/core/doctype/docfield/docfield.py index b6e2d9b67d..175cba3c7c 100644 --- a/frappe/core/doctype/docfield/docfield.py +++ b/frappe/core/doctype/docfield/docfield.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/docperm/__init__.py b/frappe/core/doctype/docperm/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/docperm/__init__.py +++ b/frappe/core/doctype/docperm/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/docperm/docperm.py b/frappe/core/doctype/docperm/docperm.py index 36ed9acbe6..9732cde920 100644 --- a/frappe/core/doctype/docperm/docperm.py +++ b/frappe/core/doctype/docperm/docperm.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/docshare/docshare.py b/frappe/core/doctype/docshare/docshare.py index 26ed53a87d..2d7b6b9e48 100644 --- a/frappe/core/doctype/docshare/docshare.py +++ b/frappe/core/doctype/docshare/docshare.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ diff --git a/frappe/core/doctype/docshare/test_docshare.py b/frappe/core/doctype/docshare/test_docshare.py index 9c424eb4d7..6551dabbea 100644 --- a/frappe/core/doctype/docshare/test_docshare.py +++ b/frappe/core/doctype/docshare/test_docshare.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals import frappe import frappe.share import unittest diff --git a/frappe/core/doctype/doctype/__init__.py b/frappe/core/doctype/doctype/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/doctype/__init__.py +++ b/frappe/core/doctype/doctype/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index f9dbeb0907..8a96fc89f6 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -2,15 +2,10 @@ # MIT License. See license.txt # imports - standard imports -from __future__ import unicode_literals import re, copy, os, shutil import json from frappe.cache_manager import clear_user_cache, clear_controller_cache -# imports - third party imports -import six -from six import iteritems - # imports - module imports import frappe import frappe.website.render @@ -486,7 +481,7 @@ class DocType(Document): # remove null and empty fields def remove_null_fields(o): to_remove = [] - for attr, value in iteritems(o): + for attr, value in o.items(): if isinstance(value, list): for v in value: remove_null_fields(v) @@ -670,7 +665,7 @@ class DocType(Document): if not name: name = self.name - flags = {"flags": re.ASCII} if six.PY3 else {} + flags = {"flags": re.ASCII} # a DocType name should not start or end with an empty space if re.search(r"^[ \t\n\r]+|[ \t\n\r]+$", name, **flags): diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 9c492d2c36..1e1a01a685 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.core.doctype.doctype.doctype import (UniqueFieldnameError, diff --git a/frappe/core/doctype/doctype_action/doctype_action.py b/frappe/core/doctype/doctype_action/doctype_action.py index a745c7da40..203b06ec1b 100644 --- a/frappe/core/doctype/doctype_action/doctype_action.py +++ b/frappe/core/doctype/doctype_action/doctype_action.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/doctype_link/doctype_link.py b/frappe/core/doctype/doctype_link/doctype_link.py index efe8b09809..07e0efdace 100644 --- a/frappe/core/doctype/doctype_link/doctype_link.py +++ b/frappe/core/doctype/doctype_link/doctype_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.py b/frappe/core/doctype/document_naming_rule/document_naming_rule.py index 4b34293af6..4f500a2abf 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils.data import evaluate_filters diff --git a/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py b/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py index 1b91f6a0cf..2206d173d7 100644 --- a/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py b/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py index 0895c9f93f..dfca052d95 100644 --- a/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py +++ b/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py b/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py index 6f1376dc62..643e963bd7 100644 --- a/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py +++ b/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/domain/domain.py b/frappe/core/doctype/domain/domain.py index a4e9f503ab..681824bb02 100644 --- a/frappe/core/doctype/domain/domain.py +++ b/frappe/core/doctype/domain/domain.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/domain/test_domain.py b/frappe/core/doctype/domain/test_domain.py index 8e0bc65c54..c2686a7566 100644 --- a/frappe/core/doctype/domain/test_domain.py +++ b/frappe/core/doctype/domain/test_domain.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/domain_settings/domain_settings.py b/frappe/core/doctype/domain_settings/domain_settings.py index d4d394a5cb..7ad0aeff21 100644 --- a/frappe/core/doctype/domain_settings/domain_settings.py +++ b/frappe/core/doctype/domain_settings/domain_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/dynamic_link/dynamic_link.py b/frappe/core/doctype/dynamic_link/dynamic_link.py index 30e0ef1f1f..a7adb9ae72 100644 --- a/frappe/core/doctype/dynamic_link/dynamic_link.py +++ b/frappe/core/doctype/dynamic_link/dynamic_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/error_log/error_log.py b/frappe/core/doctype/error_log/error_log.py index ec02aaf446..8223238c57 100644 --- a/frappe/core/doctype/error_log/error_log.py +++ b/frappe/core/doctype/error_log/error_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/error_log/test_error_log.py b/frappe/core/doctype/error_log/test_error_log.py index d93fe07c61..d7444ab2a7 100644 --- a/frappe/core/doctype/error_log/test_error_log.py +++ b/frappe/core/doctype/error_log/test_error_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/error_snapshot/error_snapshot.py b/frappe/core/doctype/error_snapshot/error_snapshot.py index 5badaad63f..247a796a6b 100644 --- a/frappe/core/doctype/error_snapshot/error_snapshot.py +++ b/frappe/core/doctype/error_snapshot/error_snapshot.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/error_snapshot/test_error_snapshot.py b/frappe/core/doctype/error_snapshot/test_error_snapshot.py index b6438eae1d..135136294a 100644 --- a/frappe/core/doctype/error_snapshot/test_error_snapshot.py +++ b/frappe/core/doctype/error_snapshot/test_error_snapshot.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index c4c37e6d13..b4bfe1d21b 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -7,8 +7,6 @@ record of files naming for same name files: file.gif, file-1.gif, file-2.gif etc """ -from __future__ import unicode_literals - import base64 import hashlib import imghdr @@ -23,8 +21,8 @@ import zipfile import requests import requests.exceptions from PIL import Image, ImageFile, ImageOps -from six import PY2, StringIO, string_types, text_type -from six.moves.urllib.parse import quote, unquote +from io import StringIO +from urllib.parse import quote, unquote import frappe from frappe import _, conf @@ -382,18 +380,14 @@ class File(Document): file_path = self.get_full_path() # read the file - if PY2: - with open(encode(file_path)) as f: - content = f.read() - else: - with io.open(encode(file_path), mode='rb') as f: - content = f.read() - try: - # for plain text files - content = content.decode() - except UnicodeDecodeError: - # for .png, .jpg, etc - pass + with io.open(encode(file_path), mode='rb') as f: + content = f.read() + try: + # for plain text files + content = content.decode() + except UnicodeDecodeError: + # for .png, .jpg, etc + pass return content @@ -430,7 +424,7 @@ class File(Document): frappe.create_folder(file_path) # write the file self.content = self.get_content() - if isinstance(self.content, text_type): + if isinstance(self.content, str): self.content = self.content.encode() with open(os.path.join(file_path.encode('utf-8'), self.file_name.encode('utf-8')), 'wb+') as f: f.write(self.content) @@ -483,7 +477,7 @@ class File(Document): self.content = content if decode: - if isinstance(content, text_type): + if isinstance(content, str): self.content = content.encode("utf-8") if b"," in self.content: @@ -632,7 +626,7 @@ def create_new_folder(file_name, folder): @frappe.whitelist() def move_file(file_list, new_parent, old_parent): - if isinstance(file_list, string_types): + if isinstance(file_list, str): file_list = json.loads(file_list) for file_obj in file_list: @@ -834,7 +828,7 @@ def remove_file_by_url(file_url, doctype=None, name=None): def get_content_hash(content): - if isinstance(content, text_type): + if isinstance(content, str): content = content.encode() return hashlib.md5(content).hexdigest() #nosec @@ -887,8 +881,8 @@ def extract_images_from_html(doc, content): filename = headers.split("filename=")[-1] # decode filename - if not isinstance(filename, text_type): - filename = text_type(filename, 'utf-8') + if not isinstance(filename, str): + filename = str(filename, 'utf-8') else: mtype = headers.split(";")[0] filename = get_random_filename(content_type=mtype) @@ -911,7 +905,7 @@ def extract_images_from_html(doc, content): return ']*src\s*=\s*["\'](?=data:)(.*?)["\']', _save_file, content) return content @@ -941,7 +935,7 @@ def get_attached_images(doctype, names): '''get list of image urls attached in form returns {name: ['image.jpg', 'image.png']}''' - if isinstance(names, string_types): + if isinstance(names, str): names = json.loads(names) img_urls = frappe.db.get_list('File', filters={ diff --git a/frappe/core/doctype/file/test_file.py b/frappe/core/doctype/file/test_file.py index 2596fe94d0..649010c468 100644 --- a/frappe/core/doctype/file/test_file.py +++ b/frappe/core/doctype/file/test_file.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import base64 import frappe import os diff --git a/frappe/core/doctype/has_domain/has_domain.py b/frappe/core/doctype/has_domain/has_domain.py index 6381996035..2220656a2e 100644 --- a/frappe/core/doctype/has_domain/has_domain.py +++ b/frappe/core/doctype/has_domain/has_domain.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/has_role/has_role.py b/frappe/core/doctype/has_role/has_role.py index 45e76c85a1..51d86c7b0a 100644 --- a/frappe/core/doctype/has_role/has_role.py +++ b/frappe/core/doctype/has_role/has_role.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/installed_application/installed_application.py b/frappe/core/doctype/installed_application/installed_application.py index 6bb12afc49..f53a6424eb 100644 --- a/frappe/core/doctype/installed_application/installed_application.py +++ b/frappe/core/doctype/installed_application/installed_application.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/installed_applications/installed_applications.py b/frappe/core/doctype/installed_applications/installed_applications.py index 4e6eadf07e..b61555f57e 100644 --- a/frappe/core/doctype/installed_applications/installed_applications.py +++ b/frappe/core/doctype/installed_applications/installed_applications.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/installed_applications/test_installed_applications.py b/frappe/core/doctype/installed_applications/test_installed_applications.py index ab9b849fa1..1d57fd2cd8 100644 --- a/frappe/core/doctype/installed_applications/test_installed_applications.py +++ b/frappe/core/doctype/installed_applications/test_installed_applications.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/language/language.py b/frappe/core/doctype/language/language.py index fb18abdf5e..01c8553e10 100644 --- a/frappe/core/doctype/language/language.py +++ b/frappe/core/doctype/language/language.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, json, re from frappe import _ from frappe.model.document import Document diff --git a/frappe/core/doctype/language/test_language.py b/frappe/core/doctype/language/test_language.py index a4f35dd77b..837594247f 100644 --- a/frappe/core/doctype/language/test_language.py +++ b/frappe/core/doctype/language/test_language.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/log_setting_user/log_setting_user.py b/frappe/core/doctype/log_setting_user/log_setting_user.py index df6d55f0a9..64728b2c2b 100644 --- a/frappe/core/doctype/log_setting_user/log_setting_user.py +++ b/frappe/core/doctype/log_setting_user/log_setting_user.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/log_setting_user/test_log_setting_user.py b/frappe/core/doctype/log_setting_user/test_log_setting_user.py index 507c02d87d..c58b8faa66 100644 --- a/frappe/core/doctype/log_setting_user/test_log_setting_user.py +++ b/frappe/core/doctype/log_setting_user/test_log_setting_user.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/log_settings/log_settings.py b/frappe/core/doctype/log_settings/log_settings.py index 08e61d3289..e73aa8dac1 100644 --- a/frappe/core/doctype/log_settings/log_settings.py +++ b/frappe/core/doctype/log_settings/log_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/core/doctype/log_settings/test_log_settings.py b/frappe/core/doctype/log_settings/test_log_settings.py index 2824c71c88..8e0c9c3f23 100644 --- a/frappe/core/doctype/log_settings/test_log_settings.py +++ b/frappe/core/doctype/log_settings/test_log_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/module_def/__init__.py b/frappe/core/doctype/module_def/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/module_def/__init__.py +++ b/frappe/core/doctype/module_def/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/module_def/module_def.py b/frappe/core/doctype/module_def/module_def.py index 7e63572162..68025c83bb 100644 --- a/frappe/core/doctype/module_def/module_def.py +++ b/frappe/core/doctype/module_def/module_def.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, os, json from frappe.model.document import Document diff --git a/frappe/core/doctype/module_def/test_module_def.py b/frappe/core/doctype/module_def/test_module_def.py index 1f9bea4768..3a3ceb4b57 100644 --- a/frappe/core/doctype/module_def/test_module_def.py +++ b/frappe/core/doctype/module_def/test_module_def.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/module_profile/module_profile.py b/frappe/core/doctype/module_profile/module_profile.py index 4f392353ac..373e5078d0 100644 --- a/frappe/core/doctype/module_profile/module_profile.py +++ b/frappe/core/doctype/module_profile/module_profile.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class ModuleProfile(Document): diff --git a/frappe/core/doctype/module_profile/test_module_profile.py b/frappe/core/doctype/module_profile/test_module_profile.py index 400053d22c..e0d9c13371 100644 --- a/frappe/core/doctype/module_profile/test_module_profile.py +++ b/frappe/core/doctype/module_profile/test_module_profile.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals import frappe import unittest diff --git a/frappe/core/doctype/navbar_item/navbar_item.py b/frappe/core/doctype/navbar_item/navbar_item.py index 614aee8eaf..a8fa611374 100644 --- a/frappe/core/doctype/navbar_item/navbar_item.py +++ b/frappe/core/doctype/navbar_item/navbar_item.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/navbar_item/test_navbar_item.py b/frappe/core/doctype/navbar_item/test_navbar_item.py index 192e8fe42a..85852a45e8 100644 --- a/frappe/core/doctype/navbar_item/test_navbar_item.py +++ b/frappe/core/doctype/navbar_item/test_navbar_item.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/navbar_settings/navbar_settings.py b/frappe/core/doctype/navbar_settings/navbar_settings.py index 2244bc9e4e..60aec67a00 100644 --- a/frappe/core/doctype/navbar_settings/navbar_settings.py +++ b/frappe/core/doctype/navbar_settings/navbar_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ diff --git a/frappe/core/doctype/navbar_settings/test_navbar_settings.py b/frappe/core/doctype/navbar_settings/test_navbar_settings.py index ed423b0f27..4d1ee72815 100644 --- a/frappe/core/doctype/navbar_settings/test_navbar_settings.py +++ b/frappe/core/doctype/navbar_settings/test_navbar_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/page/__init__.py b/frappe/core/doctype/page/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/page/__init__.py +++ b/frappe/core/doctype/page/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/page/page.py b/frappe/core/doctype/page/page.py index bdec350efd..0ba0e309dd 100644 --- a/frappe/core/doctype/page/page.py +++ b/frappe/core/doctype/page/page.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import os from frappe.model.document import Document @@ -11,7 +10,6 @@ from frappe import conf, _, safe_decode from frappe.desk.form.meta import get_code_files_via_hooks, get_js from frappe.desk.utils import validate_route_conflict from frappe.core.doctype.custom_role.custom_role import get_custom_allowed_roles -from six import text_type class Page(Document): def autoname(self): diff --git a/frappe/core/doctype/page/test_page.py b/frappe/core/doctype/page/test_page.py index f7b3952a5b..18b4aea2c8 100644 --- a/frappe/core/doctype/page/test_page.py +++ b/frappe/core/doctype/page/test_page.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/patch_log/patch_log.py b/frappe/core/doctype/patch_log/patch_log.py index 3103d44af4..cc66955eb8 100644 --- a/frappe/core/doctype/patch_log/patch_log.py +++ b/frappe/core/doctype/patch_log/patch_log.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/patch_log/test_patch_log.py b/frappe/core/doctype/patch_log/test_patch_log.py index 0a7f22a78b..d0690ecee0 100644 --- a/frappe/core/doctype/patch_log/test_patch_log.py +++ b/frappe/core/doctype/patch_log/test_patch_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/payment_gateway/payment_gateway.py b/frappe/core/doctype/payment_gateway/payment_gateway.py index 80799e311b..1459635b01 100644 --- a/frappe/core/doctype/payment_gateway/payment_gateway.py +++ b/frappe/core/doctype/payment_gateway/payment_gateway.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/payment_gateway/test_payment_gateway.py b/frappe/core/doctype/payment_gateway/test_payment_gateway.py index 2faf1a7fb4..66f899bd27 100644 --- a/frappe/core/doctype/payment_gateway/test_payment_gateway.py +++ b/frappe/core/doctype/payment_gateway/test_payment_gateway.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/prepared_report/prepared_report.py b/frappe/core/doctype/prepared_report/prepared_report.py index c27853f460..c68bb6a4f1 100644 --- a/frappe/core/doctype/prepared_report/prepared_report.py +++ b/frappe/core/doctype/prepared_report/prepared_report.py @@ -3,8 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals - import json import frappe diff --git a/frappe/core/doctype/prepared_report/test_prepared_report.py b/frappe/core/doctype/prepared_report/test_prepared_report.py index 17845be521..ef324dd01a 100644 --- a/frappe/core/doctype/prepared_report/test_prepared_report.py +++ b/frappe/core/doctype/prepared_report/test_prepared_report.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import json diff --git a/frappe/core/doctype/report/__init__.py b/frappe/core/doctype/report/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/report/__init__.py +++ b/frappe/core/doctype/report/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index 8a0f9a99f5..a5c61fa436 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals import frappe import json, datetime from frappe import _, scrub @@ -13,7 +11,6 @@ from frappe.modules import make_boilerplate from frappe.core.doctype.page.page import delete_custom_role from frappe.core.doctype.custom_role.custom_role import get_custom_allowed_roles from frappe.desk.reportview import append_totals_row -from six import iteritems from frappe.utils.safe_exec import safe_exec @@ -238,7 +235,7 @@ class Report(Document): _filters = params.get('filters') or [] if filters: - for key, value in iteritems(filters): + for key, value in filters.items(): condition, _value = '=', value if isinstance(value, (list, tuple)): condition, _value = value diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index d09799ca69..9d0c0b9af0 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals import frappe, json, os import unittest from frappe.desk.query_report import run, save_report diff --git a/frappe/core/doctype/report_column/report_column.py b/frappe/core/doctype/report_column/report_column.py index 69c88b7bda..f9078d820d 100644 --- a/frappe/core/doctype/report_column/report_column.py +++ b/frappe/core/doctype/report_column/report_column.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/report_filter/report_filter.py b/frappe/core/doctype/report_filter/report_filter.py index d85a1a5a65..ccdcc0eb6f 100644 --- a/frappe/core/doctype/report_filter/report_filter.py +++ b/frappe/core/doctype/report_filter/report_filter.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/role/__init__.py b/frappe/core/doctype/role/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/doctype/role/__init__.py +++ b/frappe/core/doctype/role/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/doctype/role/role.py b/frappe/core/doctype/role/role.py index a1523db0dd..02482c75ca 100644 --- a/frappe/core/doctype/role/role.py +++ b/frappe/core/doctype/role/role.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/role/test_role.py b/frappe/core/doctype/role/test_role.py index 6459a72c98..471f6cac43 100644 --- a/frappe/core/doctype/role/test_role.py +++ b/frappe/core/doctype/role/test_role.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py b/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py index 77b523987c..59f34a1483 100644 --- a/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py +++ b/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.core.doctype.report.report import is_prepared_report_disabled from frappe.model.document import Document diff --git a/frappe/core/doctype/role_profile/role_profile.py b/frappe/core/doctype/role_profile/role_profile.py index 4def834adb..0f58da5b5e 100644 --- a/frappe/core/doctype/role_profile/role_profile.py +++ b/frappe/core/doctype/role_profile/role_profile.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class RoleProfile(Document): diff --git a/frappe/core/doctype/role_profile/test_role_profile.py b/frappe/core/doctype/role_profile/test_role_profile.py index 975453e8d1..53e0a1b043 100644 --- a/frappe/core/doctype/role_profile/test_role_profile.py +++ b/frappe/core/doctype/role_profile/test_role_profile.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals import frappe import unittest diff --git a/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py b/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py index 26871c9adf..7f54a3b6ae 100644 --- a/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py +++ b/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py b/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py index 1e5290425b..85471d0d71 100644 --- a/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py +++ b/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py b/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py index d0a65defa4..a071cfe9a9 100644 --- a/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py +++ b/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.utils import get_datetime diff --git a/frappe/core/doctype/server_script/server_script.py b/frappe/core/doctype/server_script/server_script.py index f80a067cf1..d26fe5a188 100644 --- a/frappe/core/doctype/server_script/server_script.py +++ b/frappe/core/doctype/server_script/server_script.py @@ -2,8 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import ast from types import FunctionType, MethodType, ModuleType from typing import Dict, List diff --git a/frappe/core/doctype/server_script/test_server_script.py b/frappe/core/doctype/server_script/test_server_script.py index aac8b3deed..c39fcfa0d0 100644 --- a/frappe/core/doctype/server_script/test_server_script.py +++ b/frappe/core/doctype/server_script/test_server_script.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import requests diff --git a/frappe/core/doctype/session_default/session_default.py b/frappe/core/doctype/session_default/session_default.py index 8a8db46ff1..70ff103111 100644 --- a/frappe/core/doctype/session_default/session_default.py +++ b/frappe/core/doctype/session_default/session_default.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/session_default_settings/session_default_settings.py b/frappe/core/doctype/session_default_settings/session_default_settings.py index 7b4bd19e9a..25f7522c86 100644 --- a/frappe/core/doctype/session_default_settings/session_default_settings.py +++ b/frappe/core/doctype/session_default_settings/session_default_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ import json diff --git a/frappe/core/doctype/session_default_settings/test_session_default_settings.py b/frappe/core/doctype/session_default_settings/test_session_default_settings.py index 12aa14d343..7d20015b66 100644 --- a/frappe/core/doctype/session_default_settings/test_session_default_settings.py +++ b/frappe/core/doctype/session_default_settings/test_session_default_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.core.doctype.session_default_settings.session_default_settings import set_session_default_values, clear_session_defaults diff --git a/frappe/core/doctype/sms_parameter/__init__.py b/frappe/core/doctype/sms_parameter/__init__.py index baffc48825..8b13789179 100755 --- a/frappe/core/doctype/sms_parameter/__init__.py +++ b/frappe/core/doctype/sms_parameter/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/core/doctype/sms_parameter/sms_parameter.py b/frappe/core/doctype/sms_parameter/sms_parameter.py index 08b220b61a..d1fb1c53db 100644 --- a/frappe/core/doctype/sms_parameter/sms_parameter.py +++ b/frappe/core/doctype/sms_parameter/sms_parameter.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/sms_settings/__init__.py b/frappe/core/doctype/sms_settings/__init__.py index baffc48825..8b13789179 100755 --- a/frappe/core/doctype/sms_settings/__init__.py +++ b/frappe/core/doctype/sms_settings/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/core/doctype/sms_settings/sms_settings.py b/frappe/core/doctype/sms_settings/sms_settings.py index ac835108c1..58a0ff08f6 100644 --- a/frappe/core/doctype/sms_settings/sms_settings.py +++ b/frappe/core/doctype/sms_settings/sms_settings.py @@ -2,15 +2,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _, throw, msgprint from frappe.utils import nowdate from frappe.model.document import Document -import six -from six import string_types class SMSSettings(Document): pass @@ -35,20 +32,20 @@ def validate_receiver_nos(receiver_list): @frappe.whitelist() def get_contact_number(contact_name, ref_doctype, ref_name): "returns mobile number of the contact" - number = frappe.db.sql("""select mobile_no, phone from tabContact - where name=%s + number = frappe.db.sql("""select mobile_no, phone from tabContact + where name=%s and exists( select name from `tabDynamic Link` where link_doctype=%s and link_name=%s ) """, (contact_name, ref_doctype, ref_name)) - + return number and (number[0][0] or number[0][1]) or '' @frappe.whitelist() def send_sms(receiver_list, msg, sender_name = '', success_msg = True): import json - if isinstance(receiver_list, string_types): + if isinstance(receiver_list, str): receiver_list = json.loads(receiver_list) if not isinstance(receiver_list, list): receiver_list = [receiver_list] diff --git a/frappe/core/doctype/sms_settings/test_sms_settings.py b/frappe/core/doctype/sms_settings/test_sms_settings.py index b14fd3e4a0..862f5e3965 100644 --- a/frappe/core/doctype/sms_settings/test_sms_settings.py +++ b/frappe/core/doctype/sms_settings/test_sms_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/success_action/success_action.py b/frappe/core/doctype/success_action/success_action.py index f8b99f1fea..4ebd3d250b 100644 --- a/frappe/core/doctype/success_action/success_action.py +++ b/frappe/core/doctype/success_action/success_action.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class SuccessAction(Document): diff --git a/frappe/core/doctype/system_settings/system_settings.py b/frappe/core/doctype/system_settings/system_settings.py index 05aaca81de..466914569f 100644 --- a/frappe/core/doctype/system_settings/system_settings.py +++ b/frappe/core/doctype/system_settings/system_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/core/doctype/system_settings/test_system_settings.py b/frappe/core/doctype/system_settings/test_system_settings.py index 82d0ddbd7c..a65c602abe 100644 --- a/frappe/core/doctype/system_settings/test_system_settings.py +++ b/frappe/core/doctype/system_settings/test_system_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/test/test.py b/frappe/core/doctype/test/test.py index 7e91b1cd4a..98e36e6a30 100644 --- a/frappe/core/doctype/test/test.py +++ b/frappe/core/doctype/test/test.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document import json diff --git a/frappe/core/doctype/test/test_test.py b/frappe/core/doctype/test/test_test.py index 2a9b43bf95..d8ca975d63 100644 --- a/frappe/core/doctype/test/test_test.py +++ b/frappe/core/doctype/test/test_test.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/transaction_log/test_transaction_log.py b/frappe/core/doctype/transaction_log/test_transaction_log.py index 164a683c38..0d9b9353d0 100644 --- a/frappe/core/doctype/transaction_log/test_transaction_log.py +++ b/frappe/core/doctype/transaction_log/test_transaction_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import hashlib @@ -35,7 +33,7 @@ class TestTransactionLog(unittest.TestCase): sha = hashlib.sha256() sha.update( - frappe.safe_encode(str(third_log.transaction_hash)) + + frappe.safe_encode(str(third_log.transaction_hash)) + frappe.safe_encode(str(second_log.chaining_hash)) ) diff --git a/frappe/core/doctype/transaction_log/transaction_log.py b/frappe/core/doctype/transaction_log/transaction_log.py index b7ea6cac60..58d0b3d176 100644 --- a/frappe/core/doctype/transaction_log/transaction_log.py +++ b/frappe/core/doctype/transaction_log/transaction_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/core/doctype/translation/test_translation.py b/frappe/core/doctype/translation/test_translation.py index 12899dddf7..ae1293b38f 100644 --- a/frappe/core/doctype/translation/test_translation.py +++ b/frappe/core/doctype/translation/test_translation.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/core/doctype/translation/translation.py b/frappe/core/doctype/translation/translation.py index 177dea401f..b1f4642791 100644 --- a/frappe/core/doctype/translation/translation.py +++ b/frappe/core/doctype/translation/translation.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import strip_html_tags, is_html diff --git a/frappe/core/doctype/user/test_user.py b/frappe/core/doctype/user/test_user.py index 5bea767934..392128834d 100644 --- a/frappe/core/doctype/user/test_user.py +++ b/frappe/core/doctype/user/test_user.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest, uuid from frappe.model.delete_doc import delete_doc diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index a4d13a57e0..3fa31cbf80 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1,10 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - from bs4 import BeautifulSoup - import frappe import frappe.share import frappe.defaults diff --git a/frappe/core/doctype/user_document_type/user_document_type.py b/frappe/core/doctype/user_document_type/user_document_type.py index 979bfcb250..48dbf87b3d 100644 --- a/frappe/core/doctype/user_document_type/user_document_type.py +++ b/frappe/core/doctype/user_document_type/user_document_type.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_email/user_email.py b/frappe/core/doctype/user_email/user_email.py index a0ce2e169d..729aa03444 100644 --- a/frappe/core/doctype/user_email/user_email.py +++ b/frappe/core/doctype/user_email/user_email.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_group/test_user_group.py b/frappe/core/doctype/user_group/test_user_group.py index c7e28f3d31..2f89d032e1 100644 --- a/frappe/core/doctype/user_group/test_user_group.py +++ b/frappe/core/doctype/user_group/test_user_group.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/user_group/user_group.py b/frappe/core/doctype/user_group/user_group.py index b1d0fede4c..178775d407 100644 --- a/frappe/core/doctype/user_group/user_group.py +++ b/frappe/core/doctype/user_group/user_group.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document import frappe diff --git a/frappe/core/doctype/user_group_member/test_user_group_member.py b/frappe/core/doctype/user_group_member/test_user_group_member.py index 38aade4608..8dbaed9e65 100644 --- a/frappe/core/doctype/user_group_member/test_user_group_member.py +++ b/frappe/core/doctype/user_group_member/test_user_group_member.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/user_group_member/user_group_member.py b/frappe/core/doctype/user_group_member/user_group_member.py index 4d0656913d..f85ddc3209 100644 --- a/frappe/core/doctype/user_group_member/user_group_member.py +++ b/frappe/core/doctype/user_group_member/user_group_member.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_permission/test_user_permission.py b/frappe/core/doctype/user_permission/test_user_permission.py index 47651fee72..1a442b53e7 100644 --- a/frappe/core/doctype/user_permission/test_user_permission.py +++ b/frappe/core/doctype/user_permission/test_user_permission.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals from frappe.core.doctype.user_permission.user_permission import add_user_permissions, remove_applicable from frappe.permissions import has_user_permission from frappe.core.doctype.doctype.test_doctype import new_doctype diff --git a/frappe/core/doctype/user_permission/user_permission.py b/frappe/core/doctype/user_permission/user_permission.py index fec5019ca9..42ca4d7a14 100644 --- a/frappe/core/doctype/user_permission/user_permission.py +++ b/frappe/core/doctype/user_permission/user_permission.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, json from frappe.model.document import Document from frappe.permissions import (get_valid_perms, update_permission_property) diff --git a/frappe/core/doctype/user_select_document_type/user_select_document_type.py b/frappe/core/doctype/user_select_document_type/user_select_document_type.py index 373eaf7aa3..13e3f0d351 100644 --- a/frappe/core/doctype/user_select_document_type/user_select_document_type.py +++ b/frappe/core/doctype/user_select_document_type/user_select_document_type.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/user_social_login/user_social_login.py b/frappe/core/doctype/user_social_login/user_social_login.py index cc6c3d0e05..4a34006d2b 100644 --- a/frappe/core/doctype/user_social_login/user_social_login.py +++ b/frappe/core/doctype/user_social_login/user_social_login.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class UserSocialLogin(Document): diff --git a/frappe/core/doctype/user_type/test_user_type.py b/frappe/core/doctype/user_type/test_user_type.py index de61e0f476..1c47f02bbb 100644 --- a/frappe/core/doctype/user_type/test_user_type.py +++ b/frappe/core/doctype/user_type/test_user_type.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/core/doctype/user_type/user_type.py b/frappe/core/doctype/user_type/user_type.py index 0e8b692416..e7d06c45f2 100644 --- a/frappe/core/doctype/user_type/user_type.py +++ b/frappe/core/doctype/user_type/user_type.py @@ -2,10 +2,8 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ -from six import iteritems from frappe.utils import get_link_to_form from frappe.config import get_modules_from_app from frappe.permissions import add_permission, add_user_permission @@ -247,7 +245,7 @@ def apply_permissions_for_non_standard_user_type(doc, method=None): if not user_types: return - for user_type, data in iteritems(user_types): + for user_type, data in user_types.items(): if (not doc.get(data[1]) or doc.doctype != data[0]): continue diff --git a/frappe/core/doctype/user_type/user_type_dashboard.py b/frappe/core/doctype/user_type/user_type_dashboard.py index 7e14198bca..6cdd2f82a5 100644 --- a/frappe/core/doctype/user_type/user_type_dashboard.py +++ b/frappe/core/doctype/user_type/user_type_dashboard.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from frappe import _ def get_data(): diff --git a/frappe/core/doctype/user_type_module/user_type_module.py b/frappe/core/doctype/user_type_module/user_type_module.py index 6cd2cbacdb..9afbcd294d 100644 --- a/frappe/core/doctype/user_type_module/user_type_module.py +++ b/frappe/core/doctype/user_type_module/user_type_module.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/core/doctype/version/test_version.py b/frappe/core/doctype/version/test_version.py index 51b3c21f58..f6c099c4ea 100644 --- a/frappe/core/doctype/version/test_version.py +++ b/frappe/core/doctype/version/test_version.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest, copy from frappe.test_runner import make_test_objects diff --git a/frappe/core/doctype/version/version.py b/frappe/core/doctype/version/version.py index 7654db4ae5..a1bd851346 100644 --- a/frappe/core/doctype/version/version.py +++ b/frappe/core/doctype/version/version.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe, json from frappe.model.document import Document diff --git a/frappe/core/doctype/view_log/test_view_log.py b/frappe/core/doctype/view_log/test_view_log.py index 83967a39a4..025f3d8ad9 100644 --- a/frappe/core/doctype/view_log/test_view_log.py +++ b/frappe/core/doctype/view_log/test_view_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest @@ -25,11 +23,11 @@ class TestViewLog(unittest.TestCase): # load the form getdoc('Event', ev.name) a = frappe.get_value( - doctype="View Log", + doctype="View Log", filters={ "reference_doctype": "Event", "reference_name": ev.name - }, + }, fieldname=['viewed_by'] ) diff --git a/frappe/core/doctype/view_log/view_log.py b/frappe/core/doctype/view_log/view_log.py index 45e98e37c7..242250be8b 100644 --- a/frappe/core/doctype/view_log/view_log.py +++ b/frappe/core/doctype/view_log/view_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/core/notifications.py b/frappe/core/notifications.py index 771a15a2e7..707de43f28 100644 --- a/frappe/core/notifications.py +++ b/frappe/core/notifications.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def get_notification_config(): diff --git a/frappe/core/page/__init__.py b/frappe/core/page/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/core/page/__init__.py +++ b/frappe/core/page/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/core/page/permission_manager/permission_manager.py b/frappe/core/page/permission_manager/permission_manager.py index 1c215eb6e1..15c7cb55ae 100644 --- a/frappe/core/page/permission_manager/permission_manager.py +++ b/frappe/core/page/permission_manager/permission_manager.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ import frappe.defaults diff --git a/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py b/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py index c928939119..13602ca777 100644 --- a/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py +++ b/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _, throw import frappe.utils.user diff --git a/frappe/core/report/transaction_log_report/transaction_log_report.py b/frappe/core/report/transaction_log_report/transaction_log_report.py index 9d84901f22..ff8d8345d6 100644 --- a/frappe/core/report/transaction_log_report/transaction_log_report.py +++ b/frappe/core/report/transaction_log_report/transaction_log_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import hashlib from frappe import _ diff --git a/frappe/core/utils.py b/frappe/core/utils.py index 55cfbc34d7..9b8ee3a326 100644 --- a/frappe/core/utils.py +++ b/frappe/core/utils.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/core/web_form/edit_profile/edit_profile.py b/frappe/core/web_form/edit_profile/edit_profile.py index 2334f8b26d..e1ada61927 100644 --- a/frappe/core/web_form/edit_profile/edit_profile.py +++ b/frappe/core/web_form/edit_profile/edit_profile.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe def get_context(context): diff --git a/frappe/custom/doctype/client_script/__init__.py b/frappe/custom/doctype/client_script/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/custom/doctype/client_script/__init__.py +++ b/frappe/custom/doctype/client_script/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/custom/doctype/client_script/client_script.py b/frappe/custom/doctype/client_script/client_script.py index 049f979263..9c098fe8c9 100644 --- a/frappe/custom/doctype/client_script/client_script.py +++ b/frappe/custom/doctype/client_script/client_script.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/custom/doctype/client_script/test_client_script.py b/frappe/custom/doctype/client_script/test_client_script.py index de113c1ce7..b8358468b9 100644 --- a/frappe/custom/doctype/client_script/test_client_script.py +++ b/frappe/custom/doctype/client_script/test_client_script.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/custom/doctype/custom_field/__init__.py b/frappe/custom/doctype/custom_field/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/custom/doctype/custom_field/__init__.py +++ b/frappe/custom/doctype/custom_field/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/custom/doctype/custom_field/custom_field.py b/frappe/custom/doctype/custom_field/custom_field.py index 39aff8b4a7..7e6ea1875a 100644 --- a/frappe/custom/doctype/custom_field/custom_field.py +++ b/frappe/custom/doctype/custom_field/custom_field.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import json from frappe.utils import cstr diff --git a/frappe/custom/doctype/custom_field/test_custom_field.py b/frappe/custom/doctype/custom_field/test_custom_field.py index 819917050a..3196b66ee8 100644 --- a/frappe/custom/doctype/custom_field/test_custom_field.py +++ b/frappe/custom/doctype/custom_field/test_custom_field.py @@ -3,8 +3,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/custom/doctype/customize_form/__init__.py b/frappe/custom/doctype/customize_form/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/custom/doctype/customize_form/__init__.py +++ b/frappe/custom/doctype/customize_form/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index be0dded99c..8bcc6cf059 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals """ Customize Form is a Single DocType used to mask the Property Setter Thus providing a better UI from user perspective diff --git a/frappe/custom/doctype/customize_form/test_customize_form.py b/frappe/custom/doctype/customize_form/test_customize_form.py index 75555a8205..58bdcf9a18 100644 --- a/frappe/custom/doctype/customize_form/test_customize_form.py +++ b/frappe/custom/doctype/customize_form/test_customize_form.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, unittest, json from frappe.test_runner import make_test_records_for_doctype from frappe.core.doctype.doctype.doctype import InvalidFieldNameError diff --git a/frappe/custom/doctype/customize_form_field/__init__.py b/frappe/custom/doctype/customize_form_field/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/custom/doctype/customize_form_field/__init__.py +++ b/frappe/custom/doctype/customize_form_field/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.py b/frappe/custom/doctype/customize_form_field/customize_form_field.py index 20c206328c..f288e70754 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.py +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/custom/doctype/doctype_layout/doctype_layout.py b/frappe/custom/doctype/doctype_layout/doctype_layout.py index a4fe9a9bce..0dc320353d 100644 --- a/frappe/custom/doctype/doctype_layout/doctype_layout.py +++ b/frappe/custom/doctype/doctype_layout/doctype_layout.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - from frappe.model.document import Document from frappe.desk.utils import slug diff --git a/frappe/custom/doctype/doctype_layout/test_doctype_layout.py b/frappe/custom/doctype/doctype_layout/test_doctype_layout.py index 5765c86262..dcde3c00a4 100644 --- a/frappe/custom/doctype/doctype_layout/test_doctype_layout.py +++ b/frappe/custom/doctype/doctype_layout/test_doctype_layout.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py b/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py index 7f8c8edfce..c1e963602f 100644 --- a/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py +++ b/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/custom/doctype/property_setter/__init__.py b/frappe/custom/doctype/property_setter/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/custom/doctype/property_setter/__init__.py +++ b/frappe/custom/doctype/property_setter/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/custom/doctype/property_setter/property_setter.py b/frappe/custom/doctype/property_setter/property_setter.py index 56e5829271..2a6c06b70a 100644 --- a/frappe/custom/doctype/property_setter/property_setter.py +++ b/frappe/custom/doctype/property_setter/property_setter.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/custom/doctype/property_setter/test_property_setter.py b/frappe/custom/doctype/property_setter/test_property_setter.py index 33e7d288a4..4d4de66d51 100644 --- a/frappe/custom/doctype/property_setter/test_property_setter.py +++ b/frappe/custom/doctype/property_setter/test_property_setter.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/custom/doctype/test_rename_new/test_rename_new.py b/frappe/custom/doctype/test_rename_new/test_rename_new.py index aa5984e466..32d2396b2b 100644 --- a/frappe/custom/doctype/test_rename_new/test_rename_new.py +++ b/frappe/custom/doctype/test_rename_new/test_rename_new.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/custom/doctype/test_rename_new/test_test_rename_new.py b/frappe/custom/doctype/test_rename_new/test_test_rename_new.py index 554efbae45..b3ea4818de 100644 --- a/frappe/custom/doctype/test_rename_new/test_test_rename_new.py +++ b/frappe/custom/doctype/test_rename_new/test_test_rename_new.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/data_migration/doctype/data_migration_connector/connectors/base.py b/frappe/data_migration/doctype/data_migration_connector/connectors/base.py index 97f9f5f4a3..5eca7cfac5 100644 --- a/frappe/data_migration/doctype/data_migration_connector/connectors/base.py +++ b/frappe/data_migration/doctype/data_migration_connector/connectors/base.py @@ -1,10 +1,7 @@ -from __future__ import unicode_literals -from six import with_metaclass from abc import ABCMeta, abstractmethod from frappe.utils.password import get_decrypted_password -class BaseConnection(with_metaclass(ABCMeta)): - +class BaseConnection(metaclass=ABCMeta): @abstractmethod def get(self, remote_objectname, fields=None, filters=None, start=0, page_length=10): pass diff --git a/frappe/data_migration/doctype/data_migration_connector/connectors/frappe_connection.py b/frappe/data_migration/doctype/data_migration_connector/connectors/frappe_connection.py index 6ee41afdf2..473a15c2dc 100644 --- a/frappe/data_migration/doctype/data_migration_connector/connectors/frappe_connection.py +++ b/frappe/data_migration/doctype/data_migration_connector/connectors/frappe_connection.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.frappeclient import FrappeClient from .base import BaseConnection diff --git a/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py b/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py index 793dfe6694..d1137f2e67 100644 --- a/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py +++ b/frappe/data_migration/doctype/data_migration_connector/data_migration_connector.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, os from frappe.model.document import Document from frappe import _ @@ -76,8 +75,7 @@ def get_connection_class(python_module): return _class -connection_boilerplate = """from __future__ import unicode_literals -from frappe.data_migration.doctype.data_migration_connector.connectors.base import BaseConnection +connection_boilerplate = """from frappe.data_migration.doctype.data_migration_connector.connectors.base import BaseConnection class {connection_class}(BaseConnection): def __init__(self, connector): diff --git a/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py b/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py index a6e30fbe44..fd45f86ec1 100644 --- a/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py +++ b/frappe/data_migration/doctype/data_migration_connector/test_data_migration_connector.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals import unittest class TestDataMigrationConnector(unittest.TestCase): diff --git a/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py b/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py index 1cc54a0d1a..5cb20ba56c 100644 --- a/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py +++ b/frappe/data_migration/doctype/data_migration_mapping/data_migration_mapping.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils.safe_exec import get_safe_globals diff --git a/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py b/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py index e6f0ce2796..df11fc0522 100644 --- a/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py +++ b/frappe/data_migration/doctype/data_migration_mapping/test_data_migration_mapping.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals import unittest class TestDataMigrationMapping(unittest.TestCase): diff --git a/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py b/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py index 1ccdf76eed..6d3ef50937 100644 --- a/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py +++ b/frappe/data_migration/doctype/data_migration_mapping_detail/data_migration_mapping_detail.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class DataMigrationMappingDetail(Document): diff --git a/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py b/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py index 5cd195f4fe..a8d0e40a4c 100644 --- a/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py +++ b/frappe/data_migration/doctype/data_migration_plan/data_migration_plan.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.modules import get_module_path, scrub_dt_dn from frappe.modules.export_file import export_to_files, create_init_py diff --git a/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py b/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py index 3a33039c3d..14c585a82d 100644 --- a/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py +++ b/frappe/data_migration/doctype/data_migration_plan/test_data_migration_plan.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals import unittest class TestDataMigrationPlan(unittest.TestCase): diff --git a/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py b/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py index 85f879069c..ba4cf28eb8 100644 --- a/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py +++ b/frappe/data_migration/doctype/data_migration_plan_mapping/data_migration_plan_mapping.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class DataMigrationPlanMapping(Document): diff --git a/frappe/data_migration/doctype/data_migration_run/data_migration_run.py b/frappe/data_migration/doctype/data_migration_run/data_migration_run.py index aed9c6cb1d..c35af5827b 100644 --- a/frappe/data_migration/doctype/data_migration_run/data_migration_run.py +++ b/frappe/data_migration/doctype/data_migration_run/data_migration_run.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, json, math from frappe.model.document import Document from frappe import _ diff --git a/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py b/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py index c6c3ea138c..ef7b70dca2 100644 --- a/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py +++ b/frappe/data_migration/doctype/data_migration_run/test_data_migration_run.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals import frappe, unittest class TestDataMigrationRun(unittest.TestCase): diff --git a/frappe/database/__init__.py b/frappe/database/__init__.py index 1f0d3f9bf5..a899bec3d1 100644 --- a/frappe/database/__init__.py +++ b/frappe/database/__init__.py @@ -4,8 +4,6 @@ # Database Module # -------------------- -from __future__ import unicode_literals - def setup_database(force, source_sql=None, verbose=None, no_mariadb_socket=False): import frappe if frappe.conf.db_type == 'postgres': diff --git a/frappe/database/database.py b/frappe/database/database.py index c9c1ec3909..7e8d2da43b 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -4,8 +4,6 @@ # Database Module # -------------------- -from __future__ import unicode_literals - import re import time import frappe @@ -19,13 +17,6 @@ from frappe.utils import now, getdate, cast_fieldtype, get_datetime from frappe.model.utils.link_count import flush_local_link_count from frappe.utils import cint -# imports - compatibility imports -from six import ( - integer_types, - string_types, - text_type, - iteritems -) class Database(object): """ @@ -277,7 +268,7 @@ class Database(object): for r in result: values = [] for value in r: - if as_utf8 and isinstance(value, text_type): + if as_utf8 and isinstance(value, str): value = value.encode('utf-8') values.append(value) @@ -294,7 +285,7 @@ class Database(object): """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, integer_types)): + if isinstance(v, (datetime.date, datetime.timedelta, datetime.datetime, int)): return True if formatted and isinstance(v, (int, float)): return True @@ -312,7 +303,7 @@ class Database(object): for r in res: nr = [] for val in r: - if as_utf8 and isinstance(val, text_type): + if as_utf8 and isinstance(val, str): val = val.encode('utf-8') nr.append(val) nres.append(nr) @@ -363,7 +354,7 @@ class Database(object): # docname is a number, convert to string filters = str(filters) - if isinstance(filters, string_types): + if isinstance(filters, str): filters = { "name": filters } for f in filters: @@ -428,7 +419,7 @@ class Database(object): user = frappe.db.get_values("User", "test@example.com", "*")[0] """ out = None - if cache and isinstance(filters, string_types) and \ + if cache and isinstance(filters, str) and \ (doctype, filters, fieldname) in self.value_cache: return self.value_cache[(doctype, filters, fieldname)] @@ -440,7 +431,7 @@ class Database(object): else: fields = fieldname if fieldname!="*": - if isinstance(fieldname, string_types): + if isinstance(fieldname, str): fields = [fieldname] else: fields = fieldname @@ -461,7 +452,7 @@ class Database(object): else: out = self.get_values_from_single(fields, filters, doctype, as_dict, debug, update) - if cache and isinstance(filters, string_types): + if cache and isinstance(filters, str): self.value_cache[(doctype, filters, fieldname)] = out return out @@ -673,7 +664,7 @@ class Database(object): where field in ({0}) and doctype=%s'''.format(', '.join(['%s']*len(keys))), list(keys) + [dt], debug=debug) - for key, value in iteritems(to_update): + for key, value in to_update.items(): self.sql('''insert into `tabSingles` (doctype, field, value) values (%s, %s, %s)''', (dt, key, value), debug=debug) @@ -811,7 +802,7 @@ class Database(object): :param dt: DocType name. :param dn: Document name or filter dict.""" - if isinstance(dt, string_types): + if isinstance(dt, str): if dt!="DocType" and dt==dn: return True # single always exists (!) try: diff --git a/frappe/database/mariadb/schema.py b/frappe/database/mariadb/schema.py index 4bbecd2a2e..b40af59286 100644 --- a/frappe/database/mariadb/schema.py +++ b/frappe/database/mariadb/schema.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe from frappe import _ from frappe.database.schema import DBTable diff --git a/frappe/database/mariadb/setup_db.py b/frappe/database/mariadb/setup_db.py index 9b73d77171..6be08c66bb 100644 --- a/frappe/database/mariadb/setup_db.py +++ b/frappe/database/mariadb/setup_db.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe import os from frappe.database.db_manager import DbManager diff --git a/frappe/database/postgres/database.py b/frappe/database/postgres/database.py index 6ac2767a71..8235277e30 100644 --- a/frappe/database/postgres/database.py +++ b/frappe/database/postgres/database.py @@ -2,7 +2,6 @@ import re import frappe import psycopg2 import psycopg2.extensions -from six import string_types from frappe.utils import cstr from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT @@ -253,7 +252,7 @@ class PostgresDatabase(Database): self.sql("""CREATE INDEX IF NOT EXISTS "{}" ON `{}`("{}")""".format(index_name, table_name, '", "'.join(fields))) def add_unique(self, doctype, fields, constraint_name=None): - if isinstance(fields, string_types): + if isinstance(fields, str): fields = [fields] if not constraint_name: constraint_name = "unique_" + "_".join(fields) diff --git a/frappe/database/postgres/setup_db.py b/frappe/database/postgres/setup_db.py index 3ee6b6a286..19ba681237 100644 --- a/frappe/database/postgres/setup_db.py +++ b/frappe/database/postgres/setup_db.py @@ -83,7 +83,6 @@ def get_root_connection(root_login=None, root_password=None): root_login = frappe.conf.get("root_login") or None if not root_login: - from six.moves import input root_login = input("Enter postgres super user: ") if not root_password: diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 5f5ba06d8b..31f11dbd5e 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import re import frappe diff --git a/frappe/defaults.py b/frappe/defaults.py index 4bec6677c7..fde48d71ff 100644 --- a/frappe/defaults.py +++ b/frappe/defaults.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.desk.notifications import clear_notifications from frappe.cache_manager import clear_defaults_cache, common_default_keys diff --git a/frappe/desk/__init__.py b/frappe/desk/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/desk/__init__.py +++ b/frappe/desk/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/desk/calendar.py b/frappe/desk/calendar.py index 064d870092..f00f729415 100644 --- a/frappe/desk/calendar.py +++ b/frappe/desk/calendar.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe import _ import json diff --git a/frappe/desk/desk_page.py b/frappe/desk/desk_page.py index 6c5fdc6821..d373dbda0e 100644 --- a/frappe/desk/desk_page.py +++ b/frappe/desk/desk_page.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.translate import send_translations diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 1a3b1ca99b..0a7d436169 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -2,12 +2,10 @@ # MIT License. See license.txt # Author - Shivam Mishra -from __future__ import unicode_literals import frappe from json import loads, dumps from frappe import _, DoesNotExistError, ValidationError, _dict from frappe.boot import get_allowed_pages, get_allowed_reports -from six import string_types from functools import wraps from frappe.cache_manager import ( build_domain_restriced_doctype_cache, @@ -61,7 +59,7 @@ class Workspace: shortcuts = self.doc.shortcuts + self.extended_shortcuts for section in cards: - links = loads(section.get('links')) if isinstance(section.get('links'), string_types) else section.get('links') + links = loads(section.get('links')) if isinstance(section.get('links'), str) else section.get('links') for item in links: if self.is_item_allowed(item.get('link_to'), item.get('link_type')): return True diff --git a/frappe/desk/doctype/bulk_update/bulk_update.py b/frappe/desk/doctype/bulk_update/bulk_update.py index 9b9f7d7a73..469ee839f1 100644 --- a/frappe/desk/doctype/bulk_update/bulk_update.py +++ b/frappe/desk/doctype/bulk_update/bulk_update.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ diff --git a/frappe/desk/doctype/calendar_view/calendar_view.py b/frappe/desk/doctype/calendar_view/calendar_view.py index ae8ab1eb46..3a986f3273 100644 --- a/frappe/desk/doctype/calendar_view/calendar_view.py +++ b/frappe/desk/doctype/calendar_view/calendar_view.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class CalendarView(Document): diff --git a/frappe/desk/doctype/console_log/console_log.py b/frappe/desk/doctype/console_log/console_log.py index 635c4c1ba7..5d0f1cfa93 100644 --- a/frappe/desk/doctype/console_log/console_log.py +++ b/frappe/desk/doctype/console_log/console_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/console_log/test_console_log.py b/frappe/desk/doctype/console_log/test_console_log.py index 04dc4f241f..3bb1605204 100644 --- a/frappe/desk/doctype/console_log/test_console_log.py +++ b/frappe/desk/doctype/console_log/test_console_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/dashboard/dashboard.py b/frappe/desk/doctype/dashboard/dashboard.py index 4e66318769..d2e79279d9 100644 --- a/frappe/desk/doctype/dashboard/dashboard.py +++ b/frappe/desk/doctype/dashboard/dashboard.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document from frappe.modules.export_file import export_to_files from frappe.config import get_modules_from_all_apps_for_user diff --git a/frappe/desk/doctype/dashboard/test_dashboard.py b/frappe/desk/doctype/dashboard/test_dashboard.py index d5485d8f70..dd1bc31d86 100644 --- a/frappe/desk/doctype/dashboard/test_dashboard.py +++ b/frappe/desk/doctype/dashboard/test_dashboard.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestDashboard(unittest.TestCase): diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py index 48b34e6cd9..3bea6eded9 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ import datetime diff --git a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py index 72ab18385d..78d133b2d5 100644 --- a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest, frappe from frappe.utils import getdate, formatdate, get_last_day from frappe.utils.dateutils import get_period_ending, get_period diff --git a/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py b/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py index 734f27cc28..7d6f66daa2 100644 --- a/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py +++ b/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py index 7cd4f9daa3..359801a303 100644 --- a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py +++ b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py b/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py index 6685009078..791dbc563b 100644 --- a/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py +++ b/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, os from frappe import _ from frappe.model.document import Document diff --git a/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py b/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py index 822526b591..53fe127dfb 100644 --- a/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py +++ b/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestDashboardChartSource(unittest.TestCase): diff --git a/frappe/desk/doctype/dashboard_settings/dashboard_settings.py b/frappe/desk/doctype/dashboard_settings/dashboard_settings.py index 4697d897fc..df61c52114 100644 --- a/frappe/desk/doctype/dashboard_settings/dashboard_settings.py +++ b/frappe/desk/doctype/dashboard_settings/dashboard_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document import frappe diff --git a/frappe/desk/doctype/desktop_icon/desktop_icon.py b/frappe/desk/doctype/desktop_icon/desktop_icon.py index fcf10ef61d..81a79cdb09 100644 --- a/frappe/desk/doctype/desktop_icon/desktop_icon.py +++ b/frappe/desk/doctype/desktop_icon/desktop_icon.py @@ -2,14 +2,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import frappe from frappe import _ import json import random from frappe.model.document import Document -from six import iteritems, string_types from frappe.utils.user import UserPermissions class DesktopIcon(Document): @@ -173,7 +170,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, string_types): + if isinstance(new_order, str): new_order = json.loads(new_order) for i, module_name in enumerate(new_order): if module_name not in ('Explore',): @@ -232,7 +229,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, string_types): + if isinstance(hidden_list, str): hidden_list = json.loads(hidden_list) # set as hidden @@ -329,7 +326,7 @@ def sync_from_app(app): if isinstance(modules, dict): modules_list = [] - for m, desktop_icon in iteritems(modules): + for m, desktop_icon in modules.items(): desktop_icon['module_name'] = m modules_list.append(desktop_icon) else: diff --git a/frappe/desk/doctype/event/__init__.py b/frappe/desk/doctype/event/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/desk/doctype/event/__init__.py +++ b/frappe/desk/doctype/event/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/desk/doctype/event/event.py b/frappe/desk/doctype/event/event.py index 54905bed6a..57c89eaf2e 100644 --- a/frappe/desk/doctype/event/event.py +++ b/frappe/desk/doctype/event/event.py @@ -1,9 +1,7 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals -from six.moves import range -from six import string_types + import frappe import json @@ -106,7 +104,7 @@ class Event(Document): @frappe.whitelist() def delete_communication(event, reference_doctype, reference_docname): deleted_participant = frappe.get_doc(reference_doctype, reference_docname) - if isinstance(event, string_types): + if isinstance(event, str): event = json.loads(event) filters = [ @@ -168,7 +166,7 @@ def get_events(start, end, user=None, for_reminder=False, filters=None): if not user: user = frappe.session.user - if isinstance(filters, string_types): + if isinstance(filters, str): filters = json.loads(filters) filter_condition = get_filters_cond('Event', filters, []) diff --git a/frappe/desk/doctype/event/test_event.py b/frappe/desk/doctype/event/test_event.py index 2926a74a55..77211946a9 100644 --- a/frappe/desk/doctype/event/test_event.py +++ b/frappe/desk/doctype/event/test_event.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - """Use blog post test to test user permissions logic""" import frappe diff --git a/frappe/desk/doctype/event_participants/event_participants.py b/frappe/desk/doctype/event_participants/event_participants.py index 18e4672140..ca4fae9930 100644 --- a/frappe/desk/doctype/event_participants/event_participants.py +++ b/frappe/desk/doctype/event_participants/event_participants.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class EventParticipants(Document): diff --git a/frappe/desk/doctype/global_search_doctype/global_search_doctype.py b/frappe/desk/doctype/global_search_doctype/global_search_doctype.py index 4c9a948278..de8a48af01 100644 --- a/frappe/desk/doctype/global_search_doctype/global_search_doctype.py +++ b/frappe/desk/doctype/global_search_doctype/global_search_doctype.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/global_search_settings/global_search_settings.py b/frappe/desk/doctype/global_search_settings/global_search_settings.py index 85c9687ab3..28a1ed8239 100644 --- a/frappe/desk/doctype/global_search_settings/global_search_settings.py +++ b/frappe/desk/doctype/global_search_settings/global_search_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ diff --git a/frappe/desk/doctype/kanban_board/kanban_board.py b/frappe/desk/doctype/kanban_board/kanban_board.py index a655e9e1da..5100727f43 100644 --- a/frappe/desk/doctype/kanban_board/kanban_board.py +++ b/frappe/desk/doctype/kanban_board/kanban_board.py @@ -2,12 +2,10 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import json from frappe import _ from frappe.model.document import Document -from six import iteritems class KanbanBoard(Document): @@ -107,7 +105,7 @@ def update_order(board_name, order): order_dict = json.loads(order) updated_cards = [] - for col_name, cards in iteritems(order_dict): + for col_name, cards in order_dict.items(): order_list = [] for card in cards: column = frappe.get_value( diff --git a/frappe/desk/doctype/kanban_board/test_kanban_board.py b/frappe/desk/doctype/kanban_board/test_kanban_board.py index 33947f4a54..f9503d736a 100644 --- a/frappe/desk/doctype/kanban_board/test_kanban_board.py +++ b/frappe/desk/doctype/kanban_board/test_kanban_board.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/desk/doctype/kanban_board_column/kanban_board_column.py b/frappe/desk/doctype/kanban_board_column/kanban_board_column.py index 4ea30d21b2..aebba3351c 100644 --- a/frappe/desk/doctype/kanban_board_column/kanban_board_column.py +++ b/frappe/desk/doctype/kanban_board_column/kanban_board_column.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/list_filter/list_filter.py b/frappe/desk/doctype/list_filter/list_filter.py index 035f7e90b9..2467ae40a4 100644 --- a/frappe/desk/doctype/list_filter/list_filter.py +++ b/frappe/desk/doctype/list_filter/list_filter.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, json from frappe.model.document import Document diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.py b/frappe/desk/doctype/list_view_settings/list_view_settings.py index 74e029f499..f4a288b7ba 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/list_view_settings/test_list_view_settings.py b/frappe/desk/doctype/list_view_settings/test_list_view_settings.py index c1b2f4a0da..00010d7604 100644 --- a/frappe/desk/doctype/list_view_settings/test_list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/test_list_view_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/module_onboarding/module_onboarding.py b/frappe/desk/doctype/module_onboarding/module_onboarding.py index 8315c0b304..6f01e0fd8d 100644 --- a/frappe/desk/doctype/module_onboarding/module_onboarding.py +++ b/frappe/desk/doctype/module_onboarding/module_onboarding.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.modules.export_file import export_to_files diff --git a/frappe/desk/doctype/module_onboarding/test_module_onboarding.py b/frappe/desk/doctype/module_onboarding/test_module_onboarding.py index ef305667b1..39184401a1 100644 --- a/frappe/desk/doctype/module_onboarding/test_module_onboarding.py +++ b/frappe/desk/doctype/module_onboarding/test_module_onboarding.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/note/note.py b/frappe/desk/doctype/note/note.py index c54689418e..790f9a514c 100644 --- a/frappe/desk/doctype/note/note.py +++ b/frappe/desk/doctype/note/note.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/note/test_note.py b/frappe/desk/doctype/note/test_note.py index 38894a9c3d..1bb1730357 100644 --- a/frappe/desk/doctype/note/test_note.py +++ b/frappe/desk/doctype/note/test_note.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors # See license.txt -from __future__ import unicode_literals import frappe import unittest diff --git a/frappe/desk/doctype/note_seen_by/note_seen_by.py b/frappe/desk/doctype/note_seen_by/note_seen_by.py index 6123f20929..cec4628b20 100644 --- a/frappe/desk/doctype/note_seen_by/note_seen_by.py +++ b/frappe/desk/doctype/note_seen_by/note_seen_by.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index 25af92f532..414f272f59 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/desk/doctype/notification_log/test_notification_log.py b/frappe/desk/doctype/notification_log/test_notification_log.py index e59aee30c9..af4dee8df3 100644 --- a/frappe/desk/doctype/notification_log/test_notification_log.py +++ b/frappe/desk/doctype/notification_log/test_notification_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe from frappe.desk.form.assign_to import add as assign_task import unittest diff --git a/frappe/desk/doctype/notification_settings/notification_settings.py b/frappe/desk/doctype/notification_settings/notification_settings.py index 4ab40bffe9..eb3a16435f 100644 --- a/frappe/desk/doctype/notification_settings/notification_settings.py +++ b/frappe/desk/doctype/notification_settings/notification_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py b/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py index f005efae76..6931e77754 100644 --- a/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py +++ b/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index 7d1a697f6b..d8d5fe0953 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import cint diff --git a/frappe/desk/doctype/number_card/test_number_card.py b/frappe/desk/doctype/number_card/test_number_card.py index 4aa1ecf282..c395f5f915 100644 --- a/frappe/desk/doctype/number_card/test_number_card.py +++ b/frappe/desk/doctype/number_card/test_number_card.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/number_card_link/number_card_link.py b/frappe/desk/doctype/number_card_link/number_card_link.py index 67ad7e70cd..6c16f45f4b 100644 --- a/frappe/desk/doctype/number_card_link/number_card_link.py +++ b/frappe/desk/doctype/number_card_link/number_card_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/onboarding_permission/onboarding_permission.py b/frappe/desk/doctype/onboarding_permission/onboarding_permission.py index f8772480df..40d3dc33b1 100644 --- a/frappe/desk/doctype/onboarding_permission/onboarding_permission.py +++ b/frappe/desk/doctype/onboarding_permission/onboarding_permission.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py b/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py index 9a7e8ae6fd..80b166de0a 100644 --- a/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py +++ b/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/onboarding_step/onboarding_step.py b/frappe/desk/doctype/onboarding_step/onboarding_step.py index e1cc5dfba4..10bd8926ce 100644 --- a/frappe/desk/doctype/onboarding_step/onboarding_step.py +++ b/frappe/desk/doctype/onboarding_step/onboarding_step.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/onboarding_step/test_onboarding_step.py b/frappe/desk/doctype/onboarding_step/test_onboarding_step.py index 66bd0c6660..2425577478 100644 --- a/frappe/desk/doctype/onboarding_step/test_onboarding_step.py +++ b/frappe/desk/doctype/onboarding_step/test_onboarding_step.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py b/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py index ea34de6088..c79244c4ad 100644 --- a/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py +++ b/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/route_history/route_history.py b/frappe/desk/doctype/route_history/route_history.py index 12d898afa5..b82077f485 100644 --- a/frappe/desk/doctype/route_history/route_history.py +++ b/frappe/desk/doctype/route_history/route_history.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/system_console/system_console.py b/frappe/desk/doctype/system_console/system_console.py index 6c87ca8c36..e2b5656bc0 100644 --- a/frappe/desk/doctype/system_console/system_console.py +++ b/frappe/desk/doctype/system_console/system_console.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import json import frappe diff --git a/frappe/desk/doctype/system_console/test_system_console.py b/frappe/desk/doctype/system_console/test_system_console.py index 55ef199122..743c2d6dde 100644 --- a/frappe/desk/doctype/system_console/test_system_console.py +++ b/frappe/desk/doctype/system_console/test_system_console.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/desk/doctype/tag/tag.py b/frappe/desk/doctype/tag/tag.py index 7e016ee91b..3c67bb4668 100644 --- a/frappe/desk/doctype/tag/tag.py +++ b/frappe/desk/doctype/tag/tag.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import unique diff --git a/frappe/desk/doctype/tag/test_tag.py b/frappe/desk/doctype/tag/test_tag.py index 8efd692f43..442a891fd8 100644 --- a/frappe/desk/doctype/tag/test_tag.py +++ b/frappe/desk/doctype/tag/test_tag.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/tag_link/tag_link.py b/frappe/desk/doctype/tag_link/tag_link.py index 87c8af7212..4c5149f42c 100644 --- a/frappe/desk/doctype/tag_link/tag_link.py +++ b/frappe/desk/doctype/tag_link/tag_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/tag_link/test_tag_link.py b/frappe/desk/doctype/tag_link/test_tag_link.py index 1c22ac18bc..297ee3cc96 100644 --- a/frappe/desk/doctype/tag_link/test_tag_link.py +++ b/frappe/desk/doctype/tag_link/test_tag_link.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/todo/__init__.py b/frappe/desk/doctype/todo/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/desk/doctype/todo/__init__.py +++ b/frappe/desk/doctype/todo/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/desk/doctype/todo/test_todo.py b/frappe/desk/doctype/todo/test_todo.py index de5b6724a6..b38e4a059a 100644 --- a/frappe/desk/doctype/todo/test_todo.py +++ b/frappe/desk/doctype/todo/test_todo.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.model.db_query import DatabaseQuery diff --git a/frappe/desk/doctype/todo/todo.py b/frappe/desk/doctype/todo/todo.py index a766375fde..4696563445 100644 --- a/frappe/desk/doctype/todo/todo.py +++ b/frappe/desk/doctype/todo/todo.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import json @@ -93,7 +92,7 @@ def get_permission_query_conditions(user): if not user: user = frappe.session.user todo_roles = frappe.permissions.get_doctype_roles('ToDo') - if 'All' in todo_roles: + if 'All' in todo_roles: todo_roles.remove('All') if any(check in todo_roles for check in frappe.get_roles(user)): @@ -105,7 +104,7 @@ def get_permission_query_conditions(user): def has_permission(doc, ptype="read", user=None): user = user or frappe.session.user todo_roles = frappe.permissions.get_doctype_roles('ToDo', ptype) - if 'All' in todo_roles: + if 'All' in todo_roles: todo_roles.remove('All') if any(check in todo_roles for check in frappe.get_roles(user)): diff --git a/frappe/desk/doctype/workspace/test_workspace.py b/frappe/desk/doctype/workspace/test_workspace.py index 7a3f122ee2..619b3608eb 100644 --- a/frappe/desk/doctype/workspace/test_workspace.py +++ b/frappe/desk/doctype/workspace/test_workspace.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 0934138821..0329e0f7d2 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.modules.export_file import export_to_files diff --git a/frappe/desk/doctype/workspace_chart/workspace_chart.py b/frappe/desk/doctype/workspace_chart/workspace_chart.py index 0bb6194d2e..6ec7abfd3c 100644 --- a/frappe/desk/doctype/workspace_chart/workspace_chart.py +++ b/frappe/desk/doctype/workspace_chart/workspace_chart.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/workspace_link/workspace_link.py b/frappe/desk/doctype/workspace_link/workspace_link.py index 8a139077a6..d6ccc5306a 100644 --- a/frappe/desk/doctype/workspace_link/workspace_link.py +++ b/frappe/desk/doctype/workspace_link/workspace_link.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py b/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py index d676f08b73..83b446e454 100644 --- a/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py +++ b/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/desk/form/__init__.py b/frappe/desk/form/__init__.py index 4dbcd0d163..0e57cb68c3 100644 --- a/frappe/desk/form/__init__.py +++ b/frappe/desk/form/__init__.py @@ -1,4 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py index aee7a8e52a..3eda291d1e 100644 --- a/frappe/desk/form/assign_to.py +++ b/frappe/desk/form/assign_to.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals """assign/unassign to ToDo""" import frappe diff --git a/frappe/desk/form/document_follow.py b/frappe/desk/form/document_follow.py index f5e5c0ca9b..7f65f76a58 100644 --- a/frappe/desk/form/document_follow.py +++ b/frappe/desk/form/document_follow.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import frappe.utils from frappe.utils import get_url_to_form diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py index a62e2837d5..12880604a2 100644 --- a/frappe/desk/form/linked_with.py +++ b/frappe/desk/form/linked_with.py @@ -1,9 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import json from collections import defaultdict -from six import string_types import frappe import frappe.desk.form.load import frappe.desk.form.meta @@ -87,7 +85,7 @@ def cancel_all_linked_docs(docs, ignore_doctypes_on_cancel_all=[]): """ docs = json.loads(docs) - if isinstance(ignore_doctypes_on_cancel_all, string_types): + if isinstance(ignore_doctypes_on_cancel_all, str): ignore_doctypes_on_cancel_all = json.loads(ignore_doctypes_on_cancel_all) for i, doc in enumerate(docs, 1): if validate_linked_doc(doc, ignore_doctypes_on_cancel_all): @@ -139,7 +137,7 @@ def get_exempted_doctypes(): @frappe.whitelist() def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None): - if isinstance(linkinfo, string_types): + if isinstance(linkinfo, str): # additional fields are added in linkinfo linkinfo = json.loads(linkinfo) @@ -202,7 +200,7 @@ def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None): else: link_fieldnames = link.get("fieldname") if link_fieldnames: - if isinstance(link_fieldnames, string_types): link_fieldnames = [link_fieldnames] + if isinstance(link_fieldnames, str): link_fieldnames = [link_fieldnames] or_filters = [[dt, fieldname, '=', name] for fieldname in link_fieldnames] # dynamic link if link.get("doctype_fieldname"): diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index d81bb8c26c..a62bfd01d0 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, json import frappe.utils import frappe.share @@ -11,7 +10,7 @@ from frappe.model.utils.user_settings import get_user_settings from frappe.permissions import get_doc_permissions from frappe.desk.form.document_follow import is_document_followed from frappe import _ -from six.moves.urllib.parse import quote +from urllib.parse import quote @frappe.whitelist(allow_guest=True) def getdoc(doctype, name, user=None): diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index 087cc54d9d..947a9e5d4b 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -2,9 +2,7 @@ # MIT License. See license.txt # metadata - -from __future__ import unicode_literals -import frappe, os +import frappe, os, io from frappe.model.meta import Meta from frappe.modules import scrub, get_module_path, load_doctype_module from frappe.utils import get_html_format @@ -12,9 +10,6 @@ from frappe.translate import make_dict_from_messages, extract_messages_from_code from frappe.model.utils import render_include from frappe.build import scrub_html_template -import io - -from six import iteritems def get_meta(doctype, cached=True): # don't cache for developer mode as js files, templates may be edited @@ -199,7 +194,7 @@ class FormMeta(Meta): app = module.__name__.split(".")[0] templates = {} if hasattr(module, "form_grid_templates"): - for key, path in iteritems(module.form_grid_templates): + for key, path in module.form_grid_templates.items(): templates[key] = get_html_format(frappe.get_app_path(app, path)) self.set("__form_grid_templates", templates) diff --git a/frappe/desk/form/save.py b/frappe/desk/form/save.py index da43b14fce..a7a4b829d8 100644 --- a/frappe/desk/form/save.py +++ b/frappe/desk/form/save.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, json from frappe.desk.form.load import run_onload diff --git a/frappe/desk/form/test_form.py b/frappe/desk/form/test_form.py index ff0343b6e0..f3c4132777 100644 --- a/frappe/desk/form/test_form.py +++ b/frappe/desk/form/test_form.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, unittest from frappe.desk.form.linked_with import get_linked_docs, get_linked_doctypes diff --git a/frappe/desk/form/utils.py b/frappe/desk/form/utils.py index 395d2b9571..bfceee6ea2 100644 --- a/frappe/desk/form/utils.py +++ b/frappe/desk/form/utils.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, json import frappe.desk.form.meta import frappe.desk.form.load @@ -9,7 +8,6 @@ from frappe.desk.form.document_follow import follow_document from frappe.utils.file_manager import extract_images_from_html from frappe import _ -from six import string_types @frappe.whitelist() def remove_attach(): @@ -90,7 +88,7 @@ def get_next(doctype, value, prev, filters=None, sort_order='desc', sort_field=' prev = int(prev) if not filters: filters = [] - if isinstance(filters, string_types): + if isinstance(filters, str): filters = json.loads(filters) # # condition based on sort order diff --git a/frappe/desk/gantt.py b/frappe/desk/gantt.py index 521884beaa..7f0889c751 100644 --- a/frappe/desk/gantt.py +++ b/frappe/desk/gantt.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, json @frappe.whitelist() diff --git a/frappe/desk/leaderboard.py b/frappe/desk/leaderboard.py index d651687256..a98ae1a1c6 100644 --- a/frappe/desk/leaderboard.py +++ b/frappe/desk/leaderboard.py @@ -1,5 +1,3 @@ - -from __future__ import unicode_literals, print_function import frappe from frappe.utils import get_fullname diff --git a/frappe/desk/like.py b/frappe/desk/like.py index 6d2e9704af..d44d58a761 100644 --- a/frappe/desk/like.py +++ b/frappe/desk/like.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - """Allow adding of likes to documents""" import frappe, json diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index 91dc0f3ba9..d2c84d36bf 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -1,7 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe @frappe.whitelist(allow_guest=True) diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index df25b77e2d..021698ac92 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import json from frappe import _ diff --git a/frappe/desk/notifications.py b/frappe/desk/notifications.py index 4b584a2429..c84027928e 100644 --- a/frappe/desk/notifications.py +++ b/frappe/desk/notifications.py @@ -1,11 +1,8 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe.desk.doctype.notification_settings.notification_settings import get_subscribed_documents -from six import string_types import json @frappe.whitelist() @@ -149,7 +146,7 @@ def clear_doctype_notifications(doc, method=None, *args, **kwargs): config = get_notification_config() if not config: return - if isinstance(doc, string_types): + if isinstance(doc, str): doctype = doc # assuming doctype name was passed directly else: doctype = doc.doctype @@ -213,7 +210,7 @@ def get_filters_for(doctype): '''get open filters for doctype''' config = get_notification_config() doctype_config = config.get("for_doctype").get(doctype, {}) - filters = doctype_config if not isinstance(doctype_config, string_types) else None + filters = doctype_config if not isinstance(doctype_config, str) else None return filters diff --git a/frappe/desk/page/activity/__init__.py b/frappe/desk/page/activity/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/desk/page/activity/__init__.py +++ b/frappe/desk/page/activity/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/desk/page/activity/activity.py b/frappe/desk/page/activity/activity.py index 7de294d2f0..3abc8e0ea5 100644 --- a/frappe/desk/page/activity/activity.py +++ b/frappe/desk/page/activity/activity.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import cint from frappe.core.doctype.activity_log.feed import get_feed_match_conditions diff --git a/frappe/desk/page/backups/backups.py b/frappe/desk/page/backups/backups.py index eaa0c65143..2229a6d89e 100644 --- a/frappe/desk/page/backups/backups.py +++ b/frappe/desk/page/backups/backups.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import os import frappe from frappe import _ diff --git a/frappe/desk/page/leaderboard/leaderboard.py b/frappe/desk/page/leaderboard/leaderboard.py index 819e7fe9d1..9469096f50 100644 --- a/frappe/desk/page/leaderboard/leaderboard.py +++ b/frappe/desk/page/leaderboard/leaderboard.py @@ -1,7 +1,5 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function import frappe @frappe.whitelist() diff --git a/frappe/desk/page/setup_wizard/install_fixtures.py b/frappe/desk/page/setup_wizard/install_fixtures.py index 6d3aaee22b..06301cdeaf 100644 --- a/frappe/desk/page/setup_wizard/install_fixtures.py +++ b/frappe/desk/page/setup_wizard/install_fixtures.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals - import frappe from frappe import _ from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py index 1ac5279508..5edb44e182 100755 --- a/frappe/desk/page/setup_wizard/setup_wizard.py +++ b/frappe/desk/page/setup_wizard/setup_wizard.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals - import frappe, json, os from frappe.utils import strip, cint from frappe.translate import (set_default_language, get_dict, send_translations) @@ -10,7 +8,6 @@ from frappe.geo.country_info import get_country_info from frappe.utils.password import update_password from werkzeug.useragents import UserAgent from . import install_fixtures -from six import string_types def get_setup_stages(args): @@ -208,14 +205,14 @@ def update_user_name(args): def parse_args(args): if not args: args = frappe.local.form_dict - if isinstance(args, string_types): + if isinstance(args, str): args = json.loads(args) args = frappe._dict(args) # strip the whitespace for key, value in args.items(): - if isinstance(value, string_types): + if isinstance(value, str): args[key] = strip(value) return args @@ -294,7 +291,7 @@ def reset_is_first_startup(): def prettify_args(args): # remove attachments for key, val in args.items(): - if isinstance(val, string_types) and "data:image" in val: + if isinstance(val, str) 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) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index befaf7b01f..3c0ebf11c1 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import os import json @@ -22,7 +20,6 @@ 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, iteritems from datetime import timedelta from frappe.core.utils import ljust_list @@ -66,7 +63,7 @@ def generate_report_result(report, filters=None, user=None, custom_columns=None) user = user or frappe.session.user filters = filters or [] - if filters and isinstance(filters, string_types): + if filters and isinstance(filters, str): filters = json.loads(filters) res = [] @@ -222,7 +219,7 @@ def run(report_name, filters=None, user=None, ignore_prepared_report=False, cust and not custom_columns ): if filters: - if isinstance(filters, string_types): + if isinstance(filters, str): filters = json.loads(filters) dn = filters.get("prepared_report_name") @@ -317,7 +314,7 @@ def export_query(): data.pop("cmd", None) data.pop("csrf_token", None) - if isinstance(data.get("filters"), string_types): + if isinstance(data.get("filters"), str): filters = json.loads(data["filters"]) if data.get("report_name"): @@ -332,7 +329,7 @@ def export_query(): include_indentation = data.get("include_indentation") visible_idx = data.get("visible_idx") - if isinstance(visible_idx, string_types): + if isinstance(visible_idx, str): visible_idx = json.loads(visible_idx) if file_format_type == "Excel": @@ -363,7 +360,7 @@ def export_query(): def handle_duration_fieldtype_values(result, columns): for i, col in enumerate(columns): fieldtype = None - if isinstance(col, string_types): + if isinstance(col, str): col = col.split(":") if len(col) > 1: if col[1]: @@ -433,7 +430,7 @@ def add_total_row(result, columns, meta=None): has_percent = [] for i, col in enumerate(columns): fieldtype, options, fieldname = None, None, None - if isinstance(col, string_types): + if isinstance(col, str): if meta: # get fieldtype from the meta field = meta.get_field(col) @@ -483,7 +480,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], string_types): + if isinstance(columns[0], str): first_col = columns[0].split(":") if len(first_col) > 1: first_col_fieldtype = first_col[1].split("/")[0] @@ -701,7 +698,7 @@ def get_linked_doctypes(columns, data): if val and col not in columns_with_value: columns_with_value.append(col) - items = list(iteritems(linked_doctypes)) + items = list(linked_doctypes.items()) for doctype, key in items: if key not in columns_with_value: @@ -728,7 +725,7 @@ def get_column_as_dict(col): col_dict = frappe._dict() # string - if isinstance(col, string_types): + if isinstance(col, str): col = col.split(":") if len(col) > 1: if "/" in col[1]: diff --git a/frappe/desk/report/todo/todo.py b/frappe/desk/report/todo/todo.py index f4fe2dc805..6bd22b843e 100644 --- a/frappe/desk/report/todo/todo.py +++ b/frappe/desk/report/todo/todo.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import getdate diff --git a/frappe/desk/report_dump.py b/frappe/desk/report_dump.py index 86b1765814..b2d3ca3443 100644 --- a/frappe/desk/report_dump.py +++ b/frappe/desk/report_dump.py @@ -1,8 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals -from six.moves import range + import frappe import json import copy diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 86f8ec0aa7..55515856f1 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -1,16 +1,14 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals """build query for doclistview and return results""" import frappe, json -from six.moves import range import frappe.permissions from frappe.model.db_query import DatabaseQuery from frappe.model import default_fields, optional_fields from frappe import _ -from six import string_types, StringIO +from io import StringIO from frappe.core.doctype.access_log.access_log import make_access_log from frappe.utils import cstr, format_duration from frappe.model.base_document import get_controller @@ -171,7 +169,7 @@ def get_meta_and_docfield(fieldname, data): return meta, df def update_wildcard_field_param(data): - if ((isinstance(data.fields, string_types) and data.fields == "*") + if ((isinstance(data.fields, str) and data.fields == "*") or (isinstance(data.fields, (list, tuple)) and len(data.fields) == 1 and data.fields[0] == "*")): data.fields = frappe.db.get_table_columns(data.doctype) return True @@ -191,15 +189,15 @@ def clean_params(data): def parse_json(data): - if isinstance(data.get("filters"), string_types): + if isinstance(data.get("filters"), str): data["filters"] = json.loads(data["filters"]) - if isinstance(data.get("or_filters"), string_types): + if isinstance(data.get("or_filters"), str): data["or_filters"] = json.loads(data["or_filters"]) - if isinstance(data.get("fields"), string_types): + if isinstance(data.get("fields"), str): data["fields"] = json.loads(data["fields"]) - if isinstance(data.get("docstatus"), string_types): + if isinstance(data.get("docstatus"), str): data["docstatus"] = json.loads(data["docstatus"]) - if isinstance(data.get("save_user_settings"), string_types): + if isinstance(data.get("save_user_settings"), str): data["save_user_settings"] = json.loads(data["save_user_settings"]) else: data["save_user_settings"] = True @@ -311,7 +309,7 @@ def export_query(): for r in data: # encode only unicode type strings and not int, floats etc. writer.writerow([handle_html(frappe.as_unicode(v)) \ - if isinstance(v, string_types) else v for v in r]) + if isinstance(v, str) else v for v in r]) f.seek(0) frappe.response['result'] = cstr(f.read()) @@ -540,7 +538,7 @@ def build_match_conditions(doctype, user=None, as_condition=True): return match_conditions def get_filters_cond(doctype, filters, conditions, ignore_permissions=None, with_match_conditions=False): - if isinstance(filters, string_types): + if isinstance(filters, str): filters = json.loads(filters) if filters: @@ -549,7 +547,7 @@ def get_filters_cond(doctype, filters, conditions, ignore_permissions=None, with filters = filters.items() flt = [] for f in filters: - if isinstance(f[1], string_types) and f[1][0] == '!': + if isinstance(f[1], str) and f[1][0] == '!': flt.append([doctype, f[0], '!=', f[1][1:]]) elif isinstance(f[1], (list, tuple)) and \ f[1][0] in (">", "<", ">=", "<=", "!=", "like", "not like", "in", "not in", "between"): diff --git a/frappe/desk/search.py b/frappe/desk/search.py index 3c9109eca9..040a8c2118 100644 --- a/frappe/desk/search.py +++ b/frappe/desk/search.py @@ -2,12 +2,10 @@ # MIT License. See license.txt # Search -from __future__ import unicode_literals import frappe, json from frappe.utils import cstr, unique, cint from frappe.permissions import has_permission from frappe import _, is_whitelisted -from six import string_types import re import wrapt @@ -62,7 +60,7 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, start = cint(start) - if isinstance(filters, string_types): + if isinstance(filters, str): filters = json.loads(filters) if searchfield: diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index 6f0d7d3d5f..66acde4cb2 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/email/__init__.py b/frappe/email/__init__.py index b05aef7639..3fb539398a 100644 --- a/frappe/email/__init__.py +++ b/frappe/email/__init__.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.desk.reportview import build_match_conditions diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.py b/frappe/email/doctype/auto_email_report/auto_email_report.py index 6f1cd8eebd..911af2d1c7 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/auto_email_report.py @@ -2,8 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import calendar from datetime import timedelta diff --git a/frappe/email/doctype/auto_email_report/test_auto_email_report.py b/frappe/email/doctype/auto_email_report/test_auto_email_report.py index e656ff18f7..211a141ec0 100644 --- a/frappe/email/doctype/auto_email_report/test_auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/test_auto_email_report.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import json import unittest diff --git a/frappe/email/doctype/document_follow/document_follow.py b/frappe/email/doctype/document_follow/document_follow.py index aaabffab6b..a04f8ef4c2 100644 --- a/frappe/email/doctype/document_follow/document_follow.py +++ b/frappe/email/doctype/document_follow/document_follow.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class DocumentFollow(Document): diff --git a/frappe/email/doctype/document_follow/test_document_follow.py b/frappe/email/doctype/document_follow/test_document_follow.py index 38aa870232..456c0931f8 100644 --- a/frappe/email/doctype/document_follow/test_document_follow.py +++ b/frappe/email/doctype/document_follow/test_document_follow.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import frappe.desk.form.document_follow as document_follow diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 36b662bb39..d797c72859 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt - -from __future__ import unicode_literals, print_function import frappe import imaplib import re diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index f87ee32bb1..1b92811eb7 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals import frappe, os import unittest, email diff --git a/frappe/email/doctype/email_domain/email_domain.py b/frappe/email/doctype/email_domain/email_domain.py index ce39523564..0856549eb7 100644 --- a/frappe/email/doctype/email_domain/email_domain.py +++ b/frappe/email/doctype/email_domain/email_domain.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/email/doctype/email_domain/test_email_domain.py b/frappe/email/doctype/email_domain/test_email_domain.py index 1c5306e9c2..8607151ca8 100644 --- a/frappe/email/doctype/email_domain/test_email_domain.py +++ b/frappe/email/doctype/email_domain/test_email_domain.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.test_runner import make_test_objects diff --git a/frappe/email/doctype/email_flag_queue/email_flag_queue.py b/frappe/email/doctype/email_flag_queue/email_flag_queue.py index 487ef7db50..9bb30f08b2 100644 --- a/frappe/email/doctype/email_flag_queue/email_flag_queue.py +++ b/frappe/email/doctype/email_flag_queue/email_flag_queue.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py b/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py index 644a2a8ff7..d09b823ce6 100644 --- a/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py +++ b/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/email_group/email_group.py b/frappe/email/doctype/email_group/email_group.py index b19a134713..597aa9c18b 100755 --- a/frappe/email/doctype/email_group/email_group.py +++ b/frappe/email/doctype/email_group/email_group.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import validate_email_address diff --git a/frappe/email/doctype/email_group/test_email_group.py b/frappe/email/doctype/email_group/test_email_group.py index 09f4f4c32c..3e894118df 100644 --- a/frappe/email/doctype/email_group/test_email_group.py +++ b/frappe/email/doctype/email_group/test_email_group.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/email_group_member/email_group_member.py b/frappe/email/doctype/email_group_member/email_group_member.py index 23b279e755..1f9303b83e 100644 --- a/frappe/email/doctype/email_group_member/email_group_member.py +++ b/frappe/email/doctype/email_group_member/email_group_member.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_group_member/test_email_group_member.py b/frappe/email/doctype/email_group_member/test_email_group_member.py index 35259617c1..829d686400 100644 --- a/frappe/email/doctype/email_group_member/test_email_group_member.py +++ b/frappe/email/doctype/email_group_member/test_email_group_member.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/email_queue/test_email_queue.py b/frappe/email/doctype/email_queue/test_email_queue.py index 7cd79f9259..b76d6347b9 100644 --- a/frappe/email/doctype/email_queue/test_email_queue.py +++ b/frappe/email/doctype/email_queue/test_email_queue.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py b/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py index 3f07ec58f3..055bdb3fc1 100644 --- a/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py +++ b/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_rule/email_rule.py b/frappe/email/doctype/email_rule/email_rule.py index 220798bbdc..9807724ef1 100644 --- a/frappe/email/doctype/email_rule/email_rule.py +++ b/frappe/email/doctype/email_rule/email_rule.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/email_rule/test_email_rule.py b/frappe/email/doctype/email_rule/test_email_rule.py index 3c7f9c83e6..b2213f7405 100644 --- a/frappe/email/doctype/email_rule/test_email_rule.py +++ b/frappe/email/doctype/email_rule/test_email_rule.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/email_template/email_template.py b/frappe/email/doctype/email_template/email_template.py index 6708e9dd3f..4711451fd2 100644 --- a/frappe/email/doctype/email_template/email_template.py +++ b/frappe/email/doctype/email_template/email_template.py @@ -1,11 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # For license information, please see license.txt -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 EmailTemplate(Document): def validate(self): @@ -24,7 +22,7 @@ class EmailTemplate(Document): return frappe.render_template(self.response, doc) def get_formatted_email(self, doc): - if isinstance(doc, string_types): + if isinstance(doc, str): doc = json.loads(doc) return { @@ -36,7 +34,7 @@ class EmailTemplate(Document): @frappe.whitelist() def get_email_template(template_name, doc): '''Returns the processed HTML of a email template with the given doc''' - if isinstance(doc, string_types): + if isinstance(doc, str): doc = json.loads(doc) email_template = frappe.get_doc("Email Template", template_name) diff --git a/frappe/email/doctype/email_template/test_email_template.py b/frappe/email/doctype/email_template/test_email_template.py index a48ce94ac5..5a9ee969c6 100644 --- a/frappe/email/doctype/email_template/test_email_template.py +++ b/frappe/email/doctype/email_template/test_email_template.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestEmailTemplate(unittest.TestCase): diff --git a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py index e532e2b7eb..6c47d8c538 100644 --- a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +++ b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ diff --git a/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py b/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py index ea84253ab6..602840fe3b 100644 --- a/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py +++ b/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 6412338e96..3cba8f927c 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals - import frappe import frappe.utils from frappe import throw, _ diff --git a/frappe/email/doctype/newsletter/test_newsletter.py b/frappe/email/doctype/newsletter/test_newsletter.py index bd8fadc29c..cfd0df53a9 100644 --- a/frappe/email/doctype/newsletter/test_newsletter.py +++ b/frappe/email/doctype/newsletter/test_newsletter.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals - import unittest from random import choice diff --git a/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py b/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py index a59ac372fd..a453dda9e4 100644 --- a/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py +++ b/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 2940a34f63..57418515f5 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import json, os from frappe import _ @@ -12,7 +11,6 @@ from frappe.utils import validate_email_address, nowdate, parse_val, is_html, ad from frappe.utils.jinja import validate_template from frappe.utils.safe_exec import get_safe_globals from frappe.modules.utils import export_module_json, get_doc_module -from six import string_types from frappe.integrations.doctype.slack_webhook_url.slack_webhook_url import send_slack_message from frappe.core.doctype.sms_settings.sms_settings import send_sms from frappe.desk.doctype.notification_log.notification_log import enqueue_create_notification @@ -55,9 +53,7 @@ class Notification(Document): # py if not os.path.exists(path + '.py'): with open(path + '.py', 'w') as f: - f.write("""from __future__ import unicode_literals - -import frappe + f.write("""import frappe def get_context(context): # do your magic here @@ -397,7 +393,7 @@ def trigger_notifications(doc, method=None): def evaluate_alert(doc, alert, event): from jinja2 import TemplateError try: - if isinstance(alert, string_types): + if isinstance(alert, str): alert = frappe.get_doc("Notification", alert) context = get_context(doc) diff --git a/frappe/email/doctype/notification/test_notification.py b/frappe/email/doctype/notification/test_notification.py index 31d5d9d1cc..d6358ccbbe 100644 --- a/frappe/email/doctype/notification/test_notification.py +++ b/frappe/email/doctype/notification/test_notification.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe, frappe.utils, frappe.utils.scheduler from frappe.desk.form import assign_to import unittest diff --git a/frappe/email/doctype/notification_recipient/notification_recipient.py b/frappe/email/doctype/notification_recipient/notification_recipient.py index a85ed62c04..d8480c5455 100644 --- a/frappe/email/doctype/notification_recipient/notification_recipient.py +++ b/frappe/email/doctype/notification_recipient/notification_recipient.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/doctype/unhandled_email/test_unhandled_email.py b/frappe/email/doctype/unhandled_email/test_unhandled_email.py index 6cabcf6ec2..5606b8ff30 100644 --- a/frappe/email/doctype/unhandled_email/test_unhandled_email.py +++ b/frappe/email/doctype/unhandled_email/test_unhandled_email.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/email/doctype/unhandled_email/unhandled_email.py b/frappe/email/doctype/unhandled_email/unhandled_email.py index 1276da71a1..6414dbece3 100644 --- a/frappe/email/doctype/unhandled_email/unhandled_email.py +++ b/frappe/email/doctype/unhandled_email/unhandled_email.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py index 3b03c42b95..7f4398ef2f 100755 --- a/frappe/email/email_body.py +++ b/frappe/email/email_body.py @@ -1,14 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, re, os from frappe.utils.pdf import get_pdf from frappe.email.doctype.email_account.email_account import EmailAccount from frappe.utils import (get_url, scrub_urls, strip, expand_relative_urls, cint, split_emails, to_markdown, markdown, random_string, parse_addr) import email.utils -from six import iteritems, text_type, string_types from email.mime.multipart import MIMEMultipart from email.header import Header from email import policy @@ -55,7 +53,7 @@ class EMail: from email import charset as Charset Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') - if isinstance(recipients, string_types): + if isinstance(recipients, str): recipients = recipients.replace(';', ',').replace('\n', '') recipients = split_emails(recipients) @@ -225,7 +223,7 @@ class EMail: } # reset headers as values may be changed. - for key, val in iteritems(headers): + for key, val in headers.items(): if val: self.set_header(key, val) @@ -328,7 +326,7 @@ def add_attachment(fname, fcontent, content_type=None, maintype, subtype = content_type.split('/', 1) if maintype == 'text': # Note: we should handle calculating the charset - if isinstance(fcontent, text_type): + if isinstance(fcontent, str): fcontent = fcontent.encode("utf-8") part = MIMEText(fcontent, _subtype=subtype, _charset="utf-8") elif maintype == 'image': @@ -345,7 +343,7 @@ def add_attachment(fname, fcontent, content_type=None, # Set the filename parameter if fname: attachment_type = 'inline' if inline else 'attachment' - part.add_header('Content-Disposition', attachment_type, filename=text_type(fname)) + part.add_header('Content-Disposition', attachment_type, filename=str(fname)) if content_id: part.add_header('Content-ID', '<{0}>'.format(content_id)) @@ -452,7 +450,7 @@ def get_header(header=None): if not header: return None - if isinstance(header, string_types): + if isinstance(header, str): # header = 'My Title' header = [header, None] if len(header) == 1: diff --git a/frappe/email/inbox.py b/frappe/email/inbox.py index 395a2d3e2d..5f8f516772 100644 --- a/frappe/email/inbox.py +++ b/frappe/email/inbox.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe import json diff --git a/frappe/email/queue.py b/frappe/email/queue.py index 52c91baf1c..7aef75b669 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -1,10 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import sys -from six.moves import html_parser as HTMLParser +from html.parser import HTMLParser import smtplib, quopri, json from frappe import msgprint, _, safe_decode, safe_encode, enqueue from frappe.email.smtp import SMTPServer @@ -14,7 +13,6 @@ from frappe.utils.verified_command import get_signed_params, verify_request from html2text import html2text from frappe.utils import get_url, nowdate, now_datetime, add_days, split_emails, cstr, cint from rq.timeouts import JobTimeoutException -from six import text_type, string_types, PY3 from email.parser import Parser @@ -62,13 +60,13 @@ def send(recipients=None, sender=None, subject=None, message=None, text_content= if not bcc: bcc = [] - if isinstance(recipients, string_types): + if isinstance(recipients, str): recipients = split_emails(recipients) - if isinstance(cc, string_types): + if isinstance(cc, str): cc = split_emails(cc) - if isinstance(bcc, string_types): + if isinstance(bcc, str): bcc = split_emails(bcc) if isinstance(send_after, int): diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 6d60007cdb..803712e7b0 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -12,7 +12,6 @@ from email.header import decode_header import _socket import chardet -import six from email_reply_parser import EmailReplyParser import frappe @@ -361,13 +360,10 @@ class Email: """Parses headers, content, attachments from given raw message. :param content: Raw message.""" - if six.PY2: - self.mail = email.message_from_string(safe_encode(content)) + if isinstance(content, bytes): + self.mail = email.message_from_bytes(content) else: - if isinstance(content, bytes): - self.mail = email.message_from_bytes(content) - else: - self.mail = email.message_from_string(content) + self.mail = email.message_from_string(content) self.text_content = '' self.html_content = '' diff --git a/frappe/email/smtp.py b/frappe/email/smtp.py index 3acb76af23..9425f4dbd4 100644 --- a/frappe/email/smtp.py +++ b/frappe/email/smtp.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import smtplib import email.utils diff --git a/frappe/email/test_email_body.py b/frappe/email/test_email_body.py index 33668cddba..1961d7801e 100644 --- a/frappe/email/test_email_body.py +++ b/frappe/email/test_email_body.py @@ -1,7 +1,5 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals - import unittest, os, base64 from frappe import safe_decode from frappe.email.receive import Email @@ -9,7 +7,7 @@ from frappe.email.email_body import (replace_filename_with_cid, get_email, inline_style_in_html, get_header) from frappe.email.queue import get_email_queue from frappe.email.doctype.email_queue.email_queue import SendMailContext -from six import PY3 + class TestEmailBody(unittest.TestCase): def setUp(self): @@ -42,13 +40,8 @@ This is the text version of this email ).as_string().replace("\r\n", "\n") def test_prepare_message_returns_already_encoded_string(self): - - if PY3: - uni_chr1 = chr(40960) - uni_chr2 = chr(1972) - else: - uni_chr1 = unichr(40960) - uni_chr2 = unichr(1972) + uni_chr1 = chr(40960) + uni_chr2 = chr(1972) email = get_email_queue( recipients=['test@example.com'], @@ -73,10 +66,7 @@ This is the text version of this email mail_ctx = SendMailContext(queue_doc = email) result = safe_decode(mail_ctx.build_message(recipient_email='test@test.com')) - if PY3: - self.assertTrue(result.count('\n') == result.count("\r")) - else: - self.assertTrue(True) + self.assertTrue(result.count('\n') == result.count("\r")) def test_image(self): img_signature = ''' diff --git a/frappe/email/utils.py b/frappe/email/utils.py index 8b4bd95ba0..24ce77b922 100644 --- a/frappe/email/utils.py +++ b/frappe/email/utils.py @@ -1,7 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt - -from __future__ import unicode_literals, print_function import imaplib, poplib from frappe.utils import cint diff --git a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py index 1ab9534bdc..fc8164d8a4 100644 --- a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py +++ b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py index bf96e4e27b..2cf7282a5a 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py @@ -1,12 +1,9 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt - -from __future__ import unicode_literals import frappe import json from frappe import _ -from six import iteritems from frappe.model.document import Document from frappe.model import default_fields @@ -100,7 +97,7 @@ class DocumentTypeMapping(Document): def get_mapped_dependency(self, mapping, producer_site, doc): inner_mapping = frappe.get_doc('Document Type Mapping', mapping.mapping) filters = json.loads(mapping.remote_value_filters) - for key, value in iteritems(filters): + for key, value in filters.items(): if value.startswith('eval:'): val = frappe.safe_eval(value[5:], None, dict(doc=doc)) filters[key] = val @@ -117,7 +114,7 @@ class DocumentTypeMapping(Document): def map_rows_removed(self, update_diff, mapping): removed = [] mapping['removed'] = update_diff.removed - for key, value in iteritems(update_diff.removed.copy()): + for key, value in update_diff.removed.copy().items(): local_table_name = frappe.db.get_value('Document Type Field Mapping', { 'remote_fieldname': key, 'parent': self.name @@ -133,7 +130,7 @@ class DocumentTypeMapping(Document): def map_rows(self, update_diff, mapping, producer_site, operation): remote_fields = [] - for tablename, entries in iteritems(update_diff.get(operation).copy()): + for tablename, entries in update_diff.get(operation).copy().items(): local_table_name = frappe.db.get_value('Document Type Field Mapping', {'remote_fieldname': tablename}, 'local_fieldname') table_map = frappe.db.get_value('Document Type Field Mapping', {'local_fieldname': local_table_name, 'parent': self.name}, 'mapping') table_map = frappe.get_doc('Document Type Mapping', table_map) diff --git a/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py index 178d7b6b6a..b1bb322855 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_consumer/event_consumer.py b/frappe/event_streaming/doctype/event_consumer/event_consumer.py index 5789e09e74..00d304f7f4 100644 --- a/frappe/event_streaming/doctype/event_consumer/event_consumer.py +++ b/frappe/event_streaming/doctype/event_consumer/event_consumer.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import json import requests @@ -31,7 +30,7 @@ class EventConsumer(Document): self.update_consumer_status() else: frappe.db.set_value(self.doctype, self.name, 'incoming_change', 0) - + frappe.cache().delete_value('event_consumer_document_type_map') def on_trash(self): diff --git a/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py b/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py index 9e344842bd..b8072ecabd 100644 --- a/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py +++ b/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py b/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py index 197338027f..cf5d18edfd 100644 --- a/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py +++ b/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_producer/test_event_producer.py b/frappe/event_streaming/doctype/event_producer/test_event_producer.py index 4c259c3729..883f4f2df2 100644 --- a/frappe/event_streaming/doctype/event_producer/test_event_producer.py +++ b/frappe/event_streaming/doctype/event_producer/test_event_producer.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import json @@ -154,7 +152,7 @@ class TestEventProducer(unittest.TestCase): def test_conditional_events(self): producer = get_remote_site() - + # Add Condition event_producer = frappe.get_doc('Event Producer', producer_url) note_producer_entry = [ @@ -192,7 +190,7 @@ class TestEventProducer(unittest.TestCase): def test_conditional_events_with_cmd(self): producer = get_remote_site() - + # Add Condition event_producer = frappe.get_doc('Event Producer', producer_url) note_producer_entry = [ diff --git a/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py b/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py index 2870d5330f..9ae70e0f97 100644 --- a/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py +++ b/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py b/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py index 02e297bdd5..391cf79c27 100644 --- a/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py +++ b/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py b/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py index 0311cb2df9..62ea71edab 100644 --- a/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py +++ b/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py b/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py index 31b1f863aa..1d255a5c30 100644 --- a/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py +++ b/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py b/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py index 6c621b8b0e..ef55dc0f16 100644 --- a/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py +++ b/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_update_log/event_update_log.py b/frappe/event_streaming/doctype/event_update_log/event_update_log.py index 1c31718c2b..ae851c70d1 100644 --- a/frappe/event_streaming/doctype/event_update_log/event_update_log.py +++ b/frappe/event_streaming/doctype/event_update_log/event_update_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils.background_jobs import get_jobs @@ -235,7 +234,7 @@ def get_update_logs_for_consumer(event_consumer, doctypes, last_update): if isinstance(doctypes, str): doctypes = frappe.parse_json(doctypes) - + from frappe.event_streaming.doctype.event_consumer.event_consumer import has_consumer_access consumer = frappe.get_doc('Event Consumer', event_consumer) diff --git a/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py b/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py index e00fc767d9..99ced3c209 100644 --- a/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py +++ b/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py b/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py index ee6d5d8ca9..80a59e4c31 100644 --- a/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py +++ b/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/exceptions.py b/frappe/exceptions.py index ab65e6e006..0f111fdcf9 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import sys # BEWARE don't put anything in this file except exceptions diff --git a/frappe/frappeclient.py b/frappe/frappeclient.py index 054a8c9369..e57f82b60a 100644 --- a/frappe/frappeclient.py +++ b/frappe/frappeclient.py @@ -1,8 +1,6 @@ -from __future__ import print_function, unicode_literals import requests import json import frappe -from six import iteritems, string_types import base64 ''' @@ -88,7 +86,7 @@ class FrappeClient(object): def get_list(self, doctype, fields='["name"]', filters=None, limit_start=0, limit_page_length=0): """Returns list of records of a particular type""" - if not isinstance(fields, string_types): + if not isinstance(fields, str): fields = json.dumps(fields) params = { "fields": fields, @@ -310,7 +308,7 @@ class FrappeClient(object): def preprocess(self, params): """convert dicts, lists to json""" - for key, value in iteritems(params): + for key, value in params.items(): if isinstance(value, (dict, list)): params[key] = json.dumps(value) diff --git a/frappe/geo/country_info.py b/frappe/geo/country_info.py index 4f878325ad..ddebd1fb0e 100644 --- a/frappe/geo/country_info.py +++ b/frappe/geo/country_info.py @@ -2,8 +2,6 @@ # MIT License. See license.txt # all country info -from __future__ import unicode_literals - import os, json, frappe from frappe.utils.momentjs import get_all_timezones diff --git a/frappe/geo/doctype/country/__init__.py b/frappe/geo/doctype/country/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/geo/doctype/country/__init__.py +++ b/frappe/geo/doctype/country/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/geo/doctype/country/country.py b/frappe/geo/doctype/country/country.py index 5f8b6f7bd5..54935e6eaf 100644 --- a/frappe/geo/doctype/country/country.py +++ b/frappe/geo/doctype/country/country.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/geo/doctype/country/test_country.py b/frappe/geo/doctype/country/test_country.py index 81849d6886..e00d6ecf37 100644 --- a/frappe/geo/doctype/country/test_country.py +++ b/frappe/geo/doctype/country/test_country.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals import frappe test_records = frappe.get_test_records('Country') \ No newline at end of file diff --git a/frappe/geo/doctype/currency/__init__.py b/frappe/geo/doctype/currency/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/geo/doctype/currency/__init__.py +++ b/frappe/geo/doctype/currency/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/geo/doctype/currency/currency.py b/frappe/geo/doctype/currency/currency.py index 688303fd50..b3ce67cc67 100644 --- a/frappe/geo/doctype/currency/currency.py +++ b/frappe/geo/doctype/currency/currency.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: See license.txt -from __future__ import unicode_literals import frappe from frappe import throw, _ diff --git a/frappe/geo/doctype/currency/test_currency.py b/frappe/geo/doctype/currency/test_currency.py index 7945e193da..5552e675ec 100644 --- a/frappe/geo/doctype/currency/test_currency.py +++ b/frappe/geo/doctype/currency/test_currency.py @@ -3,6 +3,5 @@ # pre loaded -from __future__ import unicode_literals import frappe test_records = frappe.get_test_records('Currency') \ No newline at end of file diff --git a/frappe/geo/utils.py b/frappe/geo/utils.py index d94a13ea41..89de176f0b 100644 --- a/frappe/geo/utils.py +++ b/frappe/geo/utils.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import frappe from pymysql import InternalError diff --git a/frappe/handler.py b/frappe/handler.py index b622667e18..de86c15c8f 100755 --- a/frappe/handler.py +++ b/frappe/handler.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - from werkzeug.wrappers import Response import frappe diff --git a/frappe/hooks.py b/frappe/hooks.py index d0968ce051..ac42a03461 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from . import __version__ as app_version diff --git a/frappe/integrations/doctype/braintree_settings/braintree_settings.py b/frappe/integrations/doctype/braintree_settings/braintree_settings.py index 768f58c0a0..9dc9778bee 100644 --- a/frappe/integrations/doctype/braintree_settings/braintree_settings.py +++ b/frappe/integrations/doctype/braintree_settings/braintree_settings.py @@ -2,12 +2,11 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document import braintree from frappe import _ -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode from frappe.utils import get_url, call_hook_method from frappe.integrations.utils import create_request_log, create_payment_gateway diff --git a/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py b/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py index 80fa3c54b8..72a678a92c 100644 --- a/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py +++ b/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestBraintreeSettings(unittest.TestCase): diff --git a/frappe/integrations/doctype/connected_app/test_connected_app.py b/frappe/integrations/doctype/connected_app/test_connected_app.py index b4304f6ee8..d1ff19ecb2 100644 --- a/frappe/integrations/doctype/connected_app/test_connected_app.py +++ b/frappe/integrations/doctype/connected_app/test_connected_app.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # See license.txt -from __future__ import unicode_literals - import unittest import requests from urllib.parse import urljoin diff --git a/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py index 539fc417f2..d34e65de50 100644 --- a/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py index f06e13572c..96e8577c7c 100644 --- a/frappe/integrations/doctype/google_drive/test_google_drive.py +++ b/frappe/integrations/doctype/google_drive/test_google_drive.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/integrations/doctype/google_settings/google_settings.py b/frappe/integrations/doctype/google_settings/google_settings.py index ecc975235a..9a3f3c8ae2 100644 --- a/frappe/integrations/doctype/google_settings/google_settings.py +++ b/frappe/integrations/doctype/google_settings/google_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/integration_request/integration_request.py b/frappe/integrations/doctype/integration_request/integration_request.py index f1d59beb5a..4c4961d96d 100644 --- a/frappe/integrations/doctype/integration_request/integration_request.py +++ b/frappe/integrations/doctype/integration_request/integration_request.py @@ -2,11 +2,9 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document import json -from six import string_types from frappe.integrations.utils import json_handler class IntegrationRequest(Document): @@ -25,14 +23,14 @@ class IntegrationRequest(Document): def handle_success(self, response): """update the output field with the response along with the relevant status""" - if isinstance(response, string_types): + if isinstance(response, str): response = json.loads(response) self.db_set("status", "Completed") self.db_set("output", json.dumps(response, default=json_handler)) def handle_failure(self, response): """update the error field with the response along with the relevant status""" - if isinstance(response, string_types): + if isinstance(response, str): response = json.loads(response) self.db_set("status", "Failed") self.db_set("error", json.dumps(response, default=json_handler)) \ No newline at end of file diff --git a/frappe/integrations/doctype/integration_request/test_integration_request.py b/frappe/integrations/doctype/integration_request/test_integration_request.py index 6b77b57de4..a26eb4ba93 100644 --- a/frappe/integrations/doctype/integration_request/test_integration_request.py +++ b/frappe/integrations/doctype/integration_request/test_integration_request.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py b/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py index f9f2adeed0..b6bb77d964 100644 --- a/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py +++ b/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/ldap_settings/ldap_settings.py b/frappe/integrations/doctype/ldap_settings/ldap_settings.py index 80dfef2693..122096cf6f 100644 --- a/frappe/integrations/doctype/ldap_settings/ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/ldap_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _, safe_encode from frappe.model.document import Document diff --git a/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py b/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py index e6cf4eef3a..113692b6c4 100644 --- a/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py b/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py index f08e7eb5bb..0c7f02844c 100644 --- a/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py +++ b/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py b/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py index cecf187e61..6084dd64b4 100644 --- a/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py +++ b/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py b/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py index 09fd29075b..916d0205d2 100644 --- a/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py +++ b/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py b/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py index af7de360ab..6028cebcf9 100644 --- a/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py +++ b/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_client/oauth_client.py b/frappe/integrations/doctype/oauth_client/oauth_client.py index 02f5041dfb..0b449ff968 100644 --- a/frappe/integrations/doctype/oauth_client/oauth_client.py +++ b/frappe/integrations/doctype/oauth_client/oauth_client.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/integrations/doctype/oauth_client/test_oauth_client.py b/frappe/integrations/doctype/oauth_client/test_oauth_client.py index ee119455e5..a4e50e15d8 100644 --- a/frappe/integrations/doctype/oauth_client/test_oauth_client.py +++ b/frappe/integrations/doctype/oauth_client/test_oauth_client.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py b/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py index 2bf086e0fe..3ab5df92ac 100644 --- a/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py +++ b/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ diff --git a/frappe/integrations/doctype/oauth_scope/oauth_scope.py b/frappe/integrations/doctype/oauth_scope/oauth_scope.py index a5dfe7e1ce..ae579e6b51 100644 --- a/frappe/integrations/doctype/oauth_scope/oauth_scope.py +++ b/frappe/integrations/doctype/oauth_scope/oauth_scope.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/paypal_settings/paypal_settings.py b/frappe/integrations/doctype/paypal_settings/paypal_settings.py index efd1b03355..da045d2c6a 100644 --- a/frappe/integrations/doctype/paypal_settings/paypal_settings.py +++ b/frappe/integrations/doctype/paypal_settings/paypal_settings.py @@ -63,12 +63,11 @@ More Details: """ -from __future__ import unicode_literals import frappe import json import pytz from frappe import _ -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode from frappe.model.document import Document from frappe.integrations.utils import create_request_log, make_post_request, create_payment_gateway from frappe.utils import get_url, call_hook_method, cint, get_datetime diff --git a/frappe/integrations/doctype/paytm_settings/paytm_settings.py b/frappe/integrations/doctype/paytm_settings/paytm_settings.py index 616c3837d4..9f15d73f09 100644 --- a/frappe/integrations/doctype/paytm_settings/paytm_settings.py +++ b/frappe/integrations/doctype/paytm_settings/paytm_settings.py @@ -2,10 +2,9 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import json import requests -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode import frappe from frappe.model.document import Document @@ -59,7 +58,7 @@ def get_paytm_params(payment_details, order_id, paytm_config): # initialize a dictionary paytm_params = dict() - + redirect_uri = get_request_site_address(True) + "/api/method/frappe.integrations.doctype.paytm_settings.paytm_settings.verify_transaction" diff --git a/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py b/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py index 77a16c82ae..a00ce86327 100644 --- a/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py +++ b/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/integrations/doctype/query_parameters/query_parameters.py b/frappe/integrations/doctype/query_parameters/query_parameters.py index bfb8eae0b6..13fb94dbe3 100644 --- a/frappe/integrations/doctype/query_parameters/query_parameters.py +++ b/frappe/integrations/doctype/query_parameters/query_parameters.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py index af7686c9b0..d24e15f480 100644 --- a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +++ b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py @@ -60,14 +60,13 @@ For razorpay payment status is Authorized """ -from __future__ import unicode_literals import frappe from frappe import _ import json import hmac import razorpay import hashlib -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode from frappe.model.document import Document from frappe.utils import get_url, call_hook_method, cint, get_timestamp from frappe.integrations.utils import (make_get_request, make_post_request, create_request_log, diff --git a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py index 308d34c5c2..1346811652 100755 --- a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt - -from __future__ import print_function, unicode_literals import os import os.path import frappe diff --git a/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py index 04d90f9b44..3aecdf3489 100755 --- a/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestS3BackupSettings(unittest.TestCase): diff --git a/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py b/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py index 8756d19c88..a970fc1f11 100644 --- a/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py +++ b/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils import get_url_to_form diff --git a/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py b/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py index a7f9316ddd..4285c2c4bc 100644 --- a/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py +++ b/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestSlackWebhookURL(unittest.TestCase): diff --git a/frappe/integrations/doctype/social_login_key/social_login_key.py b/frappe/integrations/doctype/social_login_key/social_login_key.py index dffb730513..4a4fcd44f4 100644 --- a/frappe/integrations/doctype/social_login_key/social_login_key.py +++ b/frappe/integrations/doctype/social_login_key/social_login_key.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe, json from frappe import _ from frappe.model.document import Document diff --git a/frappe/integrations/doctype/social_login_key/test_social_login_key.py b/frappe/integrations/doctype/social_login_key/test_social_login_key.py index e0b99ad391..23effd6a44 100644 --- a/frappe/integrations/doctype/social_login_key/test_social_login_key.py +++ b/frappe/integrations/doctype/social_login_key/test_social_login_key.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe from frappe.integrations.doctype.social_login_key.social_login_key import BaseUrlNotSetError import unittest diff --git a/frappe/integrations/doctype/social_login_keys/social_login_keys.py b/frappe/integrations/doctype/social_login_keys/social_login_keys.py index bd4cea01af..da9e21cd8e 100644 --- a/frappe/integrations/doctype/social_login_keys/social_login_keys.py +++ b/frappe/integrations/doctype/social_login_keys/social_login_keys.py @@ -1,5 +1,4 @@ # see license -from __future__ import unicode_literals from frappe.model.document import Document class SocialLoginKeys(Document): diff --git a/frappe/integrations/doctype/stripe_settings/stripe_settings.py b/frappe/integrations/doctype/stripe_settings/stripe_settings.py index 70ca6002e4..9bb9c60775 100644 --- a/frappe/integrations/doctype/stripe_settings/stripe_settings.py +++ b/frappe/integrations/doctype/stripe_settings/stripe_settings.py @@ -2,11 +2,10 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe import _ -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode from frappe.utils import get_url, call_hook_method, cint, flt from frappe.integrations.utils import make_get_request, make_post_request, create_request_log, create_payment_gateway diff --git a/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py b/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py index 39e128192f..ba11c3c38b 100644 --- a/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py +++ b/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestStripeSettings(unittest.TestCase): diff --git a/frappe/integrations/doctype/token_cache/test_token_cache.py b/frappe/integrations/doctype/token_cache/test_token_cache.py index 7aa069647d..2ffd57403b 100644 --- a/frappe/integrations/doctype/token_cache/test_token_cache.py +++ b/frappe/integrations/doctype/token_cache/test_token_cache.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # See license.txt -from __future__ import unicode_literals - import unittest import frappe diff --git a/frappe/integrations/doctype/token_cache/token_cache.py b/frappe/integrations/doctype/token_cache/token_cache.py index 7cac58fae0..3001d12b2b 100644 --- a/frappe/integrations/doctype/token_cache/token_cache.py +++ b/frappe/integrations/doctype/token_cache/token_cache.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from datetime import datetime, timedelta import frappe diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 19233bd175..b92497f16c 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -2,8 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import frappe @@ -21,7 +19,7 @@ def run_webhooks(doc, method): if webhooks is None: # query webhooks webhooks_list = frappe.get_all('Webhook', - fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], + fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], filters={"enabled": True} ) diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index acf2f609e7..09ad56a190 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest import frappe @@ -86,7 +84,7 @@ class TestWebhook(unittest.TestCase): # Insert the user to db self.test_user.insert() - + self.assertTrue("User" in frappe.flags.webhooks) # only 1 hook (enabled) must be queued self.assertEqual( @@ -95,7 +93,7 @@ class TestWebhook(unittest.TestCase): ) self.assertTrue(self.test_user.email in frappe.flags.webhooks_executed) self.assertEqual( - frappe.flags.webhooks_executed.get(self.test_user.email)[0], + frappe.flags.webhooks_executed.get(self.test_user.email)[0], self.sample_webhooks[0].name ) diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index ad64d9f714..1fb2bc6743 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -2,8 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import base64 import datetime import hashlib @@ -12,7 +10,7 @@ import json from time import sleep import requests -from six.moves.urllib.parse import urlparse +from urllib.parse import urlparse import frappe from frappe import _ diff --git a/frappe/integrations/doctype/webhook_data/webhook_data.py b/frappe/integrations/doctype/webhook_data/webhook_data.py index b7d989410f..dbd9328482 100644 --- a/frappe/integrations/doctype/webhook_data/webhook_data.py +++ b/frappe/integrations/doctype/webhook_data/webhook_data.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/doctype/webhook_header/webhook_header.py b/frappe/integrations/doctype/webhook_header/webhook_header.py index 11d3ee4085..428b287db2 100644 --- a/frappe/integrations/doctype/webhook_header/webhook_header.py +++ b/frappe/integrations/doctype/webhook_header/webhook_header.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/integrations/oauth2_logins.py b/frappe/integrations/oauth2_logins.py index 14a6bcc417..c38b43beb7 100644 --- a/frappe/integrations/oauth2_logins.py +++ b/frappe/integrations/oauth2_logins.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import frappe.utils from frappe.utils.oauth import login_via_oauth2, login_via_oauth2_id_token @@ -33,7 +32,7 @@ def login_via_salesforce(code, state): @frappe.whitelist(allow_guest=True) def login_via_fairlogin(code, state): - login_via_oauth2("fairlogin", code, state, decoder=decoder_compat) + login_via_oauth2("fairlogin", code, state, decoder=decoder_compat) @frappe.whitelist(allow_guest=True) def custom(code, state): diff --git a/frappe/integrations/offsite_backup_utils.py b/frappe/integrations/offsite_backup_utils.py index 48a2c89107..7a263e9d04 100644 --- a/frappe/integrations/offsite_backup_utils.py +++ b/frappe/integrations/offsite_backup_utils.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import glob import os diff --git a/frappe/integrations/utils.py b/frappe/integrations/utils.py index 1af9682073..09c20568b5 100644 --- a/frappe/integrations/utils.py +++ b/frappe/integrations/utils.py @@ -2,11 +2,9 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import json,datetime -from six.moves.urllib.parse import parse_qs -from six import string_types, text_type +from urllib.parse import parse_qs from frappe.utils import get_request_session from frappe import _ @@ -50,10 +48,10 @@ def make_post_request(url, auth=None, headers=None, data=None): raise exc def create_request_log(data, integration_type, service_name, name=None, error=None): - if isinstance(data, string_types): + if isinstance(data, str): data = json.loads(data) - if isinstance(error, string_types): + if isinstance(error, str): error = json.loads(error) integration_request = frappe.get_doc({ @@ -116,4 +114,4 @@ def create_payment_gateway(gateway, settings=None, controller=None): def json_handler(obj): if isinstance(obj, (datetime.date, datetime.timedelta, datetime.datetime)): - return text_type(obj) + return str(obj) diff --git a/frappe/middlewares.py b/frappe/middlewares.py index 252be56c47..05944ec37a 100644 --- a/frappe/middlewares.py +++ b/frappe/middlewares.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import os from werkzeug.exceptions import NotFound diff --git a/frappe/migrate.py b/frappe/migrate.py index 619510fe5e..d19e255639 100644 --- a/frappe/migrate.py +++ b/frappe/migrate.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import json import os import sys diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index 205b451336..dd93fbcc18 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -2,7 +2,6 @@ # MIT License. See license.txt # model __init__.py -from __future__ import unicode_literals import frappe data_fieldtypes = ( diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 54d77ba988..2f5154cfd9 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -1,9 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals -from six import iteritems, string_types - import frappe import datetime from frappe import _ @@ -109,7 +105,7 @@ class BaseDocument(object): if key in d: self.set(key, d.get(key)) - for key, value in iteritems(d): + for key, value in d.items(): self.set(key, value) return self @@ -120,7 +116,7 @@ class BaseDocument(object): if "doctype" in d: self.set("doctype", d.get("doctype")) - for key, value in iteritems(d): + for key, value in d.items(): # dont_update_if_missing is a list of fieldnames, for which, you don't want to set default value if (self.get(key) is None) and (value is not None) and (key not in self.dont_update_if_missing): self.set(key, value) @@ -670,7 +666,7 @@ class BaseDocument(object): if data_field_options == "URL": if not data: continue - + frappe.utils.validate_url(data, throw=True) def _validate_constants(self): @@ -705,7 +701,7 @@ class BaseDocument(object): type_map = frappe.db.type_map - for fieldname, value in iteritems(self.get_valid_dict()): + for fieldname, value in self.get_valid_dict().items(): df = self.meta.get_field(fieldname) if not df or df.fieldtype == 'Check': @@ -770,7 +766,7 @@ class BaseDocument(object): return for fieldname, value in self.get_valid_dict().items(): - if not value or not isinstance(value, string_types): + if not value or not isinstance(value, str): continue value = frappe.as_unicode(value) @@ -839,7 +835,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, string_types): + if parentfield and not isinstance(parentfield, str): parentfield = parentfield.parentfield cache_key = parentfield or "main" @@ -986,7 +982,7 @@ def _filter(data, filters, limit=None): fval = ("not None", fval) elif fval is False: fval = ("None", fval) - elif isinstance(fval, string_types) and fval.startswith("^"): + elif isinstance(fval, str) and fval.startswith("^"): fval = ("^", fval[1:]) else: fval = ("=", fval) @@ -995,7 +991,7 @@ def _filter(data, filters, limit=None): for d in data: add = True - for f, fval in iteritems(_filters): + for f, fval in _filters.items(): if not frappe.compare(getattr(d, f, None), fval[0], fval[1]): add = False break diff --git a/frappe/model/create_new.py b/frappe/model/create_new.py index dc4fd97e4c..fba6765479 100644 --- a/frappe/model/create_new.py +++ b/frappe/model/create_new.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals """ Create a new document with defaults set """ diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index e0c3406c46..7f22282acf 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -1,10 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals - -from six import iteritems, string_types - """build query for doclistview and return results""" import frappe.defaults @@ -54,7 +49,7 @@ class DatabaseQuery(object): filters, fields = fields, filters elif fields and isinstance(filters, list) \ - and len(filters) > 1 and isinstance(filters[0], string_types): + and len(filters) > 1 and isinstance(filters[0], str): # if `filters` is a list of strings, its probably fields filters, fields = fields, filters @@ -209,7 +204,7 @@ class DatabaseQuery(object): def parse_args(self): """Convert fields and filters from strings to list, dicts""" - if isinstance(self.fields, string_types): + if isinstance(self.fields, str): if self.fields == "*": self.fields = ["*"] else: @@ -223,13 +218,13 @@ class DatabaseQuery(object): for filter_name in ["filters", "or_filters"]: filters = getattr(self, filter_name) - if isinstance(filters, string_types): + if isinstance(filters, str): filters = json.loads(filters) if isinstance(filters, dict): fdict = filters filters = [] - for key, value in iteritems(fdict): + for key, value in fdict.items(): filters.append(make_filter_tuple(self.doctype, key, value)) setattr(self, filter_name, filters) @@ -357,7 +352,7 @@ class DatabaseQuery(object): # remove from filters to_remove = [] for each in self.filters: - if isinstance(each, string_types): + if isinstance(each, str): each = [each] for element in each: @@ -391,7 +386,7 @@ class DatabaseQuery(object): filters = [filters] for f in filters: - if isinstance(f, string_types): + if isinstance(f, str): conditions.append(f) else: conditions.append(self.prepare_filter_condition(f)) @@ -522,12 +517,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, string_types) and + 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 fallback = "''" - if f.operator.lower() in ("like", "not like") and isinstance(value, string_types): + if f.operator.lower() in ("like", "not like") and isinstance(value, str): # because "like" uses backslash (\) for escaping value = value.replace("\\", "\\\\").replace("%", "%%") @@ -544,7 +539,7 @@ class DatabaseQuery(object): fallback = 0 # escape value - if isinstance(value, string_types) and not f.operator.lower() == 'between': + if isinstance(value, str) and not f.operator.lower() == 'between': value = "{0}".format(frappe.db.escape(value, percent=False)) if (self.ignore_ifnull diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 5fcc74a734..c01439d330 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -1,9 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import os -from six import string_types, integer_types import shutil import frappe @@ -35,7 +33,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, string_types) or isinstance(name, integer_types): + if isinstance(name, str) or isinstance(name, int): names = [name] for name in names or []: diff --git a/frappe/model/docfield.py b/frappe/model/docfield.py index 19b78e329d..6360c3866d 100644 --- a/frappe/model/docfield.py +++ b/frappe/model/docfield.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals """docfield utililtes""" import frappe diff --git a/frappe/model/document.py b/frappe/model/document.py index a3f8ad0cfa..8f57aae475 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -1,14 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function import frappe import time from frappe import _, msgprint, is_whitelisted from frappe.utils import flt, cstr, now, get_datetime_str, file_lock, date_diff from frappe.model.base_document import BaseDocument, get_controller from frappe.model.naming import set_new_name -from six import iteritems, string_types from werkzeug.exceptions import NotFound, Forbidden import hashlib, json from frappe.model import optional_fields, table_fields @@ -54,7 +51,7 @@ def get_doc(*args, **kwargs): if isinstance(args[0], BaseDocument): # already a document return args[0] - elif isinstance(args[0], string_types): + elif isinstance(args[0], str): doctype = args[0] elif isinstance(args[0], dict): @@ -91,7 +88,7 @@ class Document(BaseDocument): self._default_new_docs = {} self.flags = frappe._dict() - if args and args[0] and isinstance(args[0], string_types): + if args and args[0] and isinstance(args[0], str): # first arugment is doctype if len(args)==1: # single @@ -438,7 +435,7 @@ class Document(BaseDocument): def get_values(): values = self.as_dict() # format values - for key, value in iteritems(values): + for key, value in values.items(): if value==None: values[key] = "" return values @@ -455,7 +452,7 @@ class Document(BaseDocument): def update_single(self, d): """Updates values for Single type Document in `tabSingles`.""" frappe.db.sql("""delete from `tabSingles` where doctype=%s""", self.doctype) - for field, value in iteritems(d): + for field, value in d.items(): if field != "doctype": frappe.db.sql("""insert into `tabSingles` (doctype, field, value) values (%s, %s, %s)""", (self.doctype, field, value)) diff --git a/frappe/model/dynamic_links.py b/frappe/model/dynamic_links.py index 7404ba407e..676c86d7da 100644 --- a/frappe/model/dynamic_links.py +++ b/frappe/model/dynamic_links.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe # select doctypes that are accessed by the user (not read_only) first, so that the diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index d3014435e0..eb685fb840 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -1,12 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, json from frappe import _ from frappe.utils import cstr from frappe.model import default_fields, table_fields -from six import string_types @frappe.whitelist() def make_mapped_doc(method, source_name, selected_children=None, args=None): @@ -60,7 +58,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, string_types): + elif isinstance(target_doc, str): target_doc = frappe.get_doc(json.loads(target_doc)) if (not apply_strict_user_permissions diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 66e8b08d92..b67c41c990 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -14,10 +14,7 @@ Example: ''' - -from __future__ import unicode_literals, print_function from datetime import datetime -from six.moves import range import frappe, json, os from frappe.utils import cstr, cint, cast_fieldtype from frappe.model import default_fields, no_value_fields, optional_fields, data_fieldtypes, table_fields diff --git a/frappe/model/naming.py b/frappe/model/naming.py index b8d6a6f8d7..fe136adce8 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -1,12 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import now_datetime, cint, cstr import re -from six import string_types from frappe.model import log_types @@ -146,7 +144,7 @@ def make_autoname(key="", doctype="", doc=""): def parse_naming_series(parts, doctype='', doc=''): n = '' - if isinstance(parts, string_types): + if isinstance(parts, str): parts = parts.split('.') series_set = False today = now_datetime() @@ -177,7 +175,7 @@ def parse_naming_series(parts, doctype='', doc=''): else: part = e - if isinstance(part, string_types): + if isinstance(part, str): n += part return n @@ -203,7 +201,7 @@ def revert_series_if_last(key, name, doc=None): Reverts the series for particular naming series: * key is naming series - SINV-.YYYY-.#### * name is actual name - SINV-2021-0001 - + 1. This function split the key into two parts prefix (SINV-YYYY) & hashes (####). 2. Use prefix to get the current index of that naming series from Series table 3. Then revert the current index. @@ -213,7 +211,7 @@ def revert_series_if_last(key, name, doc=None): 2. If hash doesn't exit in hashes, we get the hash from prefix, then update name and prefix accordingly. *Example:* - 1. key = SINV-.YYYY.- + 1. key = SINV-.YYYY.- * If key doesn't have hash it will add hash at the end * prefix will be SINV-YYYY based on this will get current index from Series table. 2. key = SINV-.####.-2021 @@ -221,9 +219,9 @@ def revert_series_if_last(key, name, doc=None): * will search hash in key then accordingly get prefix = SINV- 3. key = ####.-2021 * prefix = #### and hashes = 2021 (hash doesn't exist) - * will search hash in key then accordingly get prefix = "" + * will search hash in key then accordingly get prefix = "" """ - if ".#" in key: + if ".#" in key: prefix, hashes = key.rsplit(".", 1) if "#" not in hashes: # get the hash part from the key diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 2c9dc5d823..fc5b3ca9fe 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import print_function, unicode_literals - import frappe from frappe import _, bold from frappe.model.dynamic_links import get_dynamic_link_map diff --git a/frappe/model/sync.py b/frappe/model/sync.py index 61983d322c..28f9deb25d 100644 --- a/frappe/model/sync.py +++ b/frappe/model/sync.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function """ Sync's doctype and docfields from txt files to database perms will get synced only if none exist diff --git a/frappe/model/utils/__init__.py b/frappe/model/utils/__init__.py index efbe46a4ab..47615182e4 100644 --- a/frappe/model/utils/__init__.py +++ b/frappe/model/utils/__init__.py @@ -1,15 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function -from six.moves import range import frappe from frappe import _ from frappe.utils import cstr from frappe.build import html_to_js_template import re -from six import text_type - import io STANDARD_FIELD_CONVERSION_MAP = { diff --git a/frappe/model/utils/link_count.py b/frappe/model/utils/link_count.py index 5faa5ba44b..7562aaae45 100644 --- a/frappe/model/utils/link_count.py +++ b/frappe/model/utils/link_count.py @@ -1,10 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe -from six import iteritems ignore_doctypes = ("DocType", "Print Format", "Role", "Module Def", "Communication", "ToDo") @@ -39,7 +36,7 @@ def update_link_count(): link_count = frappe.cache().get_value('_link_count') if link_count: - for key, count in iteritems(link_count): + for key, count in link_count.items(): if key[0] not in ignore_doctypes: try: frappe.db.sql('update `tab{0}` set idx = idx + {1} where name=%s'.format(key[0], count), diff --git a/frappe/model/utils/rename_field.py b/frappe/model/utils/rename_field.py index 778f623092..9fe9d64041 100644 --- a/frappe/model/utils/rename_field.py +++ b/frappe/model/utils/rename_field.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe import json from frappe.model import no_value_fields, table_fields diff --git a/frappe/model/utils/user_settings.py b/frappe/model/utils/user_settings.py index d59bda71a5..ad378ab93f 100644 --- a/frappe/model/utils/user_settings.py +++ b/frappe/model/utils/user_settings.py @@ -1,9 +1,8 @@ -from __future__ import unicode_literals + # Settings saved per user basis # such as page_limit, filters, last_view import frappe, json -from six import iteritems, string_types from frappe import safe_decode # dict for mapping the index and index type for the filters of different views @@ -36,7 +35,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, string_types): + if isinstance(current, str): # corrupt due to old code, remove this in a future release current = {} @@ -47,7 +46,7 @@ def update_user_settings(doctype, user_settings, for_update=False): def sync_user_settings(): '''Sync from cache to database (called asynchronously via the browser)''' - for key, data in iteritems(frappe.cache().hgetall('_user_settings')): + for key, data in frappe.cache().hgetall('_user_settings').items(): key = safe_decode(key) doctype, user = key.split('::') # WTF? frappe.db.multisql({ diff --git a/frappe/model/workflow.py b/frappe/model/workflow.py index 3e8125f9b1..fa2f557370 100644 --- a/frappe/model/workflow.py +++ b/frappe/model/workflow.py @@ -1,11 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import cint from frappe import _ -from six import string_types import json class WorkflowStateError(frappe.ValidationError): pass @@ -268,7 +266,7 @@ def print_workflow_log(messages, title, doctype, indicator): @frappe.whitelist() def get_common_transition_actions(docs, doctype): common_actions = [] - if isinstance(docs, string_types): + if isinstance(docs, str): docs = json.loads(docs) try: for (i, doc) in enumerate(docs, 1): diff --git a/frappe/modules/__init__.py b/frappe/modules/__init__.py index fef4829bb6..33411f8d74 100644 --- a/frappe/modules/__init__.py +++ b/frappe/modules/__init__.py @@ -1,2 +1,2 @@ -from __future__ import unicode_literals + from .utils import * \ No newline at end of file diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index 4b22c82105..ae9f11d53b 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, os import frappe.model from frappe.modules import scrub, get_module_path, scrub_dt_dn diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index fdfd00404c..e743f0c3da 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe, os, json from frappe.modules import get_module_path, scrub_dt_dn from frappe.utils import get_datetime_str diff --git a/frappe/modules/patch_handler.py b/frappe/modules/patch_handler.py index 0ed10d1e0d..029234d5d9 100644 --- a/frappe/modules/patch_handler.py +++ b/frappe/modules/patch_handler.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function """ Execute Patch Files @@ -14,9 +12,6 @@ from __future__ import unicode_literals, print_function """ import frappe, frappe.permissions, time -# for patches -import os - class PatchError(Exception): pass def run_all(skip_failing=False): diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py index 132aa1e2a5..0f3e57a5a0 100644 --- a/frappe/modules/utils.py +++ b/frappe/modules/utils.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function """ Utilities for using modules """ diff --git a/frappe/monitor.py b/frappe/monitor.py index 6802a59584..34ca7d67f7 100644 --- a/frappe/monitor.py +++ b/frappe/monitor.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - from datetime import datetime import json import traceback diff --git a/frappe/patches/v10_0/enable_chat_by_default_within_system_settings.py b/frappe/patches/v10_0/enable_chat_by_default_within_system_settings.py index eddca78051..24f915c512 100644 --- a/frappe/patches/v10_0/enable_chat_by_default_within_system_settings.py +++ b/frappe/patches/v10_0/enable_chat_by_default_within_system_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v10_0/enhance_security.py b/frappe/patches/v10_0/enhance_security.py index 865d18dcff..4f6ca4faa1 100644 --- a/frappe/patches/v10_0/enhance_security.py +++ b/frappe/patches/v10_0/enhance_security.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe from frappe.utils import cint diff --git a/frappe/patches/v10_0/increase_single_table_column_length.py b/frappe/patches/v10_0/increase_single_table_column_length.py index 18de0cff9e..e578d192fc 100644 --- a/frappe/patches/v10_0/increase_single_table_column_length.py +++ b/frappe/patches/v10_0/increase_single_table_column_length.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + """ Run this after updating country_info.json and or """ diff --git a/frappe/patches/v10_0/migrate_passwords_passlib.py b/frappe/patches/v10_0/migrate_passwords_passlib.py index 22b7a86f85..d0b36efbaa 100644 --- a/frappe/patches/v10_0/migrate_passwords_passlib.py +++ b/frappe/patches/v10_0/migrate_passwords_passlib.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.password import LegacyPassword diff --git a/frappe/patches/v10_0/modify_naming_series_table.py b/frappe/patches/v10_0/modify_naming_series_table.py index 659e247a38..ca6114eb55 100644 --- a/frappe/patches/v10_0/modify_naming_series_table.py +++ b/frappe/patches/v10_0/modify_naming_series_table.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - ''' Modify the Integer 10 Digits Value to BigInt 20 Digit value to generate long Naming Series diff --git a/frappe/patches/v10_0/modify_smallest_currency_fraction.py b/frappe/patches/v10_0/modify_smallest_currency_fraction.py index f875d6b87d..c9ae477359 100644 --- a/frappe/patches/v10_0/modify_smallest_currency_fraction.py +++ b/frappe/patches/v10_0/modify_smallest_currency_fraction.py @@ -1,7 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v10_0/refactor_social_login_keys.py b/frappe/patches/v10_0/refactor_social_login_keys.py index 07737912df..a3f08939ec 100644 --- a/frappe/patches/v10_0/refactor_social_login_keys.py +++ b/frappe/patches/v10_0/refactor_social_login_keys.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe from frappe.utils import cstr diff --git a/frappe/patches/v10_0/reload_countries_and_currencies.py b/frappe/patches/v10_0/reload_countries_and_currencies.py index f83ed9c3aa..8d019a4855 100644 --- a/frappe/patches/v10_0/reload_countries_and_currencies.py +++ b/frappe/patches/v10_0/reload_countries_and_currencies.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + """ Run this after updating country_info.json and or """ diff --git a/frappe/patches/v10_0/remove_custom_field_for_disabled_domain.py b/frappe/patches/v10_0/remove_custom_field_for_disabled_domain.py index f27639388e..54839cfe02 100644 --- a/frappe/patches/v10_0/remove_custom_field_for_disabled_domain.py +++ b/frappe/patches/v10_0/remove_custom_field_for_disabled_domain.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v10_0/set_default_locking_time.py b/frappe/patches/v10_0/set_default_locking_time.py index 1c9797a6cc..045fa0e3fa 100644 --- a/frappe/patches/v10_0/set_default_locking_time.py +++ b/frappe/patches/v10_0/set_default_locking_time.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v10_0/set_no_copy_to_workflow_state.py b/frappe/patches/v10_0/set_no_copy_to_workflow_state.py index 800d4a4d1b..eb469b8452 100644 --- a/frappe/patches/v10_0/set_no_copy_to_workflow_state.py +++ b/frappe/patches/v10_0/set_no_copy_to_workflow_state.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/change_email_signature_fieldtype.py b/frappe/patches/v11_0/change_email_signature_fieldtype.py index f6d4bd5dcb..ccfa8541c3 100644 --- a/frappe/patches/v11_0/change_email_signature_fieldtype.py +++ b/frappe/patches/v11_0/change_email_signature_fieldtype.py @@ -1,7 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v11_0/copy_fetch_data_from_options.py b/frappe/patches/v11_0/copy_fetch_data_from_options.py index ae7788450a..e256c7085f 100644 --- a/frappe/patches/v11_0/copy_fetch_data_from_options.py +++ b/frappe/patches/v11_0/copy_fetch_data_from_options.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/create_contact_for_user.py b/frappe/patches/v11_0/create_contact_for_user.py index b4722ab3ae..21e681a83e 100644 --- a/frappe/patches/v11_0/create_contact_for_user.py +++ b/frappe/patches/v11_0/create_contact_for_user.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.core.doctype.user.user import create_contact import re diff --git a/frappe/patches/v11_0/delete_all_prepared_reports.py b/frappe/patches/v11_0/delete_all_prepared_reports.py index 1d722da7e6..77f041e3ee 100644 --- a/frappe/patches/v11_0/delete_all_prepared_reports.py +++ b/frappe/patches/v11_0/delete_all_prepared_reports.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/delete_duplicate_user_permissions.py b/frappe/patches/v11_0/delete_duplicate_user_permissions.py index 9d9d516ac5..518c1f7714 100644 --- a/frappe/patches/v11_0/delete_duplicate_user_permissions.py +++ b/frappe/patches/v11_0/delete_duplicate_user_permissions.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/drop_column_apply_user_permissions.py b/frappe/patches/v11_0/drop_column_apply_user_permissions.py index 4f46bc0907..629d5a5da4 100644 --- a/frappe/patches/v11_0/drop_column_apply_user_permissions.py +++ b/frappe/patches/v11_0/drop_column_apply_user_permissions.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/fix_order_by_in_reports_json.py b/frappe/patches/v11_0/fix_order_by_in_reports_json.py index 2cd82d442d..096e0e7654 100644 --- a/frappe/patches/v11_0/fix_order_by_in_reports_json.py +++ b/frappe/patches/v11_0/fix_order_by_in_reports_json.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json def execute(): diff --git a/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py b/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py index f7b9e476a9..a099b89b40 100644 --- a/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py +++ b/frappe/patches/v11_0/make_all_prepared_report_attachments_private.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe diff --git a/frappe/patches/v11_0/migrate_report_settings_for_new_listview.py b/frappe/patches/v11_0/migrate_report_settings_for_new_listview.py index 5bef52c295..e5b18368db 100644 --- a/frappe/patches/v11_0/migrate_report_settings_for_new_listview.py +++ b/frappe/patches/v11_0/migrate_report_settings_for_new_listview.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json def execute(): diff --git a/frappe/patches/v11_0/multiple_references_in_events.py b/frappe/patches/v11_0/multiple_references_in_events.py index 57d4787eca..9fa5968d8e 100644 --- a/frappe/patches/v11_0/multiple_references_in_events.py +++ b/frappe/patches/v11_0/multiple_references_in_events.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/reload_and_rename_view_log.py b/frappe/patches/v11_0/reload_and_rename_view_log.py index 12c71b746f..fa0432c4e2 100644 --- a/frappe/patches/v11_0/reload_and_rename_view_log.py +++ b/frappe/patches/v11_0/reload_and_rename_view_log.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py b/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py index e2c2ef5f0e..5c54b1e5c1 100644 --- a/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py +++ b/frappe/patches/v11_0/remove_doctype_user_permissions_for_page_and_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v11_0/remove_skip_for_doctype.py b/frappe/patches/v11_0/remove_skip_for_doctype.py index edd385e317..638a5a0fd7 100644 --- a/frappe/patches/v11_0/remove_skip_for_doctype.py +++ b/frappe/patches/v11_0/remove_skip_for_doctype.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.desk.form.linked_with import get_linked_doctypes from frappe.patches.v11_0.replicate_old_user_permissions import get_doctypes_to_skip diff --git a/frappe/patches/v11_0/rename_email_alert_to_notification.py b/frappe/patches/v11_0/rename_email_alert_to_notification.py index 727055fcc4..365b76ea48 100644 --- a/frappe/patches/v11_0/rename_email_alert_to_notification.py +++ b/frappe/patches/v11_0/rename_email_alert_to_notification.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.rename_doc import rename_doc diff --git a/frappe/patches/v11_0/rename_google_maps_doctype.py b/frappe/patches/v11_0/rename_google_maps_doctype.py index 5420dcfc20..4e8aee6280 100644 --- a/frappe/patches/v11_0/rename_google_maps_doctype.py +++ b/frappe/patches/v11_0/rename_google_maps_doctype.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.rename_doc import rename_doc diff --git a/frappe/patches/v11_0/rename_standard_reply_to_email_template.py b/frappe/patches/v11_0/rename_standard_reply_to_email_template.py index 06869530e2..2906085738 100644 --- a/frappe/patches/v11_0/rename_standard_reply_to_email_template.py +++ b/frappe/patches/v11_0/rename_standard_reply_to_email_template.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.rename_doc import rename_doc diff --git a/frappe/patches/v11_0/rename_workflow_action_to_workflow_action_master.py b/frappe/patches/v11_0/rename_workflow_action_to_workflow_action_master.py index 32f17ac2d8..9a48104611 100644 --- a/frappe/patches/v11_0/rename_workflow_action_to_workflow_action_master.py +++ b/frappe/patches/v11_0/rename_workflow_action_to_workflow_action_master.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.rename_doc import rename_doc diff --git a/frappe/patches/v11_0/replicate_old_user_permissions.py b/frappe/patches/v11_0/replicate_old_user_permissions.py index d1ceae8a7f..50a81b5ce7 100644 --- a/frappe/patches/v11_0/replicate_old_user_permissions.py +++ b/frappe/patches/v11_0/replicate_old_user_permissions.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe import json from frappe.utils import cint diff --git a/frappe/patches/v11_0/set_allow_self_approval_in_workflow.py b/frappe/patches/v11_0/set_allow_self_approval_in_workflow.py index 24c01e1a58..63ae5f949f 100644 --- a/frappe/patches/v11_0/set_allow_self_approval_in_workflow.py +++ b/frappe/patches/v11_0/set_allow_self_approval_in_workflow.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/set_default_letter_head_source.py b/frappe/patches/v11_0/set_default_letter_head_source.py index a43ea397e4..3639524e7d 100644 --- a/frappe/patches/v11_0/set_default_letter_head_source.py +++ b/frappe/patches/v11_0/set_default_letter_head_source.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe def execute(): diff --git a/frappe/patches/v11_0/set_dropbox_file_backup.py b/frappe/patches/v11_0/set_dropbox_file_backup.py index 884fef320e..27492b3ab2 100644 --- a/frappe/patches/v11_0/set_dropbox_file_backup.py +++ b/frappe/patches/v11_0/set_dropbox_file_backup.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from frappe.utils import cint import frappe diff --git a/frappe/patches/v11_0/sync_stripe_settings_before_migrate.py b/frappe/patches/v11_0/sync_stripe_settings_before_migrate.py index 331b0eba32..a8e9bd4de1 100644 --- a/frappe/patches/v11_0/sync_stripe_settings_before_migrate.py +++ b/frappe/patches/v11_0/sync_stripe_settings_before_migrate.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.password import get_decrypted_password diff --git a/frappe/patches/v11_0/sync_user_permission_doctype_before_migrate.py b/frappe/patches/v11_0/sync_user_permission_doctype_before_migrate.py index 738fea1a48..55a7b74f7e 100644 --- a/frappe/patches/v11_0/sync_user_permission_doctype_before_migrate.py +++ b/frappe/patches/v11_0/sync_user_permission_doctype_before_migrate.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v11_0/update_list_user_settings.py b/frappe/patches/v11_0/update_list_user_settings.py index d492ff1704..1b179d8cdf 100644 --- a/frappe/patches/v11_0/update_list_user_settings.py +++ b/frappe/patches/v11_0/update_list_user_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json from frappe.model.utils.user_settings import update_user_settings, sync_user_settings diff --git a/frappe/patches/v12_0/create_notification_settings_for_user.py b/frappe/patches/v12_0/create_notification_settings_for_user.py index 63eeccc07a..6edfd88872 100644 --- a/frappe/patches/v12_0/create_notification_settings_for_user.py +++ b/frappe/patches/v12_0/create_notification_settings_for_user.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.desk.doctype.notification_settings.notification_settings import create_notification_settings diff --git a/frappe/patches/v12_0/init_desk_settings.py b/frappe/patches/v12_0/init_desk_settings.py index ecd9c94d5b..fceb44b924 100644 --- a/frappe/patches/v12_0/init_desk_settings.py +++ b/frappe/patches/v12_0/init_desk_settings.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import json import frappe from frappe.config import get_modules_from_all_apps_for_user diff --git a/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py b/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py index 040fde1bee..85be3f7feb 100644 --- a/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py +++ b/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe def execute(): diff --git a/frappe/patches/v12_0/setup_comments_from_communications.py b/frappe/patches/v12_0/setup_comments_from_communications.py index 28c7aa93c0..039ceeff35 100644 --- a/frappe/patches/v12_0/setup_comments_from_communications.py +++ b/frappe/patches/v12_0/setup_comments_from_communications.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe def execute(): diff --git a/frappe/patches/v12_0/setup_email_linking.py b/frappe/patches/v12_0/setup_email_linking.py index 08f57ca5e4..9e939e1245 100644 --- a/frappe/patches/v12_0/setup_email_linking.py +++ b/frappe/patches/v12_0/setup_email_linking.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from frappe.desk.page.setup_wizard.install_fixtures import setup_email_linking def execute(): diff --git a/frappe/patches/v12_0/update_auto_repeat_status_and_not_submittable.py b/frappe/patches/v12_0/update_auto_repeat_status_and_not_submittable.py index d696b6c53a..3a3dcec315 100644 --- a/frappe/patches/v12_0/update_auto_repeat_status_and_not_submittable.py +++ b/frappe/patches/v12_0/update_auto_repeat_status_and_not_submittable.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field diff --git a/frappe/patches/v13_0/add_standard_navbar_items.py b/frappe/patches/v13_0/add_standard_navbar_items.py index 9982e6e3f5..4473cb8c07 100644 --- a/frappe/patches/v13_0/add_standard_navbar_items.py +++ b/frappe/patches/v13_0/add_standard_navbar_items.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.install import add_standard_navbar_items diff --git a/frappe/patches/v13_0/add_switch_theme_to_navbar_settings.py b/frappe/patches/v13_0/add_switch_theme_to_navbar_settings.py index 29b99464b5..b5542c9c8a 100644 --- a/frappe/patches/v13_0/add_switch_theme_to_navbar_settings.py +++ b/frappe/patches/v13_0/add_switch_theme_to_navbar_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v13_0/add_toggle_width_in_navbar_settings.py b/frappe/patches/v13_0/add_toggle_width_in_navbar_settings.py index 59acb77480..bd3367377c 100644 --- a/frappe/patches/v13_0/add_toggle_width_in_navbar_settings.py +++ b/frappe/patches/v13_0/add_toggle_width_in_navbar_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v13_0/cleanup_desk_cards.py b/frappe/patches/v13_0/cleanup_desk_cards.py index 6ac8604041..b6fab66475 100644 --- a/frappe/patches/v13_0/cleanup_desk_cards.py +++ b/frappe/patches/v13_0/cleanup_desk_cards.py @@ -1,11 +1,10 @@ import frappe -from six import string_types from json import loads from frappe.desk.doctype.workspace.workspace import get_link_type, get_report_type def execute(): frappe.reload_doc('desk', 'doctype', 'workspace') - + pages = frappe.db.sql("Select `name` from `tabDesk Page`") # pages = frappe.get_all("Workspace", filters={"is_standard": 0}, pluck="name") @@ -21,14 +20,14 @@ def rebuild_links(page): doc = frappe.get_doc("Workspace", page) except frappe.DoesNotExistError: db_doc = get_doc_from_db(page) - + doc = frappe.get_doc(db_doc) doc.insert(ignore_permissions=True) - + doc.links = [] for card in get_all_cards(page): - if isinstance(card.links, string_types): + if isinstance(card.links, str): links = loads(card.links) else: links = card.links @@ -43,7 +42,7 @@ def rebuild_links(page): for link in links: if not frappe.db.exists(get_link_type(link.get('type')), link.get('name')): continue - + doc.append('links', { "label": link.get('label') or link.get('name'), "type": "Link", @@ -53,7 +52,7 @@ def rebuild_links(page): "dependencies": ', '.join(link.get('dependencies', [])), "is_query_report": get_report_type(link.get('name')) if link.get('type').lower() == "report" else 0 }) - + try: doc.save(ignore_permissions=True) except frappe.LinkValidationError: diff --git a/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py b/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py index 1eba5871c2..776e9c796e 100644 --- a/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py +++ b/frappe/patches/v13_0/delete_event_producer_and_consumer_keys.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v13_0/delete_package_publish_tool.py b/frappe/patches/v13_0/delete_package_publish_tool.py index 25024f58dd..bf9aaf5a76 100644 --- a/frappe/patches/v13_0/delete_package_publish_tool.py +++ b/frappe/patches/v13_0/delete_package_publish_tool.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/patches/v13_0/enable_custom_script.py b/frappe/patches/v13_0/enable_custom_script.py index edc242e700..0684074fe7 100644 --- a/frappe/patches/v13_0/enable_custom_script.py +++ b/frappe/patches/v13_0/enable_custom_script.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v13_0/generate_theme_files_in_public_folder.py b/frappe/patches/v13_0/generate_theme_files_in_public_folder.py index bcb47bec24..dd9fb1961a 100644 --- a/frappe/patches/v13_0/generate_theme_files_in_public_folder.py +++ b/frappe/patches/v13_0/generate_theme_files_in_public_folder.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/patches/v13_0/jinja_hook.py b/frappe/patches/v13_0/jinja_hook.py index 84ed6e6cff..990ae50f35 100644 --- a/frappe/patches/v13_0/jinja_hook.py +++ b/frappe/patches/v13_0/jinja_hook.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from click import secho diff --git a/frappe/patches/v13_0/queryreport_columns.py b/frappe/patches/v13_0/queryreport_columns.py index 6c2a1b1219..5c381f4f3e 100644 --- a/frappe/patches/v13_0/queryreport_columns.py +++ b/frappe/patches/v13_0/queryreport_columns.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import json diff --git a/frappe/patches/v13_0/remove_duplicate_navbar_items.py b/frappe/patches/v13_0/remove_duplicate_navbar_items.py index cb4de4ca07..b6c6033f64 100644 --- a/frappe/patches/v13_0/remove_duplicate_navbar_items.py +++ b/frappe/patches/v13_0/remove_duplicate_navbar_items.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v13_0/remove_tailwind_from_page_builder.py b/frappe/patches/v13_0/remove_tailwind_from_page_builder.py index 6e7bf67bac..2bf2c7bf87 100644 --- a/frappe/patches/v13_0/remove_tailwind_from_page_builder.py +++ b/frappe/patches/v13_0/remove_tailwind_from_page_builder.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py index 7c3aec9510..3122de8bea 100644 --- a/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py +++ b/frappe/patches/v13_0/rename_list_view_setting_to_list_view_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/patches/v13_0/rename_notification_fields.py b/frappe/patches/v13_0/rename_notification_fields.py index 2984e6503c..1413d80358 100644 --- a/frappe/patches/v13_0/rename_notification_fields.py +++ b/frappe/patches/v13_0/rename_notification_fields.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field diff --git a/frappe/patches/v13_0/rename_onboarding.py b/frappe/patches/v13_0/rename_onboarding.py index c506c6076e..852065dfd2 100644 --- a/frappe/patches/v13_0/rename_onboarding.py +++ b/frappe/patches/v13_0/rename_onboarding.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v13_0/replace_old_data_import.py b/frappe/patches/v13_0/replace_old_data_import.py index 920ee7b553..838881b48e 100644 --- a/frappe/patches/v13_0/replace_old_data_import.py +++ b/frappe/patches/v13_0/replace_old_data_import.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/patches/v13_0/update_date_filters_in_user_settings.py b/frappe/patches/v13_0/update_date_filters_in_user_settings.py index d4c6aa1d03..3b1b07fe0a 100644 --- a/frappe/patches/v13_0/update_date_filters_in_user_settings.py +++ b/frappe/patches/v13_0/update_date_filters_in_user_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json from frappe.model.utils.user_settings import update_user_settings, sync_user_settings diff --git a/frappe/patches/v13_0/update_duration_options.py b/frappe/patches/v13_0/update_duration_options.py index 60eef8fc93..e0d8dea4ea 100644 --- a/frappe/patches/v13_0/update_duration_options.py +++ b/frappe/patches/v13_0/update_duration_options.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v13_0/update_icons_in_customized_desk_pages.py b/frappe/patches/v13_0/update_icons_in_customized_desk_pages.py index 93bf5c766e..ff58f99c2f 100644 --- a/frappe/patches/v13_0/update_icons_in_customized_desk_pages.py +++ b/frappe/patches/v13_0/update_icons_in_customized_desk_pages.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v13_0/update_newsletter_content_type.py b/frappe/patches/v13_0/update_newsletter_content_type.py index 6f8dcc1935..5f047680ee 100644 --- a/frappe/patches/v13_0/update_newsletter_content_type.py +++ b/frappe/patches/v13_0/update_newsletter_content_type.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v13_0/update_notification_channel_if_empty.py b/frappe/patches/v13_0/update_notification_channel_if_empty.py index 2c2a40e81b..bcf9a7b28c 100644 --- a/frappe/patches/v13_0/update_notification_channel_if_empty.py +++ b/frappe/patches/v13_0/update_notification_channel_if_empty.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v13_0/web_template_set_module.py b/frappe/patches/v13_0/web_template_set_module.py index df008557d8..2ee9e3ba2d 100644 --- a/frappe/patches/v13_0/web_template_set_module.py +++ b/frappe/patches/v13_0/web_template_set_module.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/add_delete_permission.py b/frappe/patches/v4_0/add_delete_permission.py index 091bdab3ff..9e375a431d 100644 --- a/frappe/patches/v4_0/add_delete_permission.py +++ b/frappe/patches/v4_0/add_delete_permission.py @@ -1,13 +1,13 @@ -from __future__ import unicode_literals + import frappe def execute(): frappe.reload_doc("core", "doctype", "docperm") - + # delete same as cancel (map old permissions) frappe.db.sql("""update tabDocPerm set `delete`=ifnull(`cancel`,0)""") - + # can't cancel if can't submit frappe.db.sql("""update tabDocPerm set `cancel`=0 where ifnull(`submit`,0)=0""") - + frappe.clear_cache() \ No newline at end of file diff --git a/frappe/patches/v4_0/change_varchar_length.py b/frappe/patches/v4_0/change_varchar_length.py index 29fe8f310d..914034ccba 100644 --- a/frappe/patches/v4_0/change_varchar_length.py +++ b/frappe/patches/v4_0/change_varchar_length.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/create_custom_field_for_owner_match.py b/frappe/patches/v4_0/create_custom_field_for_owner_match.py index 60dafc27da..438e280669 100644 --- a/frappe/patches/v4_0/create_custom_field_for_owner_match.py +++ b/frappe/patches/v4_0/create_custom_field_for_owner_match.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_field diff --git a/frappe/patches/v4_0/deprecate_control_panel.py b/frappe/patches/v4_0/deprecate_control_panel.py index 892d3043c4..29ec8d35f6 100644 --- a/frappe/patches/v4_0/deprecate_control_panel.py +++ b/frappe/patches/v4_0/deprecate_control_panel.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/deprecate_link_selects.py b/frappe/patches/v4_0/deprecate_link_selects.py index a3243cffb8..837144a6ba 100644 --- a/frappe/patches/v4_0/deprecate_link_selects.py +++ b/frappe/patches/v4_0/deprecate_link_selects.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/enable_scheduler_in_system_settings.py b/frappe/patches/v4_0/enable_scheduler_in_system_settings.py index 5d1b836270..68c74edb4f 100644 --- a/frappe/patches/v4_0/enable_scheduler_in_system_settings.py +++ b/frappe/patches/v4_0/enable_scheduler_in_system_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils.scheduler import disable_scheduler, enable_scheduler from frappe.utils import cint diff --git a/frappe/patches/v4_0/file_manager_hooks.py b/frappe/patches/v4_0/file_manager_hooks.py index 6be3b25124..ccf95d1d31 100644 --- a/frappe/patches/v4_0/file_manager_hooks.py +++ b/frappe/patches/v4_0/file_manager_hooks.py @@ -1,11 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe import os -from frappe.utils import get_files_path from frappe.core.doctype.file.file import get_content_hash diff --git a/frappe/patches/v4_0/fix_attach_field_file_url.py b/frappe/patches/v4_0/fix_attach_field_file_url.py index c29e5763f1..61c35b120d 100644 --- a/frappe/patches/v4_0/fix_attach_field_file_url.py +++ b/frappe/patches/v4_0/fix_attach_field_file_url.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/private_backups.py b/frappe/patches/v4_0/private_backups.py index 016af0615d..7920564677 100644 --- a/frappe/patches/v4_0/private_backups.py +++ b/frappe/patches/v4_0/private_backups.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.installer import make_site_dirs diff --git a/frappe/patches/v4_0/remove_index_sitemap.py b/frappe/patches/v4_0/remove_index_sitemap.py index 5dcd0d79c7..8f48729276 100644 --- a/frappe/patches/v4_0/remove_index_sitemap.py +++ b/frappe/patches/v4_0/remove_index_sitemap.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v4_0/remove_old_parent.py b/frappe/patches/v4_0/remove_old_parent.py index 7717f7b7e3..f2d125953a 100644 --- a/frappe/patches/v4_0/remove_old_parent.py +++ b/frappe/patches/v4_0/remove_old_parent.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/remove_user_owner_custom_field.py b/frappe/patches/v4_0/remove_user_owner_custom_field.py index be6a45e090..4620f055d9 100644 --- a/frappe/patches/v4_0/remove_user_owner_custom_field.py +++ b/frappe/patches/v4_0/remove_user_owner_custom_field.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/rename_profile_to_user.py b/frappe/patches/v4_0/rename_profile_to_user.py index 48555ead9e..3e6f269329 100644 --- a/frappe/patches/v4_0/rename_profile_to_user.py +++ b/frappe/patches/v4_0/rename_profile_to_user.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field diff --git a/frappe/patches/v4_0/rename_sitemap_to_route.py b/frappe/patches/v4_0/rename_sitemap_to_route.py index 8ae5170b44..b4606672bc 100644 --- a/frappe/patches/v4_0/rename_sitemap_to_route.py +++ b/frappe/patches/v4_0/rename_sitemap_to_route.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.utils.rename_field import rename_field diff --git a/frappe/patches/v4_0/replace_deprecated_timezones.py b/frappe/patches/v4_0/replace_deprecated_timezones.py index a491325ebc..a3d8ecbf2b 100644 --- a/frappe/patches/v4_0/replace_deprecated_timezones.py +++ b/frappe/patches/v4_0/replace_deprecated_timezones.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils.momentjs import data as momentjs_data diff --git a/frappe/patches/v4_0/set_module_in_report.py b/frappe/patches/v4_0/set_module_in_report.py index 9760f7efb3..6c670f4c8e 100644 --- a/frappe/patches/v4_0/set_module_in_report.py +++ b/frappe/patches/v4_0/set_module_in_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/set_todo_checked_as_closed.py b/frappe/patches/v4_0/set_todo_checked_as_closed.py index 59e8df3793..5f02e1447b 100644 --- a/frappe/patches/v4_0/set_todo_checked_as_closed.py +++ b/frappe/patches/v4_0/set_todo_checked_as_closed.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v4_0/set_user_gravatar.py b/frappe/patches/v4_0/set_user_gravatar.py index 733b9bfe11..348991c320 100644 --- a/frappe/patches/v4_0/set_user_gravatar.py +++ b/frappe/patches/v4_0/set_user_gravatar.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/set_user_permissions.py b/frappe/patches/v4_0/set_user_permissions.py index 726b9ee715..ef6f3a27e5 100644 --- a/frappe/patches/v4_0/set_user_permissions.py +++ b/frappe/patches/v4_0/set_user_permissions.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import frappe.permissions diff --git a/frappe/patches/v4_0/set_website_route_idx.py b/frappe/patches/v4_0/set_website_route_idx.py index 663a324008..c3dba712d8 100644 --- a/frappe/patches/v4_0/set_website_route_idx.py +++ b/frappe/patches/v4_0/set_website_route_idx.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v4_0/update_custom_field_insert_after.py b/frappe/patches/v4_0/update_custom_field_insert_after.py index ddb888c493..4cb50956d6 100644 --- a/frappe/patches/v4_0/update_custom_field_insert_after.py +++ b/frappe/patches/v4_0/update_custom_field_insert_after.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_0/update_datetime.py b/frappe/patches/v4_0/update_datetime.py index 0e91174780..4034d8f665 100644 --- a/frappe/patches/v4_0/update_datetime.py +++ b/frappe/patches/v4_0/update_datetime.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v4_0/webnotes_to_frappe.py b/frappe/patches/v4_0/webnotes_to_frappe.py index 22b3848d5a..c29f6f603e 100644 --- a/frappe/patches/v4_0/webnotes_to_frappe.py +++ b/frappe/patches/v4_0/webnotes_to_frappe.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json def execute(): diff --git a/frappe/patches/v4_0/website_sitemap_hierarchy.py b/frappe/patches/v4_0/website_sitemap_hierarchy.py index bb22144cd7..6404986245 100644 --- a/frappe/patches/v4_0/website_sitemap_hierarchy.py +++ b/frappe/patches/v4_0/website_sitemap_hierarchy.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe def execute(): diff --git a/frappe/patches/v4_1/enable_outgoing_email_settings.py b/frappe/patches/v4_1/enable_outgoing_email_settings.py index 7ffa84a278..ffa891ae7c 100644 --- a/frappe/patches/v4_1/enable_outgoing_email_settings.py +++ b/frappe/patches/v4_1/enable_outgoing_email_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_1/enable_print_as_pdf.py b/frappe/patches/v4_1/enable_print_as_pdf.py index 74db9f72ca..e5a8f830f6 100644 --- a/frappe/patches/v4_1/enable_print_as_pdf.py +++ b/frappe/patches/v4_1/enable_print_as_pdf.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_1/file_manager_fix.py b/frappe/patches/v4_1/file_manager_fix.py index cd30c94177..18f44203f2 100644 --- a/frappe/patches/v4_1/file_manager_fix.py +++ b/frappe/patches/v4_1/file_manager_fix.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe import os from frappe.core.doctype.file.file import get_content_hash, get_file_name @@ -19,7 +16,6 @@ from frappe.utils import get_files_path, get_site_path # a backup from a time before version 3 migration # # * Patch remaining unpatched File records. -from six import iteritems def execute(): @@ -52,7 +48,7 @@ def get_replaced_files(): old_files = dict(frappe.db.sql("select name, file_name from `tabFile` where ifnull(content_hash, '')=''")) invfiles = invert_dict(new_files) - for nname, nfilename in iteritems(new_files): + for nname, nfilename in new_files.items(): if 'files/' + nfilename in old_files.values(): ret.append((nfilename, invfiles[nfilename])) return ret @@ -85,7 +81,7 @@ def rename_replacing_files(): def invert_dict(ddict): ret = {} - for k,v in iteritems(ddict): + for k,v in ddict.items(): if not ret.get(v): ret[v] = [k] else: diff --git a/frappe/patches/v4_2/print_with_letterhead.py b/frappe/patches/v4_2/print_with_letterhead.py index 3e611ce073..111f6c762e 100644 --- a/frappe/patches/v4_2/print_with_letterhead.py +++ b/frappe/patches/v4_2/print_with_letterhead.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v4_2/refactor_website_routing.py b/frappe/patches/v4_2/refactor_website_routing.py index a5856db1c9..77eea3d429 100644 --- a/frappe/patches/v4_2/refactor_website_routing.py +++ b/frappe/patches/v4_2/refactor_website_routing.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v4_2/set_assign_in_doc.py b/frappe/patches/v4_2/set_assign_in_doc.py index a6a06492a0..8fbd37c5c5 100644 --- a/frappe/patches/v4_2/set_assign_in_doc.py +++ b/frappe/patches/v4_2/set_assign_in_doc.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v4_3/remove_allow_on_submit_customization.py b/frappe/patches/v4_3/remove_allow_on_submit_customization.py index af6ade68e6..a762fd10ab 100644 --- a/frappe/patches/v4_3/remove_allow_on_submit_customization.py +++ b/frappe/patches/v4_3/remove_allow_on_submit_customization.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v5_0/bookmarks_to_stars.py b/frappe/patches/v5_0/bookmarks_to_stars.py index 048d059701..0d2c13525e 100644 --- a/frappe/patches/v5_0/bookmarks_to_stars.py +++ b/frappe/patches/v5_0/bookmarks_to_stars.py @@ -1,9 +1,8 @@ -from __future__ import unicode_literals + 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"): @@ -13,7 +12,7 @@ def execute(): if not bookmarks: continue - if isinstance(bookmarks, string_types): + if isinstance(bookmarks, str): bookmarks = json.loads(bookmarks) for opts in bookmarks: diff --git a/frappe/patches/v5_0/clear_website_group_and_notifications.py b/frappe/patches/v5_0/clear_website_group_and_notifications.py index bad50222a3..3d3d0c0d16 100644 --- a/frappe/patches/v5_0/clear_website_group_and_notifications.py +++ b/frappe/patches/v5_0/clear_website_group_and_notifications.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/communication_parent.py b/frappe/patches/v5_0/communication_parent.py index 2ea3b401c6..3c73d91972 100644 --- a/frappe/patches/v5_0/communication_parent.py +++ b/frappe/patches/v5_0/communication_parent.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py b/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py index 0ea2ee2387..6fa6434f98 100644 --- a/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py +++ b/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.database.mariadb.setup_db import check_database_settings from frappe.model.meta import trim_tables diff --git a/frappe/patches/v5_0/expire_old_scheduler_logs.py b/frappe/patches/v5_0/expire_old_scheduler_logs.py index 8b65ed5fb1..0262acd346 100644 --- a/frappe/patches/v5_0/expire_old_scheduler_logs.py +++ b/frappe/patches/v5_0/expire_old_scheduler_logs.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/fix_email_alert.py b/frappe/patches/v5_0/fix_email_alert.py index 0676f50a9c..e7366e8b66 100644 --- a/frappe/patches/v5_0/fix_email_alert.py +++ b/frappe/patches/v5_0/fix_email_alert.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe def execute(): diff --git a/frappe/patches/v5_0/fix_null_date_datetime.py b/frappe/patches/v5_0/fix_null_date_datetime.py index e4f4e9e8b9..078cba079a 100644 --- a/frappe/patches/v5_0/fix_null_date_datetime.py +++ b/frappe/patches/v5_0/fix_null_date_datetime.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/fix_text_editor_file_urls.py b/frappe/patches/v5_0/fix_text_editor_file_urls.py index a6d7d2fb9a..43f0c9d8a5 100644 --- a/frappe/patches/v5_0/fix_text_editor_file_urls.py +++ b/frappe/patches/v5_0/fix_text_editor_file_urls.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals, print_function import frappe import re diff --git a/frappe/patches/v5_0/force_sync_website.py b/frappe/patches/v5_0/force_sync_website.py index 5dcd0d79c7..8f48729276 100644 --- a/frappe/patches/v5_0/force_sync_website.py +++ b/frappe/patches/v5_0/force_sync_website.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/modify_session.py b/frappe/patches/v5_0/modify_session.py index f0e247a633..1c2ff0d6e6 100644 --- a/frappe/patches/v5_0/modify_session.py +++ b/frappe/patches/v5_0/modify_session.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py b/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py index 0fa1dad1e5..bdc52e6152 100644 --- a/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py +++ b/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v5_0/remove_shopping_cart_app.py b/frappe/patches/v5_0/remove_shopping_cart_app.py index babde585a1..ed9414159e 100644 --- a/frappe/patches/v5_0/remove_shopping_cart_app.py +++ b/frappe/patches/v5_0/remove_shopping_cart_app.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals - def execute(): from frappe.installer import remove_from_installed_apps remove_from_installed_apps("shopping_cart") diff --git a/frappe/patches/v5_0/rename_ref_type_fieldnames.py b/frappe/patches/v5_0/rename_ref_type_fieldnames.py index dd24f6e5b5..01e36af8a9 100644 --- a/frappe/patches/v5_0/rename_ref_type_fieldnames.py +++ b/frappe/patches/v5_0/rename_ref_type_fieldnames.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v5_0/rename_table_fieldnames.py b/frappe/patches/v5_0/rename_table_fieldnames.py index b716599f28..79703bbba2 100644 --- a/frappe/patches/v5_0/rename_table_fieldnames.py +++ b/frappe/patches/v5_0/rename_table_fieldnames.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.utils.rename_field import rename_field from frappe.modules import scrub, get_doctype_module diff --git a/frappe/patches/v5_0/style_settings_to_website_theme.py b/frappe/patches/v5_0/style_settings_to_website_theme.py index 40414d4e20..73ee28c1fc 100644 --- a/frappe/patches/v5_0/style_settings_to_website_theme.py +++ b/frappe/patches/v5_0/style_settings_to_website_theme.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe import _ from frappe.utils import cint diff --git a/frappe/patches/v5_0/update_shared.py b/frappe/patches/v5_0/update_shared.py index f2b77895d8..e549d7271d 100644 --- a/frappe/patches/v5_0/update_shared.py +++ b/frappe/patches/v5_0/update_shared.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe import frappe.share diff --git a/frappe/patches/v5_0/v4_to_v5.py b/frappe/patches/v5_0/v4_to_v5.py index cd34f04c97..479acc6d63 100644 --- a/frappe/patches/v5_0/v4_to_v5.py +++ b/frappe/patches/v5_0/v4_to_v5.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v5_2/change_checks_to_not_null.py b/frappe/patches/v5_2/change_checks_to_not_null.py index 23f5d659b5..32be3aa752 100644 --- a/frappe/patches/v5_2/change_checks_to_not_null.py +++ b/frappe/patches/v5_2/change_checks_to_not_null.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils import cint from frappe.model import default_fields diff --git a/frappe/patches/v5_3/rename_chinese_languages.py b/frappe/patches/v5_3/rename_chinese_languages.py index 8bc954c04c..f720fb7538 100644 --- a/frappe/patches/v5_3/rename_chinese_languages.py +++ b/frappe/patches/v5_3/rename_chinese_languages.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import frappe from frappe.translate import rename_language diff --git a/frappe/patches/v6_0/communication_status_and_permission.py b/frappe/patches/v6_0/communication_status_and_permission.py index c68ed9b4d6..435dcc21a5 100644 --- a/frappe/patches/v6_0/communication_status_and_permission.py +++ b/frappe/patches/v6_0/communication_status_and_permission.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.permissions import reset_perms diff --git a/frappe/patches/v6_0/document_type_rename.py b/frappe/patches/v6_0/document_type_rename.py index 16c7d34286..53eec5d85c 100644 --- a/frappe/patches/v6_0/document_type_rename.py +++ b/frappe/patches/v6_0/document_type_rename.py @@ -1,8 +1,8 @@ -from __future__ import unicode_literals + import frappe def execute(): frappe.db.sql("""update tabDocType set document_type='Document' where document_type='Transaction'""") frappe.db.sql("""update tabDocType set document_type='Setup' - where document_type='Master'""") + where document_type='Master'""") diff --git a/frappe/patches/v6_0/fix_ghana_currency.py b/frappe/patches/v6_0/fix_ghana_currency.py index 67f740d240..50feb3ca3f 100644 --- a/frappe/patches/v6_0/fix_ghana_currency.py +++ b/frappe/patches/v6_0/fix_ghana_currency.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - def execute(): from frappe.geo.country_info import get_all import frappe.utils.install diff --git a/frappe/patches/v6_0/make_task_log_folder.py b/frappe/patches/v6_0/make_task_log_folder.py index 87d6e4126f..b5ed547d71 100644 --- a/frappe/patches/v6_0/make_task_log_folder.py +++ b/frappe/patches/v6_0/make_task_log_folder.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe.utils, os def execute(): diff --git a/frappe/patches/v6_1/rename_file_data.py b/frappe/patches/v6_1/rename_file_data.py index 83152271eb..3c62217e8d 100644 --- a/frappe/patches/v6_1/rename_file_data.py +++ b/frappe/patches/v6_1/rename_file_data.py @@ -1,4 +1,3 @@ -from __future__ import print_function, unicode_literals import frappe def execute(): diff --git a/frappe/patches/v6_11/rename_field_in_email_account.py b/frappe/patches/v6_11/rename_field_in_email_account.py index 319b569802..8e600cc2b9 100644 --- a/frappe/patches/v6_11/rename_field_in_email_account.py +++ b/frappe/patches/v6_11/rename_field_in_email_account.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_15/remove_property_setter_for_previous_field.py b/frappe/patches/v6_15/remove_property_setter_for_previous_field.py index b24bf38442..9f0cd69489 100644 --- a/frappe/patches/v6_15/remove_property_setter_for_previous_field.py +++ b/frappe/patches/v6_15/remove_property_setter_for_previous_field.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, json from frappe.utils import cstr diff --git a/frappe/patches/v6_15/set_username.py b/frappe/patches/v6_15/set_username.py index 513ff3301d..ebf01763d0 100644 --- a/frappe/patches/v6_15/set_username.py +++ b/frappe/patches/v6_15/set_username.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_16/feed_doc_owner.py b/frappe/patches/v6_16/feed_doc_owner.py index 2dac9a143d..b7e738b6d9 100644 --- a/frappe/patches/v6_16/feed_doc_owner.py +++ b/frappe/patches/v6_16/feed_doc_owner.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_16/star_to_like.py b/frappe/patches/v6_16/star_to_like.py index e859223d54..f3fc6310d9 100644 --- a/frappe/patches/v6_16/star_to_like.py +++ b/frappe/patches/v6_16/star_to_like.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.database.schema import add_column diff --git a/frappe/patches/v6_19/comment_feed_communication.py b/frappe/patches/v6_19/comment_feed_communication.py index a7503c08ab..64c5ad9c4c 100644 --- a/frappe/patches/v6_19/comment_feed_communication.py +++ b/frappe/patches/v6_19/comment_feed_communication.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe import _ from frappe.model.rename_doc import get_link_fields diff --git a/frappe/patches/v6_2/ignore_user_permissions_if_missing.py b/frappe/patches/v6_2/ignore_user_permissions_if_missing.py index 356d28989a..e216dc36b6 100644 --- a/frappe/patches/v6_2/ignore_user_permissions_if_missing.py +++ b/frappe/patches/v6_2/ignore_user_permissions_if_missing.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_2/rename_backup_manager.py b/frappe/patches/v6_2/rename_backup_manager.py index af02e55878..df2fa72c05 100644 --- a/frappe/patches/v6_2/rename_backup_manager.py +++ b/frappe/patches/v6_2/rename_backup_manager.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_20x/remove_roles_from_website_user.py b/frappe/patches/v6_20x/remove_roles_from_website_user.py index a4d579a1f0..19009ff455 100644 --- a/frappe/patches/v6_20x/remove_roles_from_website_user.py +++ b/frappe/patches/v6_20x/remove_roles_from_website_user.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_20x/set_allow_draft_for_print.py b/frappe/patches/v6_20x/set_allow_draft_for_print.py index 90c15e22b2..0b604567ec 100644 --- a/frappe/patches/v6_20x/set_allow_draft_for_print.py +++ b/frappe/patches/v6_20x/set_allow_draft_for_print.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_20x/update_insert_after.py b/frappe/patches/v6_20x/update_insert_after.py index 5ebec52fc9..37820b2437 100644 --- a/frappe/patches/v6_20x/update_insert_after.py +++ b/frappe/patches/v6_20x/update_insert_after.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json def execute(): diff --git a/frappe/patches/v6_21/print_settings_repeat_header_footer.py b/frappe/patches/v6_21/print_settings_repeat_header_footer.py index 941a145a54..0919c35903 100644 --- a/frappe/patches/v6_21/print_settings_repeat_header_footer.py +++ b/frappe/patches/v6_21/print_settings_repeat_header_footer.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_24/set_language_as_code.py b/frappe/patches/v6_24/set_language_as_code.py index d685fd7d0e..6f862ede2e 100644 --- a/frappe/patches/v6_24/set_language_as_code.py +++ b/frappe/patches/v6_24/set_language_as_code.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.translate import get_lang_dict diff --git a/frappe/patches/v6_4/reduce_varchar_length.py b/frappe/patches/v6_4/reduce_varchar_length.py index 93a8be8c92..7edde55778 100644 --- a/frappe/patches/v6_4/reduce_varchar_length.py +++ b/frappe/patches/v6_4/reduce_varchar_length.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals, print_function import frappe def execute(): diff --git a/frappe/patches/v6_4/rename_bengali_language.py b/frappe/patches/v6_4/rename_bengali_language.py index dbbcb62f8d..f872dea1b9 100644 --- a/frappe/patches/v6_4/rename_bengali_language.py +++ b/frappe/patches/v6_4/rename_bengali_language.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import frappe from frappe.translate import rename_language diff --git a/frappe/patches/v6_6/fix_file_url.py b/frappe/patches/v6_6/fix_file_url.py index 4f8956d343..48e292f4d4 100644 --- a/frappe/patches/v6_6/fix_file_url.py +++ b/frappe/patches/v6_6/fix_file_url.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.meta import is_single diff --git a/frappe/patches/v6_6/rename_slovak_language.py b/frappe/patches/v6_6/rename_slovak_language.py index a942543372..198949e79c 100644 --- a/frappe/patches/v6_6/rename_slovak_language.py +++ b/frappe/patches/v6_6/rename_slovak_language.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import frappe from frappe.translate import rename_language diff --git a/frappe/patches/v6_6/user_last_active.py b/frappe/patches/v6_6/user_last_active.py index fd55935174..b9f63fa45e 100644 --- a/frappe/patches/v6_6/user_last_active.py +++ b/frappe/patches/v6_6/user_last_active.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v6_9/int_float_not_null.py b/frappe/patches/v6_9/int_float_not_null.py index 97495f9077..c414d6b583 100644 --- a/frappe/patches/v6_9/int_float_not_null.py +++ b/frappe/patches/v6_9/int_float_not_null.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils import cint, flt diff --git a/frappe/patches/v6_9/rename_burmese_language.py b/frappe/patches/v6_9/rename_burmese_language.py index 66477f7efe..5e1333077e 100644 --- a/frappe/patches/v6_9/rename_burmese_language.py +++ b/frappe/patches/v6_9/rename_burmese_language.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals import frappe from frappe.translate import rename_language diff --git a/frappe/patches/v7_0/add_communication_in_doc.py b/frappe/patches/v7_0/add_communication_in_doc.py index 4db02c5bab..8be229fe3a 100644 --- a/frappe/patches/v7_0/add_communication_in_doc.py +++ b/frappe/patches/v7_0/add_communication_in_doc.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.core.doctype.comment.comment import update_comment_in_doc diff --git a/frappe/patches/v7_0/cleanup_list_settings.py b/frappe/patches/v7_0/cleanup_list_settings.py index e03ff57406..9fe2e71ed1 100644 --- a/frappe/patches/v7_0/cleanup_list_settings.py +++ b/frappe/patches/v7_0/cleanup_list_settings.py @@ -1,8 +1,8 @@ -from __future__ import unicode_literals + import frappe, json def execute(): - if frappe.db.table_exists("__ListSettings"): + if frappe.db.table_exists("__ListSettings"): list_settings = frappe.db.sql("select user, doctype, data from __ListSettings", as_dict=1) for ls in list_settings: if ls and ls.data: @@ -14,7 +14,7 @@ def execute(): if "name as" in field: fields.remove(field) data["fields"] = fields - - frappe.db.sql("update __ListSettings set data = %s where user=%s and doctype=%s", - (json.dumps(data), ls.user, ls.doctype)) - + + frappe.db.sql("update __ListSettings set data = %s where user=%s and doctype=%s", + (json.dumps(data), ls.user, ls.doctype)) + diff --git a/frappe/patches/v7_0/create_private_file_folder.py b/frappe/patches/v7_0/create_private_file_folder.py index bd26917a78..e89beb5d0f 100644 --- a/frappe/patches/v7_0/create_private_file_folder.py +++ b/frappe/patches/v7_0/create_private_file_folder.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, os def execute(): diff --git a/frappe/patches/v7_0/re_route.py b/frappe/patches/v7_0/re_route.py index cc36594ae8..8a4daaea86 100644 --- a/frappe/patches/v7_0/re_route.py +++ b/frappe/patches/v7_0/re_route.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.model.base_document import get_controller diff --git a/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py b/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py index 9a7a756144..42f2dfe4c2 100644 --- a/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py +++ b/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py b/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py index 79061d383c..5e40d9df35 100644 --- a/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py +++ b/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_0/set_email_group.py b/frappe/patches/v7_0/set_email_group.py index e3dd66ebf3..251e9a27b6 100644 --- a/frappe/patches/v7_0/set_email_group.py +++ b/frappe/patches/v7_0/set_email_group.py @@ -1,11 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): frappe.reload_doc("email", "doctype", "email_group_member") if "newsletter_list" in frappe.db.get_table_columns("Email Group Member"): - frappe.db.sql("""update `tabEmail Group Member` set email_group = newsletter_list + frappe.db.sql("""update `tabEmail Group Member` set email_group = newsletter_list where email_group is null or email_group = ''""") \ No newline at end of file diff --git a/frappe/patches/v7_0/set_user_fullname.py b/frappe/patches/v7_0/set_user_fullname.py index a7c6670f45..e69c180c27 100644 --- a/frappe/patches/v7_0/set_user_fullname.py +++ b/frappe/patches/v7_0/set_user_fullname.py @@ -1,9 +1,9 @@ -from __future__ import unicode_literals + import frappe def execute(): frappe.reload_doc("Core", "DocType", "User") - + for user in frappe.db.get_all('User'): user = frappe.get_doc('User', user.name) user.set_full_name() diff --git a/frappe/patches/v7_0/update_auth.py b/frappe/patches/v7_0/update_auth.py index 3d47edf4b5..098081563f 100644 --- a/frappe/patches/v7_0/update_auth.py +++ b/frappe/patches/v7_0/update_auth.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.password import create_auth_table, set_encrypted_password diff --git a/frappe/patches/v7_0/update_report_builder_json.py b/frappe/patches/v7_0/update_report_builder_json.py index a344ca5412..01a6126de7 100644 --- a/frappe/patches/v7_0/update_report_builder_json.py +++ b/frappe/patches/v7_0/update_report_builder_json.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v7_0/update_send_after_in_bulk_email.py b/frappe/patches/v7_0/update_send_after_in_bulk_email.py index 1b08309b6a..b9da83eaab 100644 --- a/frappe/patches/v7_0/update_send_after_in_bulk_email.py +++ b/frappe/patches/v7_0/update_send_after_in_bulk_email.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils import now_datetime diff --git a/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py b/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py index c74d2d98f9..6ab9340845 100644 --- a/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py +++ b/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py @@ -2,16 +2,15 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): frappe.reload_doctype('Print Format') - frappe.db.sql(""" - update - `tabPrint Format` - set - align_labels_right = 0, line_breaks = 0, show_section_headings = 0 - where + frappe.db.sql(""" + update + `tabPrint Format` + set + align_labels_right = 0, line_breaks = 0, show_section_headings = 0 + where custom_format = 1 """) diff --git a/frappe/patches/v7_1/refactor_integration_broker.py b/frappe/patches/v7_1/refactor_integration_broker.py index 8c9aaa6795..05ccae5d46 100644 --- a/frappe/patches/v7_1/refactor_integration_broker.py +++ b/frappe/patches/v7_1/refactor_integration_broker.py @@ -2,14 +2,13 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe import json def execute(): for doctype_name in ["Razorpay Log", "Razorpay Payment", "Razorpay Settings"]: delete_doc("DocType", doctype_name) - + reload_doctypes() setup_services() @@ -32,19 +31,19 @@ def setup_services(): service_settings = frappe.new_doc("{0} Settings".format(service["new_name"])) service_settings.update(settings) - + service_settings.flags.ignore_mandatory = True service_settings.save(ignore_permissions=True) if service["old_name"] in ["Dropbox Integration", "LDAP Auth"]: delete_doc("Integration Service", service["old_name"]) - + new_service_doc = frappe.get_doc({ "doctype": "Integration Service", "service": service["new_name"], "enabled": 1 }) - + new_service_doc.flags.ignore_mandatory = True new_service_doc.save(ignore_permissions=True) diff --git a/frappe/patches/v7_1/rename_chinese_language_codes.py b/frappe/patches/v7_1/rename_chinese_language_codes.py index 1ed25a4959..91ed73ccae 100644 --- a/frappe/patches/v7_1/rename_chinese_language_codes.py +++ b/frappe/patches/v7_1/rename_chinese_language_codes.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py b/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py index 4d1a39538f..c0c9e03565 100644 --- a/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py +++ b/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_1/set_backup_limit.py b/frappe/patches/v7_1/set_backup_limit.py index 7b0a344305..ce502393b2 100644 --- a/frappe/patches/v7_1/set_backup_limit.py +++ b/frappe/patches/v7_1/set_backup_limit.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + from frappe.utils import cint import frappe diff --git a/frappe/patches/v7_1/setup_integration_services.py b/frappe/patches/v7_1/setup_integration_services.py index 1c70b8e835..9f4c8a3915 100644 --- a/frappe/patches/v7_1/setup_integration_services.py +++ b/frappe/patches/v7_1/setup_integration_services.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.exceptions import DataError from frappe.utils.password import get_decrypted_password diff --git a/frappe/patches/v7_1/sync_language_doctype.py b/frappe/patches/v7_1/sync_language_doctype.py index 83d1a4f5a6..a5e9ad1cb1 100644 --- a/frappe/patches/v7_1/sync_language_doctype.py +++ b/frappe/patches/v7_1/sync_language_doctype.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.translate import get_lang_dict diff --git a/frappe/patches/v7_2/fix_email_queue_recipient.py b/frappe/patches/v7_2/fix_email_queue_recipient.py index 645b17b5c9..021397031b 100644 --- a/frappe/patches/v7_2/fix_email_queue_recipient.py +++ b/frappe/patches/v7_2/fix_email_queue_recipient.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_2/merge_knowledge_base.py b/frappe/patches/v7_2/merge_knowledge_base.py index 301d15e1dd..04e6c16213 100644 --- a/frappe/patches/v7_2/merge_knowledge_base.py +++ b/frappe/patches/v7_2/merge_knowledge_base.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.patches.v7_0.re_route import update_routes diff --git a/frappe/patches/v7_2/remove_in_filter.py b/frappe/patches/v7_2/remove_in_filter.py index 36556d7c13..306879f996 100644 --- a/frappe/patches/v7_2/remove_in_filter.py +++ b/frappe/patches/v7_2/remove_in_filter.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_2/set_doctype_engine.py b/frappe/patches/v7_2/set_doctype_engine.py index 3a5cc384a2..e0df9cff87 100644 --- a/frappe/patches/v7_2/set_doctype_engine.py +++ b/frappe/patches/v7_2/set_doctype_engine.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_2/set_in_standard_filter_property.py b/frappe/patches/v7_2/set_in_standard_filter_property.py index 12f97f7f8e..568f43d2aa 100644 --- a/frappe/patches/v7_2/set_in_standard_filter_property.py +++ b/frappe/patches/v7_2/set_in_standard_filter_property.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_2/setup_custom_perms.py b/frappe/patches/v7_2/setup_custom_perms.py index 1b3b86236c..1f46072782 100644 --- a/frappe/patches/v7_2/setup_custom_perms.py +++ b/frappe/patches/v7_2/setup_custom_perms.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.permissions import setup_custom_perms from frappe.core.page.permission_manager.permission_manager import get_standard_permissions diff --git a/frappe/patches/v7_2/setup_ldap_config.py b/frappe/patches/v7_2/setup_ldap_config.py index 31dd8ca6fe..c9ad3e6714 100644 --- a/frappe/patches/v7_2/setup_ldap_config.py +++ b/frappe/patches/v7_2/setup_ldap_config.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils import cint diff --git a/frappe/patches/v7_2/update_communications.py b/frappe/patches/v7_2/update_communications.py index f3d859b95a..114e531324 100644 --- a/frappe/patches/v7_2/update_communications.py +++ b/frappe/patches/v7_2/update_communications.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v7_2/update_feedback_request.py b/frappe/patches/v7_2/update_feedback_request.py index 11e9eb8e92..9bc656bf67 100644 --- a/frappe/patches/v7_2/update_feedback_request.py +++ b/frappe/patches/v7_2/update_feedback_request.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_0/deprecate_integration_broker.py b/frappe/patches/v8_0/deprecate_integration_broker.py index ad1a7d9571..9aeee17837 100644 --- a/frappe/patches/v8_0/deprecate_integration_broker.py +++ b/frappe/patches/v8_0/deprecate_integration_broker.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.integrations.utils import create_payment_gateway @@ -7,14 +7,14 @@ def execute(): for doctype in ["integration_request", "oauth_authorization_code", "oauth_bearer_token", "oauth_client"]: frappe.reload_doc('integrations', 'doctype', doctype) - + frappe.reload_doc("core", "doctype", "payment_gateway") update_doctype_module() create_payment_gateway_master_records() for doctype in ["Integration Service", "Integration Service Parameter"]: frappe.delete_doc("DocType", doctype) - + if not frappe.db.get_value("DocType", {"module": "Integration Broker"}, "name"): frappe.delete_doc("Module Def", "Integration Broker") diff --git a/frappe/patches/v8_0/drop_in_dialog.py b/frappe/patches/v8_0/drop_in_dialog.py index 231d757f26..5022333d22 100644 --- a/frappe/patches/v8_0/drop_in_dialog.py +++ b/frappe/patches/v8_0/drop_in_dialog.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_0/drop_is_custom_from_docperm.py b/frappe/patches/v8_0/drop_is_custom_from_docperm.py index 4530dcd2e0..0f17bbef5c 100644 --- a/frappe/patches/v8_0/drop_is_custom_from_docperm.py +++ b/frappe/patches/v8_0/drop_is_custom_from_docperm.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_0/drop_unwanted_indexes.py b/frappe/patches/v8_0/drop_unwanted_indexes.py index fc66ed43fd..655bce1a4b 100644 --- a/frappe/patches/v8_0/drop_unwanted_indexes.py +++ b/frappe/patches/v8_0/drop_unwanted_indexes.py @@ -2,14 +2,13 @@ # License: GNU General Public License v3. See license.txt # -*- coding: utf-8 -*- -from __future__ import unicode_literals import frappe def execute(): # communication - unwanted_indexes = ["communication_date_index", "message_id_index", "modified_index", + unwanted_indexes = ["communication_date_index", "message_id_index", "modified_index", "creation_index", "reference_owner", "communication_date"] - + for k in unwanted_indexes: try: frappe.db.sql("drop index {0} on `tabCommunication`".format(k)) diff --git a/frappe/patches/v8_0/install_new_build_system_requirements.py b/frappe/patches/v8_0/install_new_build_system_requirements.py index 536c2fcfb3..75ccfa87cd 100644 --- a/frappe/patches/v8_0/install_new_build_system_requirements.py +++ b/frappe/patches/v8_0/install_new_build_system_requirements.py @@ -1,4 +1,3 @@ -from __future__ import print_function, unicode_literals from subprocess import Popen, call, PIPE def execute(): diff --git a/frappe/patches/v8_0/newsletter_childtable_migrate.py b/frappe/patches/v8_0/newsletter_childtable_migrate.py index f652b37f56..67ff5e586f 100644 --- a/frappe/patches/v8_0/newsletter_childtable_migrate.py +++ b/frappe/patches/v8_0/newsletter_childtable_migrate.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): @@ -10,7 +9,7 @@ def execute(): if "email_group" not in frappe.db.get_table_columns("Newsletter"): return - + newsletters = frappe.get_all("Newsletter", fields=["name", "email_group"]) for newsletter in newsletters: if newsletter.email_group: diff --git a/frappe/patches/v8_0/rename_listsettings_to_usersettings.py b/frappe/patches/v8_0/rename_listsettings_to_usersettings.py index 584e4a1111..9545953e34 100644 --- a/frappe/patches/v8_0/rename_listsettings_to_usersettings.py +++ b/frappe/patches/v8_0/rename_listsettings_to_usersettings.py @@ -1,7 +1,6 @@ -from __future__ import unicode_literals + from frappe.model.utils.user_settings import update_user_settings import frappe, json -from six import iteritems def execute(): @@ -35,7 +34,7 @@ def execute(): for user in frappe.db.get_all('User', {'user_type': 'System User'}): defaults = frappe.defaults.get_defaults_for(user.name) - for key, value in iteritems(defaults): + for key, value in defaults.items(): if key.startswith('_list_settings:'): doctype = key.replace('_list_settings:', '') columns = ['`tab{1}`.`{0}`'.format(*c) for c in json.loads(value)] diff --git a/frappe/patches/v8_0/rename_page_role_to_has_role.py b/frappe/patches/v8_0/rename_page_role_to_has_role.py index 9c610d857d..49006ea419 100644 --- a/frappe/patches/v8_0/rename_page_role_to_has_role.py +++ b/frappe/patches/v8_0/rename_page_role_to_has_role.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): @@ -17,7 +16,7 @@ def reload_doc(): frappe.reload_doc("core", 'doctype', "report") frappe.reload_doc("core", 'doctype', "user") frappe.reload_doc("core", 'doctype', "has_role") - + def set_ref_doctype_roles_to_report(): for data in frappe.get_all('Report', fields=["name"]): doc = frappe.get_doc('Report', data.name) diff --git a/frappe/patches/v8_0/rename_print_to_printing.py b/frappe/patches/v8_0/rename_print_to_printing.py index ecdbc3f7be..56889d630e 100644 --- a/frappe/patches/v8_0/rename_print_to_printing.py +++ b/frappe/patches/v8_0/rename_print_to_printing.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): @@ -9,5 +9,5 @@ def execute(): frappe.reload_doc('printing', 'doctype', 'letter_head') frappe.reload_doc('printing', 'page', 'print_format_builder') frappe.db.sql("""update `tabPrint Format` set module='Printing' where module='Print'""") - + frappe.delete_doc('Module Def', 'Print') \ No newline at end of file diff --git a/frappe/patches/v8_0/set_allow_traceback.py b/frappe/patches/v8_0/set_allow_traceback.py index 3eceb3e29c..bb72e7dde6 100644 --- a/frappe/patches/v8_0/set_allow_traceback.py +++ b/frappe/patches/v8_0/set_allow_traceback.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_0/set_currency_field_precision.py b/frappe/patches/v8_0/set_currency_field_precision.py index 89835c8c1e..57b12ffdee 100644 --- a/frappe/patches/v8_0/set_currency_field_precision.py +++ b/frappe/patches/v8_0/set_currency_field_precision.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import get_number_format_info diff --git a/frappe/patches/v8_0/set_doctype_values_in_custom_role.py b/frappe/patches/v8_0/set_doctype_values_in_custom_role.py index 58cdc4497d..50e7eb83e1 100644 --- a/frappe/patches/v8_0/set_doctype_values_in_custom_role.py +++ b/frappe/patches/v8_0/set_doctype_values_in_custom_role.py @@ -1,13 +1,12 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): frappe.reload_doctype('Custom Role') - + # set ref doctype in custom role for reports - frappe.db.sql(""" update `tabCustom Role` set + frappe.db.sql(""" update `tabCustom Role` set `tabCustom Role`.ref_doctype = (select ref_doctype from `tabReport` where name = `tabCustom Role`.report) where `tabCustom Role`.report is not null""") diff --git a/frappe/patches/v8_0/set_user_permission_for_page_and_report.py b/frappe/patches/v8_0/set_user_permission_for_page_and_report.py index 560ea46db2..55789a8301 100644 --- a/frappe/patches/v8_0/set_user_permission_for_page_and_report.py +++ b/frappe/patches/v8_0/set_user_permission_for_page_and_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): @@ -9,13 +8,13 @@ def execute(): frappe.reload_doc("core", 'doctype', "custom_role") set_user_permission_for_page_and_report() - update_ref_doctype_in_custom_role() + update_ref_doctype_in_custom_role() def update_ref_doctype_in_custom_role(): frappe.reload_doc("core", 'doctype', "custom_role") - frappe.db.sql("""update `tabCustom Role` - set - ref_doctype = (select ref_doctype from tabReport where name = `tabCustom Role`.report) + frappe.db.sql("""update `tabCustom Role` + set + ref_doctype = (select ref_doctype from tabReport where name = `tabCustom Role`.report) where report is not null""") def set_user_permission_for_page_and_report(): diff --git a/frappe/patches/v8_0/setup_email_inbox.py b/frappe/patches/v8_0/setup_email_inbox.py index 1bfe3b0b74..ad99068eb9 100644 --- a/frappe/patches/v8_0/setup_email_inbox.py +++ b/frappe/patches/v8_0/setup_email_inbox.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe, json from frappe.core.doctype.user.user import ask_pass_update, setup_user_email_inbox diff --git a/frappe/patches/v8_0/update_gender_and_salutation.py b/frappe/patches/v8_0/update_gender_and_salutation.py index bcd9d4cbd7..913e0f714b 100644 --- a/frappe/patches/v8_0/update_gender_and_salutation.py +++ b/frappe/patches/v8_0/update_gender_and_salutation.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -from __future__ import unicode_literals import frappe from frappe.desk.page.setup_wizard.install_fixtures import update_genders, update_salutations diff --git a/frappe/patches/v8_0/update_global_search_table.py b/frappe/patches/v8_0/update_global_search_table.py index 3c0a70155b..4d5c8be9cf 100644 --- a/frappe/patches/v8_0/update_global_search_table.py +++ b/frappe/patches/v8_0/update_global_search_table.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_0/update_published_in_global_search.py b/frappe/patches/v8_0/update_published_in_global_search.py index a378f24732..ae86cb8b24 100644 --- a/frappe/patches/v8_0/update_published_in_global_search.py +++ b/frappe/patches/v8_0/update_published_in_global_search.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_0/update_records_in_global_search.py b/frappe/patches/v8_0/update_records_in_global_search.py index dafa1e76d3..316f84b2f0 100644 --- a/frappe/patches/v8_0/update_records_in_global_search.py +++ b/frappe/patches/v8_0/update_records_in_global_search.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.global_search import get_doctypes_with_global_search, rebuild_for_doctype from frappe.utils import update_progress_bar @@ -6,7 +6,7 @@ from frappe.utils import update_progress_bar def execute(): frappe.cache().delete_value('doctypes_with_global_search') doctypes_with_global_search = get_doctypes_with_global_search(with_child_tables=False) - + for i, doctype in enumerate(doctypes_with_global_search): update_progress_bar("Updating Global Search", i, len(doctypes_with_global_search)) rebuild_for_doctype(doctype) diff --git a/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py b/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py index 92b54edfd4..510018eb47 100644 --- a/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py +++ b/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py b/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py index 9bd9757a86..513bb274bc 100644 --- a/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py +++ b/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v8_1/update_format_options_in_auto_email_report.py b/frappe/patches/v8_1/update_format_options_in_auto_email_report.py index 56609780cb..8bea2b7bf5 100644 --- a/frappe/patches/v8_1/update_format_options_in_auto_email_report.py +++ b/frappe/patches/v8_1/update_format_options_in_auto_email_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v8_10/delete_static_web_page_from_global_search.py b/frappe/patches/v8_10/delete_static_web_page_from_global_search.py index 336562c157..aa6a053412 100644 --- a/frappe/patches/v8_10/delete_static_web_page_from_global_search.py +++ b/frappe/patches/v8_10/delete_static_web_page_from_global_search.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py b/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py index 89a9a7a1b9..5851e2855b 100644 --- a/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py +++ b/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import validate_email_address diff --git a/frappe/patches/v8_5/patch_event_colors.py b/frappe/patches/v8_5/patch_event_colors.py index 8ac7aec238..3c34f7946b 100644 --- a/frappe/patches/v8_5/patch_event_colors.py +++ b/frappe/patches/v8_5/patch_event_colors.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v8_x/update_user_permission.py b/frappe/patches/v8_x/update_user_permission.py index 693b87c974..387751500f 100644 --- a/frappe/patches/v8_x/update_user_permission.py +++ b/frappe/patches/v8_x/update_user_permission.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v9_1/__init__.py b/frappe/patches/v9_1/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/patches/v9_1/__init__.py +++ b/frappe/patches/v9_1/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py b/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py index 9d7c0f003f..f63e86a340 100644 --- a/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py +++ b/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe def execute(): diff --git a/frappe/patches/v9_1/move_feed_to_activity_log.py b/frappe/patches/v9_1/move_feed_to_activity_log.py index db46b4e419..a549296357 100644 --- a/frappe/patches/v9_1/move_feed_to_activity_log.py +++ b/frappe/patches/v9_1/move_feed_to_activity_log.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.background_jobs import enqueue diff --git a/frappe/patches/v9_1/resave_domain_settings.py b/frappe/patches/v9_1/resave_domain_settings.py index 1e54ad3aa5..5814871c2e 100644 --- a/frappe/patches/v9_1/resave_domain_settings.py +++ b/frappe/patches/v9_1/resave_domain_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/patches/v9_1/revert_domain_settings.py b/frappe/patches/v9_1/revert_domain_settings.py index a14b48dae6..99c5561d78 100644 --- a/frappe/patches/v9_1/revert_domain_settings.py +++ b/frappe/patches/v9_1/revert_domain_settings.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe def execute(): diff --git a/frappe/permissions.py b/frappe/permissions.py index 19f101aab5..e139b04a4e 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -1,12 +1,10 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function -from six import string_types -import frappe, copy, json +import frappe, copy from frappe import _, msgprint from frappe.utils import cint import frappe.share + rights = ("select", "read", "write", "create", "delete", "submit", "cancel", "amend", "print", "email", "report", "import", "export", "set_user_permissions", "share") @@ -58,7 +56,7 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None, ra meta = frappe.get_meta(doctype) if doc: - if isinstance(doc, string_types): + if isinstance(doc, str): doc = frappe.get_doc(meta.name, doc) perm = get_doc_permissions(doc, user=user, ptype=ptype).get(ptype) if not perm: push_perm_check_log(_('User {0} does not have access to this document').format(frappe.bold(user))) @@ -159,7 +157,7 @@ def get_role_permissions(doctype_meta, user=None, is_owner=None): } } """ - if isinstance(doctype_meta, string_types): + if isinstance(doctype_meta, str): doctype_meta = frappe.get_meta(doctype_meta) # assuming doctype name was passed if not user: user = frappe.session.user @@ -534,7 +532,7 @@ def get_linked_doctypes(dt): def get_doc_name(doc): if not doc: return None - return doc if isinstance(doc, string_types) else doc.name + return doc if isinstance(doc, str) else doc.name def allow_everything(): ''' diff --git a/frappe/printing/doctype/letter_head/letter_head.py b/frappe/printing/doctype/letter_head/letter_head.py index 3a3b14faad..948be60b88 100644 --- a/frappe/printing/doctype/letter_head/letter_head.py +++ b/frappe/printing/doctype/letter_head/letter_head.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import is_image from frappe.model.document import Document @@ -19,7 +18,7 @@ class LetterHead(Document): def validate_disabled_and_default(self): if self.disabled and self.is_default: frappe.throw(_("Letter Head cannot be both disabled and default")) - + if not self.is_default and not self.disabled: if not frappe.db.exists('Letter Head', dict(is_default=1)): self.is_default = 1 diff --git a/frappe/printing/doctype/letter_head/test_letter_head.py b/frappe/printing/doctype/letter_head/test_letter_head.py index b69e9924ea..96dfc68705 100644 --- a/frappe/printing/doctype/letter_head/test_letter_head.py +++ b/frappe/printing/doctype/letter_head/test_letter_head.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/printing/doctype/print_format/print_format.py b/frappe/printing/doctype/print_format/print_format.py index 1c11f2d519..5d4ff92fe2 100644 --- a/frappe/printing/doctype/print_format/print_format.py +++ b/frappe/printing/doctype/print_format/print_format.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import frappe.utils import json diff --git a/frappe/printing/doctype/print_format/test_print_format.py b/frappe/printing/doctype/print_format/test_print_format.py index 121916ae5f..e65eb0183f 100644 --- a/frappe/printing/doctype/print_format/test_print_format.py +++ b/frappe/printing/doctype/print_format/test_print_format.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals, print_function - import frappe import unittest import re diff --git a/frappe/printing/doctype/print_heading/print_heading.py b/frappe/printing/doctype/print_heading/print_heading.py index 1bb3e52dd5..f9955c019d 100644 --- a/frappe/printing/doctype/print_heading/print_heading.py +++ b/frappe/printing/doctype/print_heading/print_heading.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/printing/doctype/print_heading/test_print_heading.py b/frappe/printing/doctype/print_heading/test_print_heading.py index 1a6435e783..ce99cde607 100644 --- a/frappe/printing/doctype/print_heading/test_print_heading.py +++ b/frappe/printing/doctype/print_heading/test_print_heading.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/printing/doctype/print_settings/print_settings.py b/frappe/printing/doctype/print_settings/print_settings.py index cf6a71a8ac..610c083097 100644 --- a/frappe/printing/doctype/print_settings/print_settings.py +++ b/frappe/printing/doctype/print_settings/print_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import cint diff --git a/frappe/printing/doctype/print_settings/test_print_settings.py b/frappe/printing/doctype/print_settings/test_print_settings.py index b8ad70a681..d1dec861b2 100644 --- a/frappe/printing/doctype/print_settings/test_print_settings.py +++ b/frappe/printing/doctype/print_settings/test_print_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import unittest class TestPrintSettings(unittest.TestCase): diff --git a/frappe/printing/doctype/print_style/print_style.py b/frappe/printing/doctype/print_style/print_style.py index 310babd5df..a91786795c 100644 --- a/frappe/printing/doctype/print_style/print_style.py +++ b/frappe/printing/doctype/print_style/print_style.py @@ -2,7 +2,6 @@ # Copyright (c) 2017, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/printing/doctype/print_style/test_print_style.py b/frappe/printing/doctype/print_style/test_print_style.py index cee57f8826..b717b23df8 100644 --- a/frappe/printing/doctype/print_style/test_print_style.py +++ b/frappe/printing/doctype/print_style/test_print_style.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/pythonrc.py b/frappe/pythonrc.py index 308bad7382..6761ead05b 100755 --- a/frappe/pythonrc.py +++ b/frappe/pythonrc.py @@ -3,8 +3,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import os import frappe frappe.connect(site=os.environ.get("site")) \ No newline at end of file diff --git a/frappe/rate_limiter.py b/frappe/rate_limiter.py index 40db8fe892..023cdb9cb0 100644 --- a/frappe/rate_limiter.py +++ b/frappe/rate_limiter.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - from datetime import datetime from functools import wraps from typing import Union, Callable diff --git a/frappe/recorder.py b/frappe/recorder.py index e3eef94809..02036b7374 100644 --- a/frappe/recorder.py +++ b/frappe/recorder.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - from collections import Counter import datetime import inspect diff --git a/frappe/sessions.py b/frappe/sessions.py index 9e503bbe25..1bc78448e7 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals """ Boot session from cache or build @@ -16,8 +14,7 @@ import frappe.model.meta import frappe.defaults import frappe.translate import redis -from six.moves.urllib.parse import unquote -from six import text_type +from urllib.parse import unquote from frappe.cache_manager import clear_user_cache @frappe.whitelist(allow_guest=True) @@ -337,7 +334,7 @@ class Session: now = frappe.utils.now() self.data['data']['last_updated'] = now - self.data['data']['lang'] = text_type(frappe.lang) + self.data['data']['lang'] = str(frappe.lang) # update session in db last_updated = frappe.cache().hget("last_db_session_update", self.sid) diff --git a/frappe/share.py b/frappe/share.py index 63c6ce2f35..10c0f26c22 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.desk.form.document_follow import follow_document diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.py b/frappe/social/doctype/energy_point_log/energy_point_log.py index 2e2289aed4..aff3c7cd59 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/energy_point_log.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ import json diff --git a/frappe/social/doctype/energy_point_log/test_energy_point_log.py b/frappe/social/doctype/energy_point_log/test_energy_point_log.py index 222c64389b..8c4dba5d6b 100644 --- a/frappe/social/doctype/energy_point_log/test_energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/test_energy_point_log.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from .energy_point_log import get_energy_points as _get_energy_points, create_review_points_log, review 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 9acb63d087..1c736528de 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ import frappe.cache_manager diff --git a/frappe/social/doctype/energy_point_settings/energy_point_settings.py b/frappe/social/doctype/energy_point_settings/energy_point_settings.py index 7299eef916..64944d64e8 100644 --- a/frappe/social/doctype/energy_point_settings/energy_point_settings.py +++ b/frappe/social/doctype/energy_point_settings/energy_point_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.social.doctype.energy_point_log.energy_point_log import create_review_points_log diff --git a/frappe/social/doctype/post/post.py b/frappe/social/doctype/post/post.py index 9c7c1db1d4..62a0155d3c 100644 --- a/frappe/social/doctype/post/post.py +++ b/frappe/social/doctype/post/post.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import requests from bs4 import BeautifulSoup diff --git a/frappe/social/doctype/post_comment/post_comment.py b/frappe/social/doctype/post_comment/post_comment.py index df24c4609a..14001ba537 100644 --- a/frappe/social/doctype/post_comment/post_comment.py +++ b/frappe/social/doctype/post_comment/post_comment.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.core.doctype.user.user import extract_mentions diff --git a/frappe/social/doctype/review_level/review_level.py b/frappe/social/doctype/review_level/review_level.py index 87720b63fc..6622a89ab9 100644 --- a/frappe/social/doctype/review_level/review_level.py +++ b/frappe/social/doctype/review_level/review_level.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/templates/includes/comments/comments.py b/frappe/templates/includes/comments/comments.py index d08eb12ba8..2dda492593 100644 --- a/frappe/templates/includes/comments/comments.py +++ b/frappe/templates/includes/comments/comments.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import re from frappe.website.render import clear_cache diff --git a/frappe/templates/pages/integrations/braintree_checkout.py b/frappe/templates/pages/integrations/braintree_checkout.py index ad262c34b2..c4aa1a7b9f 100644 --- a/frappe/templates/pages/integrations/braintree_checkout.py +++ b/frappe/templates/pages/integrations/braintree_checkout.py @@ -1,6 +1,5 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import flt diff --git a/frappe/templates/pages/integrations/payment_cancel.py b/frappe/templates/pages/integrations/payment_cancel.py index db335b8549..0387c9e50a 100644 --- a/frappe/templates/pages/integrations/payment_cancel.py +++ b/frappe/templates/pages/integrations/payment_cancel.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals import frappe def get_context(context): diff --git a/frappe/templates/pages/integrations/payment_success.py b/frappe/templates/pages/integrations/payment_success.py index bdc14db5b9..1eb9215121 100644 --- a/frappe/templates/pages/integrations/payment_success.py +++ b/frappe/templates/pages/integrations/payment_success.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe no_cache = True diff --git a/frappe/templates/pages/integrations/paytm_checkout.py b/frappe/templates/pages/integrations/paytm_checkout.py index bc385b5784..1bd9457ef6 100644 --- a/frappe/templates/pages/integrations/paytm_checkout.py +++ b/frappe/templates/pages/integrations/paytm_checkout.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ import json diff --git a/frappe/templates/pages/integrations/razorpay_checkout.py b/frappe/templates/pages/integrations/razorpay_checkout.py index 039ea1776e..1901577d4b 100644 --- a/frappe/templates/pages/integrations/razorpay_checkout.py +++ b/frappe/templates/pages/integrations/razorpay_checkout.py @@ -1,11 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import flt, cint import json -from six import string_types no_cache = 1 @@ -47,7 +45,7 @@ def get_api_key(): def make_payment(razorpay_payment_id, options, reference_doctype, reference_docname, token): data = {} - if isinstance(options, string_types): + if isinstance(options, str): data = json.loads(options) data.update({ diff --git a/frappe/templates/pages/integrations/stripe_checkout.py b/frappe/templates/pages/integrations/stripe_checkout.py index 142d5b35cd..186c3e0942 100644 --- a/frappe/templates/pages/integrations/stripe_checkout.py +++ b/frappe/templates/pages/integrations/stripe_checkout.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import cint, fmt_money diff --git a/frappe/test_runner.py b/frappe/test_runner.py index cd71dd46c5..1f99e55fb8 100644 --- a/frappe/test_runner.py +++ b/frappe/test_runner.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe import unittest, json, sys, os import time @@ -11,8 +8,8 @@ import importlib from frappe.modules import load_doctype_module, get_module_name import frappe.utils.scheduler import cProfile, pstats -from six import StringIO -from six.moves import reload_module +from io import StringIO +from importlib import reload from frappe.model.naming import revert_series_if_last unittest_runner = unittest.TextTestRunner @@ -281,7 +278,7 @@ def get_modules(doctype): try: test_module = load_doctype_module(doctype, module, "test_") if test_module: - reload_module(test_module) + reload(test_module) except ImportError: test_module = None diff --git a/frappe/tests/test_assign.py b/frappe/tests/test_assign.py index 439e1546c0..e9c1ccec6d 100644 --- a/frappe/tests/test_assign.py +++ b/frappe/tests/test_assign.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest import frappe.desk.form.assign_to from frappe.desk.listview import get_group_by_count diff --git a/frappe/tests/test_auth.py b/frappe/tests/test_auth.py index bbe9c36aea..bc23cb591c 100644 --- a/frappe/tests/test_auth.py +++ b/frappe/tests/test_auth.py @@ -1,7 +1,5 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import time import unittest diff --git a/frappe/tests/test_bot.py b/frappe/tests/test_bot.py index b098584a8f..4500ab95ac 100644 --- a/frappe/tests/test_bot.py +++ b/frappe/tests/test_bot.py @@ -3,7 +3,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest class TestBot(unittest.TestCase): diff --git a/frappe/tests/test_client.py b/frappe/tests/test_client.py index 6be437601b..aed8dc8581 100644 --- a/frappe/tests/test_client.py +++ b/frappe/tests/test_client.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -from __future__ import unicode_literals - import unittest import frappe diff --git a/frappe/tests/test_cors.py b/frappe/tests/test_cors.py index d4ed260f61..38c3fd8132 100644 --- a/frappe/tests/test_cors.py +++ b/frappe/tests/test_cors.py @@ -1,7 +1,5 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest from werkzeug.wrappers import Response from frappe.app import process_response diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 79ab8bf421..a31a898d73 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -3,8 +3,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest from random import choice diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 085c257550..42ebd05b67 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest from frappe.model.db_query import DatabaseQuery diff --git a/frappe/tests/test_defaults.py b/frappe/tests/test_defaults.py index 210ea0d36c..d051c0a184 100644 --- a/frappe/tests/test_defaults.py +++ b/frappe/tests/test_defaults.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest from frappe.defaults import * diff --git a/frappe/tests/test_document.py b/frappe/tests/test_document.py index 1a5a8721fd..7c0c95671a 100644 --- a/frappe/tests/test_document.py +++ b/frappe/tests/test_document.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import os import unittest diff --git a/frappe/tests/test_document_locks.py b/frappe/tests/test_document_locks.py index c270b1bf28..650a913bee 100644 --- a/frappe/tests/test_document_locks.py +++ b/frappe/tests/test_document_locks.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest class TestDocumentLocks(unittest.TestCase): diff --git a/frappe/tests/test_domainification.py b/frappe/tests/test_domainification.py index 2fd2e7f3ff..c9acd9ec45 100644 --- a/frappe/tests/test_domainification.py +++ b/frappe/tests/test_domainification.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest, frappe from frappe.core.page.permission_manager.permission_manager import get_roles_and_doctypes from frappe.desk.doctype.desktop_icon.desktop_icon import (get_desktop_icons, add_user_icon, diff --git a/frappe/tests/test_dynamic_links.py b/frappe/tests/test_dynamic_links.py index 98da2cbc35..04ccc91ff2 100644 --- a/frappe/tests/test_dynamic_links.py +++ b/frappe/tests/test_dynamic_links.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest class TestDynamicLinks(unittest.TestCase): diff --git a/frappe/tests/test_email.py b/frappe/tests/test_email.py index 8340db4852..445ee21b36 100644 --- a/frappe/tests/test_email.py +++ b/frappe/tests/test_email.py @@ -1,10 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest, frappe, re, email -from six import PY3 test_dependencies = ['Email Account'] @@ -118,10 +115,7 @@ class TestEmail(unittest.TestCase): content = part.get_payload(decode=True) if content: - if PY3: - eol = "\r\n" - else: - eol = "\n" + eol = "\r\n" frappe.local.flags.signed_query_string = \ re.search(r'(?<=/api/method/frappe.email.queue.unsubscribe\?).*(?=' + eol + ')', diff --git a/frappe/tests/test_exporter_fixtures.py b/frappe/tests/test_exporter_fixtures.py index b8bd94e3e9..0893500daf 100644 --- a/frappe/tests/test_exporter_fixtures.py +++ b/frappe/tests/test_exporter_fixtures.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import frappe.defaults from frappe.core.doctype.data_import.data_import import export_csv diff --git a/frappe/tests/test_fmt_datetime.py b/frappe/tests/test_fmt_datetime.py index e19eb25fe6..8f5408948d 100644 --- a/frappe/tests/test_fmt_datetime.py +++ b/frappe/tests/test_fmt_datetime.py @@ -1,7 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import datetime import frappe diff --git a/frappe/tests/test_fmt_money.py b/frappe/tests/test_fmt_money.py index a1321658b7..160ea33378 100644 --- a/frappe/tests/test_fmt_money.py +++ b/frappe/tests/test_fmt_money.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe.utils import fmt_money import unittest diff --git a/frappe/tests/test_form_load.py b/frappe/tests/test_form_load.py index b382fa7381..dd6ccd9bcd 100644 --- a/frappe/tests/test_form_load.py +++ b/frappe/tests/test_form_load.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest from frappe.desk.form.load import getdoctype, getdoc from frappe.core.page.permission_manager.permission_manager import update, reset, add diff --git a/frappe/tests/test_geo_ip.py b/frappe/tests/test_geo_ip.py index b292e43ba5..f085838f37 100644 --- a/frappe/tests/test_geo_ip.py +++ b/frappe/tests/test_geo_ip.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest class TestGeoIP(unittest.TestCase): diff --git a/frappe/tests/test_global_search.py b/frappe/tests/test_global_search.py index 5cffbaaf64..3921af6738 100644 --- a/frappe/tests/test_global_search.py +++ b/frappe/tests/test_global_search.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe diff --git a/frappe/tests/test_goal.py b/frappe/tests/test_goal.py index b4c0736482..5a83baa1af 100644 --- a/frappe/tests/test_goal.py +++ b/frappe/tests/test_goal.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe diff --git a/frappe/tests/test_hooks.py b/frappe/tests/test_hooks.py index ff71e2414c..3f66afe34a 100644 --- a/frappe/tests/test_hooks.py +++ b/frappe/tests/test_hooks.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe from frappe.desk.doctype.todo.todo import ToDo @@ -19,12 +18,12 @@ class TestHooks(unittest.TestCase): def test_override_doctype_class(self): from frappe import hooks - + # Set hook hooks.override_doctype_class = { 'ToDo': ['frappe.tests.test_hooks.CustomToDo'] } - + # Clear cache frappe.cache().delete_value('app_hooks') clear_controller_cache('ToDo') diff --git a/frappe/tests/test_listview.py b/frappe/tests/test_listview.py index 1ef72fdd32..4efb570e7e 100644 --- a/frappe/tests/test_listview.py +++ b/frappe/tests/test_listview.py @@ -1,7 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest import frappe import json diff --git a/frappe/tests/test_monitor.py b/frappe/tests/test_monitor.py index b447e89b06..dbc5fe35e1 100644 --- a/frappe/tests/test_monitor.py +++ b/frappe/tests/test_monitor.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe import frappe.monitor diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 66d48e3612..557993882f 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -1,7 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe from frappe.utils import now_datetime diff --git a/frappe/tests/test_password.py b/frappe/tests/test_password.py index 98141072e2..6a5b948d93 100644 --- a/frappe/tests/test_password.py +++ b/frappe/tests/test_password.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import unittest from frappe.utils.password import update_password, check_password, passlibctx diff --git a/frappe/tests/test_patches.py b/frappe/tests/test_patches.py index ed22afc0af..7f4efc700c 100644 --- a/frappe/tests/test_patches.py +++ b/frappe/tests/test_patches.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import unittest, frappe from frappe.modules import patch_handler diff --git a/frappe/tests/test_pdf.py b/frappe/tests/test_pdf.py index be287e0d92..b67aee7a68 100644 --- a/frappe/tests/test_pdf.py +++ b/frappe/tests/test_pdf.py @@ -1,11 +1,9 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest import frappe.utils.pdf as pdfgen -import frappe, io, six +import frappe, io from PyPDF2 import PdfFileReader #class TestPdfBorders(unittest.TestCase): @@ -44,8 +42,6 @@ class TestPdf(unittest.TestCase): pdf = pdfgen.get_pdf(self.html, options={"password": password}) reader = PdfFileReader(io.BytesIO(pdf)) self.assertTrue(reader.isEncrypted) - if six.PY2: - password = frappe.safe_encode(password) self.assertTrue(reader.decrypt(password)) def test_pdf_generation_as_a_user(self): diff --git a/frappe/tests/test_permissions.py b/frappe/tests/test_permissions.py index 82f0ee920a..ada64156de 100644 --- a/frappe/tests/test_permissions.py +++ b/frappe/tests/test_permissions.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - """Use blog post test to test user permissions logic""" import frappe diff --git a/frappe/tests/test_query_report.py b/frappe/tests/test_query_report.py index eaf4dc7070..3d9791d399 100644 --- a/frappe/tests/test_query_report.py +++ b/frappe/tests/test_query_report.py @@ -1,8 +1,6 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest import frappe diff --git a/frappe/tests/test_rate_limiter.py b/frappe/tests/test_rate_limiter.py index ae1857bb31..71977935a9 100644 --- a/frappe/tests/test_rate_limiter.py +++ b/frappe/tests/test_rate_limiter.py @@ -3,8 +3,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest from werkzeug.wrappers import Response import time diff --git a/frappe/tests/test_recorder.py b/frappe/tests/test_recorder.py index 64d3c52f63..08dbde0144 100644 --- a/frappe/tests/test_recorder.py +++ b/frappe/tests/test_recorder.py @@ -3,7 +3,6 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe import frappe.recorder diff --git a/frappe/tests/test_safe_exec.py b/frappe/tests/test_safe_exec.py index d7b25b8194..79f2c504a4 100644 --- a/frappe/tests/test_safe_exec.py +++ b/frappe/tests/test_safe_exec.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import unittest, frappe from frappe.utils.safe_exec import safe_exec, get_safe_globals diff --git a/frappe/tests/test_scheduler.py b/frappe/tests/test_scheduler.py index d5344c60b5..ec43c08ab7 100644 --- a/frappe/tests/test_scheduler.py +++ b/frappe/tests/test_scheduler.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from unittest import TestCase from dateutil.relativedelta import relativedelta from frappe.core.doctype.scheduled_job_type.scheduled_job_type import sync_jobs diff --git a/frappe/tests/test_search.py b/frappe/tests/test_search.py index e39d6c4691..9ad02f49a6 100644 --- a/frappe/tests/test_search.py +++ b/frappe/tests/test_search.py @@ -1,7 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import unittest import frappe from frappe.desk.search import search_link diff --git a/frappe/tests/test_seen.py b/frappe/tests/test_seen.py index 8eea30d773..7f4e8719a3 100644 --- a/frappe/tests/test_seen.py +++ b/frappe/tests/test_seen.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest, json class TestSeen(unittest.TestCase): diff --git a/frappe/tests/test_sitemap.py b/frappe/tests/test_sitemap.py index 22669000c1..e29a453a14 100644 --- a/frappe/tests/test_sitemap.py +++ b/frappe/tests/test_sitemap.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe, unittest from frappe.utils import get_html_for_route diff --git a/frappe/tests/test_translate.py b/frappe/tests/test_translate.py index c29390c429..f51f31d509 100644 --- a/frappe/tests/test_translate.py +++ b/frappe/tests/test_translate.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest, os import frappe.translate from frappe import _ diff --git a/frappe/tests/test_translation.py b/frappe/tests/test_translation.py index 0e1e6e452c..94af1bb870 100644 --- a/frappe/tests/test_translation.py +++ b/frappe/tests/test_translation.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, unittest, os import frappe.translate diff --git a/frappe/tests/test_twofactor.py b/frappe/tests/test_twofactor.py index 709b88b8f3..7de155bc96 100644 --- a/frappe/tests/test_twofactor.py +++ b/frappe/tests/test_twofactor.py @@ -1,7 +1,5 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest, frappe, pyotp from frappe.auth import HTTPRequest from frappe.utils import cint diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 74ceec8287..c2e5d99731 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest import frappe @@ -56,14 +54,14 @@ class TestMoney(unittest.TestCase): for num in nums_bhd: self.assertEqual( - money_in_words(num[0], "BHD"), - num[1], + money_in_words(num[0], "BHD"), + num[1], "{0} is not the same as {1}".format(money_in_words(num[0], "BHD"), num[1]) ) for num in nums_ngn: self.assertEqual( - money_in_words(num[0], "NGN"), num[1], + money_in_words(num[0], "NGN"), num[1], "{0} is not the same as {1}".format(money_in_words(num[0], "NGN"), num[1]) ) @@ -139,7 +137,7 @@ class TestValidationUtils(unittest.TestCase): # Valid URLs self.assertTrue(validate_url('https://google.com')) self.assertTrue(validate_url('http://frappe.io', throw=True)) - + # Invalid URLs without throw self.assertFalse(validate_url('google.io')) self.assertFalse(validate_url('google.io')) @@ -152,9 +150,9 @@ class TestValidationUtils(unittest.TestCase): self.assertTrue(validate_url('ftp://frappe.cloud', valid_schemes=['https', 'ftp'])) self.assertFalse(validate_url('bolo://frappe.io', valid_schemes=("http", "https", "ftp", "ftps"))) self.assertRaises( - frappe.ValidationError, - validate_url, - 'gopher://frappe.io', + frappe.ValidationError, + validate_url, + 'gopher://frappe.io', valid_schemes='https', throw=True ) @@ -167,16 +165,16 @@ class TestValidationUtils(unittest.TestCase): # Valid addresses self.assertTrue(validate_email_address('someone@frappe.com')) self.assertTrue(validate_email_address('someone@frappe.com, anyone@frappe.io')) - + # Invalid address self.assertFalse(validate_email_address('someone')) self.assertFalse(validate_email_address('someone@----.com')) # Invalid with throw self.assertRaises( - frappe.InvalidEmailAddressError, - validate_email_address, - 'someone.com', + frappe.InvalidEmailAddressError, + validate_email_address, + 'someone.com', throw=True ) diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index dc3862174d..52ddc5ef71 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import unittest import frappe diff --git a/frappe/tests/tests_geo_utils.py b/frappe/tests/tests_geo_utils.py index 2067a6aa97..e928bc0fef 100644 --- a/frappe/tests/tests_geo_utils.py +++ b/frappe/tests/tests_geo_utils.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import unittest import frappe diff --git a/frappe/translate.py b/frappe/translate.py index b9dd5e263a..f95fdad015 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -1,12 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - -from six import iteritems, text_type, string_types, PY2 - -from frappe.utils import cstr - """ frappe.translate ~~~~~~~~~~~~~~~~ @@ -14,10 +7,11 @@ from frappe.utils import cstr Translation tools for frappe """ -import frappe, os, re, io, codecs, json +import frappe, os, re, io, json from frappe.model.utils import render_include, InvalidIncludePath from frappe.utils import strip, strip_html_tags, is_html import itertools, operator +from csv import reader def guess_language(lang_list=None): """Set `frappe.local.lang` from HTTP headers at beginning of request""" @@ -36,8 +30,8 @@ def guess_language(lang_list=None): for l in lang_codes: code = l.strip() - if not isinstance(code, text_type): - code = text_type(code, 'utf-8') + if not isinstance(code, str): + code = str(code, 'utf-8') if code in lang_list or code == "en": guess = code break @@ -127,7 +121,7 @@ def get_dict(fortype, name=None): message_dict = make_dict_from_messages(messages, load_user_translation=False) message_dict.update(get_dict_from_hooks(fortype, name)) # remove untranslated - message_dict = {k:v for k, v in iteritems(message_dict) if k!=v} + message_dict = {k: v for k, v in message_dict.items() if k!=v} translation_assets[asset_key] = message_dict cache.hset("translation_assets", frappe.local.lang, translation_assets, shared=True) @@ -389,7 +383,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, string_types) and fixture == 'Worflow': + if isinstance(fixture, str) and fixture == 'Worflow': workflows = frappe.get_all('Workflow') break elif isinstance(fixture, dict) and fixture.get('dt', fixture.get('doctype')) == 'Workflow': @@ -425,7 +419,7 @@ def get_messages_from_custom_fields(app_name): custom_fields = [] for fixture in fixtures: - if isinstance(fixture, string_types) and fixture == 'Custom Field': + if isinstance(fixture, str) 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': @@ -609,20 +603,11 @@ def read_csv_file(path): """Read CSV file and return as list of list :param path: File path""" - from csv import reader - if PY2: - with codecs.open(path, 'r', 'utf-8') as msgfile: - data = msgfile.read() + with io.open(path, mode='r', encoding='utf-8', newline='') as msgfile: + data = reader(msgfile) + newdata = [[ val for val in row ] for row in data] - # for japanese! #wtf - data = data.replace(chr(28), "").replace(chr(29), "") - data = reader([r.encode('utf-8') for r in data.splitlines()]) - newdata = [[text_type(val, 'utf-8') for val in row] for row in data] - else: - with io.open(path, mode='r', encoding='utf-8', newline='') as msgfile: - data = reader(msgfile) - newdata = [[ val for val in row ] for row in data] return newdata def write_csv_file(path, app_messages, lang_dict): @@ -812,7 +797,7 @@ def update_translations_for_source(source=None, translation_dict=None): frappe.delete_doc('Translation', d.name) # remaining values are to be inserted - for lang, translated_text in iteritems(translation_dict): + for lang, translated_text in translation_dict.items(): doc = frappe.new_doc('Translation') doc.language = lang doc.source_text = source diff --git a/frappe/twofactor.py b/frappe/twofactor.py index 4e098c3075..c2fb6d5de9 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -1,17 +1,13 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals - import frappe from frappe import _ import pyotp, os from frappe.utils.background_jobs import enqueue from pyqrcode import create as qrcreate -from six import BytesIO +from io import BytesIO from base64 import b64encode, b32encode from frappe.utils import get_url, get_datetime, time_diff_in_seconds, cint -from six import iteritems, string_types class ExpiredLoginException(Exception): pass @@ -78,7 +74,7 @@ def cache_2fa_data(user, token, otp_secret, tmp_id): frappe.cache().expire(tmp_id + '_token', expiry_time) else: expiry_time = frappe.flags.otp_expiry or 180 - for k, v in iteritems({'_usr': user, '_pwd': pwd, '_otp_secret': otp_secret}): + for k, v in {'_usr': user, '_pwd': pwd, '_otp_secret': otp_secret}.items(): frappe.cache().set("{0}{1}".format(tmp_id, k), v) frappe.cache().expire("{0}{1}".format(tmp_id, k), expiry_time) @@ -87,7 +83,7 @@ def two_factor_is_enabled_for_(user): if user == "Administrator": return False - if isinstance(user, string_types): + if isinstance(user, str): user = frappe.get_doc('User', user) roles = [frappe.db.escape(d.role) for d in user.roles or []] @@ -393,7 +389,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, string_types): + if isinstance(barcode, str): barcode = frappe.get_doc('File', barcode) lifespan = frappe.db.get_value('System Settings', 'System Settings', 'lifespan_qrcode_image') or 240 if time_diff_in_seconds(get_datetime(), barcode.creation) > int(lifespan): diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 436dcba028..cb02035299 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -739,7 +739,7 @@ def get_safe_filters(filters): try: filters = json.loads(filters) - if isinstance(filters, (integer_types, float)): + if isinstance(filters, (int, float)): filters = frappe.as_unicode(filters) except (TypeError, ValueError): diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index bd1f1154a9..8456835ca7 100755 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals, print_function import redis from rq import Connection, Queue, Worker from rq.logutils import setup_loghandlers @@ -7,11 +6,9 @@ from collections import defaultdict import frappe import os, socket, time from frappe import _ -from six import string_types from uuid import uuid4 import frappe.monitor -# imports - third-party imports default_timeout = 300 queue_timeout = { @@ -89,7 +86,7 @@ def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True, if user: frappe.set_user(user) - if isinstance(method, string_types): + if isinstance(method, str): method_name = method method = frappe.get_attr(method) else: @@ -193,7 +190,7 @@ def get_queue_list(queue_list=None): '''Defines possible queues. Also wraps a given queue in a list after validating.''' default_queue_list = list(queue_timeout) if queue_list: - if isinstance(queue_list, string_types): + if isinstance(queue_list, str): queue_list = [queue_list] for queue in queue_list: diff --git a/frappe/utils/bench_helper.py b/frappe/utils/bench_helper.py index 2fb0bda058..ec08d2a15e 100644 --- a/frappe/utils/bench_helper.py +++ b/frappe/utils/bench_helper.py @@ -1,4 +1,3 @@ -from __future__ import unicode_literals, print_function import click import frappe import os diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index d950d9f082..92150b79cf 100755 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -1,8 +1,5 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe, os, re, git from frappe.utils import touch_file, cstr diff --git a/frappe/utils/bot.py b/frappe/utils/bot.py index 45e1bd5a4e..572723c056 100644 --- a/frappe/utils/bot.py +++ b/frappe/utils/bot.py @@ -1,8 +1,6 @@ # Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe, re, frappe.utils from frappe.desk.notifications import get_notifications from frappe import _ diff --git a/frappe/utils/change_log.py b/frappe/utils/change_log.py index 33801af722..6cb71c6ac5 100644 --- a/frappe/utils/change_log.py +++ b/frappe/utils/change_log.py @@ -7,7 +7,6 @@ import subprocess # nosec import requests from semantic_version import Version -from six.moves import range import frappe from frappe import _, safe_decode diff --git a/frappe/utils/connections.py b/frappe/utils/connections.py index 1f57d8fbae..5640da666c 100644 --- a/frappe/utils/connections.py +++ b/frappe/utils/connections.py @@ -1,6 +1,6 @@ import socket -from six.moves.urllib.parse import urlparse +from urllib.parse import urlparse from frappe import get_conf REDIS_KEYS = ('redis_cache', 'redis_queue', 'redis_socketio') diff --git a/frappe/utils/csvutils.py b/frappe/utils/csvutils.py index 00163ade5f..734d68fe8a 100644 --- a/frappe/utils/csvutils.py +++ b/frappe/utils/csvutils.py @@ -1,14 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals import frappe from frappe import msgprint, _ import json import csv -import six import requests -from six import StringIO, text_type, string_types +from io import StringIO from frappe.utils import encode, cstr, cint, flt, comma_or def read_csv_content_from_uploaded_file(ignore_encoding=False): @@ -40,11 +37,11 @@ def read_csv_content_from_attached_file(doc): def read_csv_content(fcontent, ignore_encoding=False): rows = [] - if not isinstance(fcontent, text_type): + if not isinstance(fcontent, str): decoded = False for encoding in ["utf-8", "windows-1250", "windows-1252"]: try: - fcontent = text_type(fcontent, encoding) + fcontent = str(fcontent, encoding) decoded = True break except UnicodeDecodeError: @@ -56,10 +53,7 @@ def read_csv_content(fcontent, ignore_encoding=False): fcontent = fcontent.encode("utf-8") content = [ ] for line in fcontent.splitlines(True): - if six.PY2: - content.append(line) - else: - content.append(frappe.safe_decode(line)) + content.append(frappe.safe_decode(line)) try: rows = [] @@ -85,7 +79,7 @@ def read_csv_content(fcontent, ignore_encoding=False): @frappe.whitelist() def send_csv_to_client(args): - if isinstance(args, string_types): + if isinstance(args, str): args = json.loads(args) args = frappe._dict(args) @@ -113,8 +107,6 @@ class UnicodeWriter: self.writer = csv.writer(self.queue, quoting=quoting) def writerow(self, row): - if six.PY2: - row = encode(row, self.encoding) self.writer.writerow(row) def getvalue(self): diff --git a/frappe/utils/dashboard.py b/frappe/utils/dashboard.py index e386dcd881..ad61486113 100644 --- a/frappe/utils/dashboard.py +++ b/frappe/utils/dashboard.py @@ -1,6 +1,5 @@ # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from functools import wraps diff --git a/frappe/utils/data.py b/frappe/utils/data.py index a9af30ab2c..09b02a918a 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -1,14 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import operator import json import re, datetime, math, time -from six.moves.urllib.parse import quote, urljoin -from six import iteritems, text_type, string_types, integer_types +from urllib.parse import quote, urljoin from frappe.desk.utils import slug DATE_FORMAT = "%Y-%m-%d" @@ -72,7 +69,7 @@ def get_datetime(datetime_str=None): def to_timedelta(time_str): from dateutil import parser - if isinstance(time_str, string_types): + if isinstance(time_str, str): t = parser.parse(time_str) return datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second, microseconds=t.microsecond) @@ -91,7 +88,7 @@ def add_to_date(date, years=0, months=0, weeks=0, days=0, hours=0, minutes=0, se if hours: as_datetime = True - if isinstance(date, string_types): + if isinstance(date, str): as_string = True if " " in date: as_datetime = True @@ -274,17 +271,17 @@ def get_time(time_str): return parser.parse(time_str).time() def get_datetime_str(datetime_obj): - if isinstance(datetime_obj, string_types): + if isinstance(datetime_obj, str): datetime_obj = get_datetime(datetime_obj) return datetime_obj.strftime(DATETIME_FORMAT) def get_date_str(date_obj): - if isinstance(date_obj, string_types): + if isinstance(date_obj, str): date_obj = get_datetime(date_obj) return date_obj.strftime(DATE_FORMAT) def get_time_str(timedelta_obj): - if isinstance(timedelta_obj, string_types): + if isinstance(timedelta_obj, str): timedelta_obj = to_timedelta(timedelta_obj) hours, remainder = divmod(timedelta_obj.seconds, 3600) @@ -549,7 +546,7 @@ def flt(s, precision=None): >>> flt("a") 0.0 """ - if isinstance(s, string_types): + if isinstance(s, str): s = s.replace(',','') try: @@ -706,12 +703,12 @@ def encode(obj, encoding="utf-8"): if isinstance(obj, list): out = [] for o in obj: - if isinstance(o, text_type): + if isinstance(o, str): out.append(o.encode(encoding)) else: out.append(o) return out - elif isinstance(obj, text_type): + elif isinstance(obj, str): return obj.encode(encoding) else: return obj @@ -719,10 +716,10 @@ def encode(obj, encoding="utf-8"): def parse_val(v): """Converts to simple datatypes from SQL query results""" if isinstance(v, (datetime.date, datetime.datetime)): - v = text_type(v) + v = str(v) elif isinstance(v, datetime.timedelta): - v = ":".join(text_type(v).split(":")[:2]) - elif isinstance(v, integer_types): + v = ":".join(str(v).split(":")[:2]) + elif isinstance(v, int): v = int(v) return v @@ -743,7 +740,7 @@ def fmt_money(amount, precision=None, currency=None, format=None): # 40,000.00000 -> 40,000.00 # 40,000.23000 -> 40,000.23 - if isinstance(amount, string_types): + if isinstance(amount, str): amount = flt(amount, precision) if decimal_str: @@ -959,7 +956,7 @@ def strip_html(text): return _striptags_re.sub("", text) def escape_html(text): - if not isinstance(text, string_types): + if not isinstance(text, str): return text html_escape_table = { @@ -982,7 +979,7 @@ def pretty_date(iso_datetime): if not iso_datetime: return '' import math - if isinstance(iso_datetime, string_types): + if isinstance(iso_datetime, str): iso_datetime = datetime.datetime.strptime(iso_datetime, DATETIME_FORMAT) now_dt = datetime.datetime.strptime(now(), DATETIME_FORMAT) dt_diff = now_dt - iso_datetime @@ -1031,7 +1028,7 @@ def comma_and(some_list ,add_quotes=True): def comma_sep(some_list, pattern, add_quotes=True): if isinstance(some_list, (list, tuple)): # list(some_list) is done to preserve the existing list - some_list = [text_type(s) for s in list(some_list)] + some_list = [str(s) for s in list(some_list)] if not some_list: return "" elif len(some_list) == 1: @@ -1045,7 +1042,7 @@ def comma_sep(some_list, pattern, add_quotes=True): def new_line_sep(some_list): if isinstance(some_list, (list, tuple)): # list(some_list) is done to preserve the existing list - some_list = [text_type(s) for s in list(some_list)] + some_list = [str(s) for s in list(some_list)] if not some_list: return "" elif len(some_list) == 1: @@ -1131,7 +1128,7 @@ def get_link_to_report(name, label=None, report_type=None, doctype=None, filters if filters: conditions = [] - for k,v in iteritems(filters): + for k,v in filters.items(): if isinstance(v, list): for value in v: conditions.append(str(k)+'='+'["'+str(value[0]+'"'+','+'"'+str(value[1])+'"]')) @@ -1187,7 +1184,7 @@ operator_map = { def evaluate_filters(doc, filters): '''Returns true if doc matches filters''' if isinstance(filters, dict): - for key, value in iteritems(filters): + for key, value in filters.items(): f = get_filter(None, {key:value}) if not compare(doc.get(f.fieldname), f.operator, f.value, f.fieldtype): return False @@ -1375,7 +1372,7 @@ def strip(val, chars=None): def to_markdown(html): from html2text import html2text - from six.moves import html_parser as HTMLParser + from html.parser import HTMLParser text = None try: @@ -1514,7 +1511,7 @@ def get_user_info_for_avatar(user_id): return user_info -class UnicodeWithAttrs(text_type): +class UnicodeWithAttrs(str): def __init__(self, text): self.toc_html = text.toc_html self.metadata = text.metadata diff --git a/frappe/utils/dateutils.py b/frappe/utils/dateutils.py index 06b434a512..2c2537da5f 100644 --- a/frappe/utils/dateutils.py +++ b/frappe/utils/dateutils.py @@ -1,14 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import frappe.defaults import datetime from frappe.utils import get_datetime, add_to_date, getdate from frappe.utils.data import get_first_day, get_first_day_of_week, get_quarter_start, get_year_start,\ get_last_day, get_last_day_of_week, get_quarter_ending, get_year_ending -from six import string_types # global values -- used for caching dateformats = { @@ -71,7 +69,7 @@ def get_user_date_format(): def datetime_in_user_format(date_time): if not date_time: return "" - if isinstance(date_time, string_types): + if isinstance(date_time, str): date_time = get_datetime(date_time) from frappe.utils import formatdate return formatdate(date_time.date()) + " " + date_time.strftime("%H:%M") diff --git a/frappe/utils/doctor.py b/frappe/utils/doctor.py index e97f792b88..9dafc4dd21 100644 --- a/frappe/utils/doctor.py +++ b/frappe/utils/doctor.py @@ -1,10 +1,8 @@ -from __future__ import unicode_literals, print_function import frappe.utils from collections import defaultdict from rq import Worker, Connection from frappe.utils.background_jobs import get_redis_conn, get_queue, get_queue_list from frappe.utils.scheduler import is_scheduler_disabled, is_scheduler_inactive -from six import iteritems def get_workers(): @@ -130,7 +128,7 @@ def doctor(site=None): print("Queue:", queue) print("Number of Jobs: ", job_count[queue]) print("Methods:") - for method, count in iteritems(jobs_per_queue[queue]): + for method, count in jobs_per_queue[queue].items(): print("{0} : {1}".format(method, count)) print("------------") diff --git a/frappe/utils/error.py b/frappe/utils/error.py index 2d8d6491a5..61905b4985 100644 --- a/frappe/utils/error.py +++ b/frappe/utils/error.py @@ -2,8 +2,6 @@ # Copyright (c) 2015, Maxwell Morais and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import os import sys import traceback @@ -17,7 +15,7 @@ import pydoc import cgitb import datetime import json -import six + def make_error_snapshot(exception): if frappe.conf.disable_error_snapshot: @@ -51,7 +49,7 @@ def get_snapshot(exception, context=10): """ etype, evalue, etb = sys.exc_info() - if isinstance(etype, six.class_types): + if isinstance(etype, type): etype = etype.__name__ # creates a snapshot dict with some basic information @@ -131,7 +129,7 @@ def get_snapshot(exception, context=10): # add all local values (of last frame) to the snapshot for name, value in locals.items(): - s['locals'][name] = value if isinstance(value, six.text_type) else pydoc.text.repr(value) + s['locals'][name] = value if isinstance(value, str) else pydoc.text.repr(value) return s diff --git a/frappe/utils/file_lock.py b/frappe/utils/file_lock.py index b85ace7db9..8c65dd32ce 100644 --- a/frappe/utils/file_lock.py +++ b/frappe/utils/file_lock.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - ''' File based locking utility ''' diff --git a/frappe/utils/file_manager.py b/frappe/utils/file_manager.py index 2177e67274..30b0d816bb 100644 --- a/frappe/utils/file_manager.py +++ b/frappe/utils/file_manager.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import os, base64, re, json import hashlib @@ -11,8 +10,7 @@ from frappe.utils import get_hook_method, get_files_path, random_string, encode, from frappe import _ from frappe import conf from copy import copy -from six.moves.urllib.parse import unquote -from six import text_type, PY2, string_types +from urllib.parse import unquote class MaxFileSizeReachedError(frappe.ValidationError): @@ -123,7 +121,7 @@ def get_uploaded_content(): def save_file(fname, content, dt, dn, folder=None, decode=False, is_private=0, df=None): if decode: - if isinstance(content, text_type): + if isinstance(content, str): content = content.encode("utf-8") if b"," in content: @@ -207,7 +205,7 @@ def write_file(content, fname, is_private=0): # create directory (if not exists) frappe.create_folder(file_path) # write the file - if isinstance(content, text_type): + if isinstance(content, str): content = content.encode() with open(os.path.join(file_path.encode('utf-8'), fname.encode('utf-8')), 'wb+') as f: f.write(content) @@ -297,18 +295,14 @@ def get_file(fname): file_path = get_file_path(fname) # read the file - if PY2: - with open(encode(file_path)) as f: - content = f.read() - else: - with io.open(encode(file_path), mode='rb') as f: - content = f.read() - try: - # for plain text files - content = content.decode() - except UnicodeDecodeError: - # for .png, .jpg, etc - pass + with io.open(encode(file_path), mode='rb') as f: + content = f.read() + try: + # for plain text files + content = content.decode() + except UnicodeDecodeError: + # for .png, .jpg, etc + pass return [file_path.rsplit("/", 1)[-1], content] @@ -338,7 +332,7 @@ def get_file_path(file_name): def get_content_hash(content): - if isinstance(content, text_type): + if isinstance(content, str): content = content.encode() return hashlib.md5(content).hexdigest() @@ -397,8 +391,8 @@ def extract_images_from_html(doc, content): filename = headers.split("filename=")[-1] # decode filename - if not isinstance(filename, text_type): - filename = text_type(filename, 'utf-8') + if not isinstance(filename, str): + filename = str(filename, 'utf-8') else: mtype = headers.split(";")[0] filename = get_random_filename(content_type=mtype) @@ -443,12 +437,12 @@ def validate_filename(filename): @frappe.whitelist() def add_attachments(doctype, name, attachments): '''Add attachments to the given DocType''' - if isinstance(attachments, string_types): + if isinstance(attachments, str): attachments = json.loads(attachments) # loop through attachments files =[] for a in attachments: - if isinstance(a, string_types): + if isinstance(a, str): attach = frappe.db.get_value("File", {"name":a}, ["file_name", "file_url", "is_private"], as_dict=1) # save attachments to new doc f = save_url(attach.file_url, attach.file_name, doctype, name, "Home/Attachments", attach.is_private) diff --git a/frappe/utils/formatters.py b/frappe/utils/formatters.py index 7913413878..9efccc15f0 100644 --- a/frappe/utils/formatters.py +++ b/frappe/utils/formatters.py @@ -1,18 +1,16 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import datetime from frappe.utils import formatdate, fmt_money, flt, cstr, cint, format_datetime, format_time, format_duration 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, string_types): + if isinstance(df, str): df = frappe._dict(fieldtype=df) if not df: diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py index c20f3b29d4..3cf10cd9e0 100644 --- a/frappe/utils/global_search.py +++ b/frappe/utils/global_search.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals - import frappe import re import redis @@ -11,7 +9,6 @@ import os from frappe.utils import cint, strip_html_tags from frappe.utils.html_utils import unescape_html from frappe.model.base_document import get_controller -from six import text_type def setup_global_search_table(): """ @@ -348,9 +345,9 @@ def get_formatted_value(value, field): if getattr(field, 'fieldtype', None) in ["Text", "Text Editor"]: value = unescape_html(frappe.safe_decode(value)) - value = (re.subn(r'(?s)<[\s]*(script|style).*?', '', text_type(value))[0]) + value = (re.subn(r'(?s)<[\s]*(script|style).*?', '', str(value))[0]) value = ' '.join(value.split()) - return field.label + " : " + strip_html_tags(text_type(value)) + return field.label + " : " + strip_html_tags(str(value)) def sync_global_search(): diff --git a/frappe/utils/goal.py b/frappe/utils/goal.py index 4c63eb9fc4..195c962aab 100644 --- a/frappe/utils/goal.py +++ b/frappe/utils/goal.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/utils/html_utils.py b/frappe/utils/html_utils.py index f3f86dcad2..24def07c63 100644 --- a/frappe/utils/html_utils.py +++ b/frappe/utils/html_utils.py @@ -1,14 +1,13 @@ -from __future__ import unicode_literals + import frappe import json import re import bleach_whitelist.bleach_whitelist as bleach_whitelist -from six import string_types def clean_html(html): import bleach - if not isinstance(html, string_types): + if not isinstance(html, str): return html return bleach.clean(clean_script_and_style(html), @@ -21,7 +20,7 @@ def clean_html(html): def clean_email_html(html): import bleach - if not isinstance(html, string_types): + if not isinstance(html, str): return html return bleach.clean(clean_script_and_style(html), @@ -60,7 +59,7 @@ def sanitize_html(html, linkify=False): import bleach from bs4 import BeautifulSoup - if not isinstance(html, string_types): + if not isinstance(html, str): return html elif is_json(html): diff --git a/frappe/utils/identicon.py b/frappe/utils/identicon.py index 328fb03836..e570875b4a 100644 --- a/frappe/utils/identicon.py +++ b/frappe/utils/identicon.py @@ -1,9 +1,9 @@ -from __future__ import unicode_literals + from PIL import Image, ImageDraw from hashlib import md5 import base64 import random -from six import StringIO +from io import StringIO GRID_SIZE = 5 BORDER_SIZE = 20 diff --git a/frappe/utils/image.py b/frappe/utils/image.py index 60595464a1..b6f4c67c44 100644 --- a/frappe/utils/image.py +++ b/frappe/utils/image.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function import os def resize_images(path, maxdim=700): @@ -24,7 +22,7 @@ def strip_exif_data(content, content_type): Works by creating a new Image object which ignores exif by default and then extracts the binary data back into content. - Returns: + Returns: Bytes: Stripped image content """ @@ -33,11 +31,11 @@ def strip_exif_data(content, content_type): original_image = Image.open(io.BytesIO(content)) output = io.BytesIO() - + new_image = Image.new(original_image.mode, original_image.size) new_image.putdata(list(original_image.getdata())) new_image.save(output, format=content_type.split('/')[1]) - + content = output.getvalue() return content \ No newline at end of file diff --git a/frappe/utils/install.py b/frappe/utils/install.py index 93f46a2a16..91d8f04eb4 100644 --- a/frappe/utils/install.py +++ b/frappe/utils/install.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - import frappe import getpass from frappe.utils.password import update_password diff --git a/frappe/utils/jinja.py b/frappe/utils/jinja.py index a77eca4977..685208e71f 100644 --- a/frappe/utils/jinja.py +++ b/frappe/utils/jinja.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - def get_jenv(): import frappe from frappe.utils.safe_exec import get_safe_globals diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py index 347d52dc57..e24dff05f1 100644 --- a/frappe/utils/jinja_globals.py +++ b/frappe/utils/jinja_globals.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals from frappe.utils.jinja import get_jenv diff --git a/frappe/utils/logger.py b/frappe/utils/logger.py index 364ffa776d..617572deb7 100755 --- a/frappe/utils/logger.py +++ b/frappe/utils/logger.py @@ -1,13 +1,9 @@ -# imports - compatibility imports -from __future__ import unicode_literals - # imports - standard imports import logging import os from logging.handlers import RotatingFileHandler # imports - third party imports -from six import text_type # imports - module imports import frappe @@ -83,10 +79,10 @@ class SiteContextFilter(logging.Filter): """This is a filter which injects request information (if available) into the log.""" def filter(self, record): - if "Form Dict" not in text_type(record.msg): + if "Form Dict" not in str(record.msg): site = getattr(frappe.local, "site", None) form_dict = getattr(frappe.local, "form_dict", None) - record.msg = text_type(record.msg) + "\nSite: {0}\nForm Dict: {1}".format(site, form_dict) + record.msg = str(record.msg) + "\nSite: {0}\nForm Dict: {1}".format(site, form_dict) return True diff --git a/frappe/utils/make_random.py b/frappe/utils/make_random.py index ad353dea84..2ebabb78f9 100644 --- a/frappe/utils/make_random.py +++ b/frappe/utils/make_random.py @@ -1,7 +1,5 @@ -from __future__ import unicode_literals + import frappe, random -from six.moves import range -from six import string_types settings = frappe._dict( prob = { @@ -17,7 +15,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], string_types): + if isinstance(val[0], str): d[key] = get_random(*val) else: d[key] = random.randrange(*val) diff --git a/frappe/utils/minify.py b/frappe/utils/minify.py index 08d05c7225..b2cc93e554 100644 --- a/frappe/utils/minify.py +++ b/frappe/utils/minify.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + # This code is original from jsmin by Douglas Crockford, it was translated to # Python by Baruch Even. The original code had the following copyright and # license. @@ -29,7 +29,7 @@ from __future__ import unicode_literals # SOFTWARE. # */ -from six import StringIO +from io import StringIO def jsmin(js): ins = StringIO(js) diff --git a/frappe/utils/momentjs.py b/frappe/utils/momentjs.py index 3c5ec91f63..18df9903a7 100644 --- a/frappe/utils/momentjs.py +++ b/frappe/utils/momentjs.py @@ -1,5 +1,4 @@ # get data for moment.js -from __future__ import unicode_literals def update(tz, out): ltz = data["links"].get(tz, tz) zone = data["zones"].get(ltz) diff --git a/frappe/utils/nestedset.py b/frappe/utils/nestedset.py index 531699db0c..3c024c40e4 100644 --- a/frappe/utils/nestedset.py +++ b/frappe/utils/nestedset.py @@ -10,8 +10,6 @@ # 3. call update_nsm(doc_obj) in the on_upate method # ------------------------------------------ -from __future__ import unicode_literals - import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/utils/oauth.py b/frappe/utils/oauth.py index 6a92737a0d..45cce737e1 100644 --- a/frappe/utils/oauth.py +++ b/frappe/utils/oauth.py @@ -1,14 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import frappe.utils import json, jwt import base64 from frappe import _ from frappe.utils.password import get_decrypted_password -from six import string_types class SignupDisabledError(frappe.PermissionError): pass @@ -163,10 +161,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, string_types): + if isinstance(data, str): data = json.loads(data) - if isinstance(state, string_types): + if isinstance(state, str): state = base64.b64decode(state) state = json.loads(state.decode("utf-8")) diff --git a/frappe/utils/password.py b/frappe/utils/password.py index fbed3cd8e7..005a3cede6 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import string import frappe from frappe import _ diff --git a/frappe/utils/password_strength.py b/frappe/utils/password_strength.py index a4182d1cab..3959d8c3dd 100644 --- a/frappe/utils/password_strength.py +++ b/frappe/utils/password_strength.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - try: from zxcvbn import zxcvbn except Exception: diff --git a/frappe/utils/pdf.py b/frappe/utils/pdf.py index 70464aafc5..92459abc46 100644 --- a/frappe/utils/pdf.py +++ b/frappe/utils/pdf.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import io import os import re @@ -9,7 +7,6 @@ from distutils.version import LooseVersion import subprocess import pdfkit -import six from bs4 import BeautifulSoup from PyPDF2 import PdfFileReader, PdfFileWriter @@ -57,8 +54,6 @@ def get_pdf(html, options=None, output=None): if "password" in options: password = options["password"] - if six.PY2: - password = frappe.safe_encode(password) if output: output.appendPagesFromReader(reader) diff --git a/frappe/utils/print_format.py b/frappe/utils/print_format.py index e83a5f6c71..6cf2ecc304 100644 --- a/frappe/utils/print_format.py +++ b/frappe/utils/print_format.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe, os from frappe import _ diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index 678a61ca6e..41aa4e7ad1 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -1,11 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - -import redis, frappe, re -from six.moves import cPickle as pickle +import redis, frappe, re, pickle from frappe.utils import cstr -from six import iteritems class RedisWrapper(redis.Redis): @@ -165,8 +161,10 @@ class RedisWrapper(redis.Redis): pass def hgetall(self, name): - return {key: pickle.loads(value) for key, value in - iteritems(super(RedisWrapper, self).hgetall(self.make_key(name)))} + value = super(RedisWrapper, self).hgetall(self.make_key(name)) + return { + key: pickle.loads(value) for key, value in value.items() + } def hget(self, name, key, generator=None, shared=False): _name = self.make_key(name, shared=shared) diff --git a/frappe/utils/reset_doc.py b/frappe/utils/reset_doc.py index 2119df5897..15aff4dc6c 100755 --- a/frappe/utils/reset_doc.py +++ b/frappe/utils/reset_doc.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe import json, os from frappe.modules import scrub, get_module_path, utils @@ -7,7 +7,7 @@ from frappe.custom.doctype.property_setter.property_setter import make_property_ from frappe.custom.doctype.custom_field.custom_field import create_custom_field from frappe.core.page.permission_manager.permission_manager import get_standard_permissions from frappe.permissions import setup_custom_perms -from six.moves.urllib.request import urlopen +from urllib.request import urlopen branch = 'develop' diff --git a/frappe/utils/response.py b/frappe/utils/response.py index b152d69d8d..84f30f22fd 100644 --- a/frappe/utils/response.py +++ b/frappe/utils/response.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import json import datetime import decimal @@ -18,8 +17,7 @@ from werkzeug.wsgi import wrap_file from werkzeug.wrappers import Response from werkzeug.exceptions import NotFound, Forbidden from frappe.utils import cint -from six import text_type -from six.moves.urllib.parse import quote +from urllib.parse import quote from frappe.core.doctype.access_log.access_log import make_access_log @@ -125,13 +123,13 @@ def json_handler(obj): import collections.abc if isinstance(obj, (datetime.date, datetime.timedelta, datetime.datetime)): - return text_type(obj) + return str(obj) elif isinstance(obj, decimal.Decimal): return float(obj) elif isinstance(obj, LocalProxy): - return text_type(obj) + return str(obj) elif isinstance(obj, frappe.model.document.BaseDocument): doc = obj.as_dict(no_nulls=True) diff --git a/frappe/utils/scheduler.py b/frappe/utils/scheduler.py index 749a41682f..0bfc50eab5 100755 --- a/frappe/utils/scheduler.py +++ b/frappe/utils/scheduler.py @@ -7,8 +7,6 @@ Events: monthly weekly """ -# imports - compatibility imports -from __future__ import print_function, unicode_literals # imports - standard imports import os diff --git a/frappe/utils/testutils.py b/frappe/utils/testutils.py index 4af3ad647c..c451d090f1 100644 --- a/frappe/utils/testutils.py +++ b/frappe/utils/testutils.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe def add_custom_field(doctype, fieldname, fieldtype='Data', options=None): diff --git a/frappe/utils/user.py b/frappe/utils/user.py index 61b698db9f..fe768c28c5 100755 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, json from frappe import _dict import frappe.share diff --git a/frappe/utils/verified_command.py b/frappe/utils/verified_command.py index 971c0a243c..4b038b88c3 100644 --- a/frappe/utils/verified_command.py +++ b/frappe/utils/verified_command.py @@ -1,20 +1,17 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals import hmac, hashlib -from six.moves.urllib.parse import urlencode +from urllib.parse import urlencode 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, string_types): + if not isinstance(params, str): params = urlencode(params) signature = hmac.new(params.encode(), digestmod=hashlib.md5) diff --git a/frappe/website/context.py b/frappe/website/context.py index c898d39869..8278edb958 100644 --- a/frappe/website/context.py +++ b/frappe/website/context.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, os, json from frappe.website.doctype.website_settings.website_settings import get_website_settings diff --git a/frappe/website/doctype/__init__.py b/frappe/website/doctype/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/website/doctype/__init__.py +++ b/frappe/website/doctype/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/website/doctype/about_us_settings/about_us_settings.py b/frappe/website/doctype/about_us_settings/about_us_settings.py index 5b93cdcede..938a8de1b9 100644 --- a/frappe/website/doctype/about_us_settings/about_us_settings.py +++ b/frappe/website/doctype/about_us_settings/about_us_settings.py @@ -3,17 +3,16 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document class AboutUsSettings(Document): - + def on_update(self): from frappe.website.render import clear_cache clear_cache("about") - + def get_args(): obj = frappe.get_doc("About Us Settings") return { diff --git a/frappe/website/doctype/about_us_settings/test_about_us_settings.py b/frappe/website/doctype/about_us_settings/test_about_us_settings.py index 85173a20e5..ab47505fb1 100644 --- a/frappe/website/doctype/about_us_settings/test_about_us_settings.py +++ b/frappe/website/doctype/about_us_settings/test_about_us_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/about_us_team_member/about_us_team_member.py b/frappe/website/doctype/about_us_team_member/about_us_team_member.py index a872a6e5e2..864b6a3e81 100644 --- a/frappe/website/doctype/about_us_team_member/about_us_team_member.py +++ b/frappe/website/doctype/about_us_team_member/about_us_team_member.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/blog_category/blog_category.py b/frappe/website/doctype/blog_category/blog_category.py index 375ba5b6a3..91b213744f 100644 --- a/frappe/website/doctype/blog_category/blog_category.py +++ b/frappe/website/doctype/blog_category/blog_category.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals from frappe.website.website_generator import WebsiteGenerator from frappe.website.render import clear_cache diff --git a/frappe/website/doctype/blog_category/test_blog_category.py b/frappe/website/doctype/blog_category/test_blog_category.py index fe8f4544cd..d9093e76f0 100644 --- a/frappe/website/doctype/blog_category/test_blog_category.py +++ b/frappe/website/doctype/blog_category/test_blog_category.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/website/doctype/blog_post/blog_post.py b/frappe/website/doctype/blog_post/blog_post.py index bfccc0bbc7..b39b7c7d04 100644 --- a/frappe/website/doctype/blog_post/blog_post.py +++ b/frappe/website/doctype/blog_post/blog_post.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe import _ from frappe.website.website_generator import WebsiteGenerator diff --git a/frappe/website/doctype/blog_post/test_blog_post.py b/frappe/website/doctype/blog_post/test_blog_post.py index 9ecac07ee5..99acf2b710 100644 --- a/frappe/website/doctype/blog_post/test_blog_post.py +++ b/frappe/website/doctype/blog_post/test_blog_post.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import unittest from bs4 import BeautifulSoup diff --git a/frappe/website/doctype/blog_settings/blog_settings.py b/frappe/website/doctype/blog_settings/blog_settings.py index 0ed98b9b87..01e18931a3 100644 --- a/frappe/website/doctype/blog_settings/blog_settings.py +++ b/frappe/website/doctype/blog_settings/blog_settings.py @@ -3,13 +3,12 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document class BlogSettings(Document): - + def on_update(self): from frappe.website.render import clear_cache clear_cache("blog") diff --git a/frappe/website/doctype/blog_settings/test_blog_settings.py b/frappe/website/doctype/blog_settings/test_blog_settings.py index e4ddb85c4b..6b03ab88d9 100644 --- a/frappe/website/doctype/blog_settings/test_blog_settings.py +++ b/frappe/website/doctype/blog_settings/test_blog_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/blogger/blogger.py b/frappe/website/doctype/blogger/blogger.py index cbba6a98a5..77e7a6e7a1 100644 --- a/frappe/website/doctype/blogger/blogger.py +++ b/frappe/website/doctype/blogger/blogger.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/website/doctype/blogger/test_blogger.py b/frappe/website/doctype/blogger/test_blogger.py index 77ade561fb..f121859cbb 100644 --- a/frappe/website/doctype/blogger/test_blogger.py +++ b/frappe/website/doctype/blogger/test_blogger.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe test_records = frappe.get_test_records('Blogger') \ No newline at end of file diff --git a/frappe/website/doctype/color/color.py b/frappe/website/doctype/color/color.py index 245b9e9165..080e51e406 100644 --- a/frappe/website/doctype/color/color.py +++ b/frappe/website/doctype/color/color.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/color/test_color.py b/frappe/website/doctype/color/test_color.py index 2f2be331ad..99e4310a1c 100644 --- a/frappe/website/doctype/color/test_color.py +++ b/frappe/website/doctype/color/test_color.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/company_history/company_history.py b/frappe/website/doctype/company_history/company_history.py index 2c3c81a898..128aefe636 100644 --- a/frappe/website/doctype/company_history/company_history.py +++ b/frappe/website/doctype/company_history/company_history.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/contact_us_settings/contact_us_settings.py b/frappe/website/doctype/contact_us_settings/contact_us_settings.py index 24e9811a47..12e62f8403 100644 --- a/frappe/website/doctype/contact_us_settings/contact_us_settings.py +++ b/frappe/website/doctype/contact_us_settings/contact_us_settings.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/help_article/help_article.py b/frappe/website/doctype/help_article/help_article.py index fa26cfef99..139fced70a 100644 --- a/frappe/website/doctype/help_article/help_article.py +++ b/frappe/website/doctype/help_article/help_article.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Frappe and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.website.website_generator import WebsiteGenerator from frappe.utils import is_markdown, markdown, cint diff --git a/frappe/website/doctype/help_article/test_help_article.py b/frappe/website/doctype/help_article/test_help_article.py index e20a3a20e3..a1a0a59a24 100644 --- a/frappe/website/doctype/help_article/test_help_article.py +++ b/frappe/website/doctype/help_article/test_help_article.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/website/doctype/help_category/help_category.py b/frappe/website/doctype/help_category/help_category.py index 59df82b90c..912c1f568e 100644 --- a/frappe/website/doctype/help_category/help_category.py +++ b/frappe/website/doctype/help_category/help_category.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Frappe and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.website.website_generator import WebsiteGenerator from frappe.website.doctype.help_article.help_article import clear_cache diff --git a/frappe/website/doctype/help_category/test_help_category.py b/frappe/website/doctype/help_category/test_help_category.py index 9954e7424e..68fcbd2872 100644 --- a/frappe/website/doctype/help_category/test_help_category.py +++ b/frappe/website/doctype/help_category/test_help_category.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/website/doctype/personal_data_deletion_request/test_personal_data_deletion_request.py b/frappe/website/doctype/personal_data_deletion_request/test_personal_data_deletion_request.py index 1bc90daf1c..606e5aad34 100644 --- a/frappe/website/doctype/personal_data_deletion_request/test_personal_data_deletion_request.py +++ b/frappe/website/doctype/personal_data_deletion_request/test_personal_data_deletion_request.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.website.doctype.personal_data_deletion_request.personal_data_deletion_request import ( diff --git a/frappe/website/doctype/personal_data_deletion_step/personal_data_deletion_step.py b/frappe/website/doctype/personal_data_deletion_step/personal_data_deletion_step.py index 2a7451473d..7cd1277f6c 100644 --- a/frappe/website/doctype/personal_data_deletion_step/personal_data_deletion_step.py +++ b/frappe/website/doctype/personal_data_deletion_step/personal_data_deletion_step.py @@ -2,7 +2,6 @@ # Copyright (c) 2021, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py b/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py index 46faeb8539..9255adb8c2 100644 --- a/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py +++ b/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe import json from frappe import _ diff --git a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py index 6eb381e7ce..563b6b3843 100644 --- a/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py +++ b/frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest import json diff --git a/frappe/website/doctype/portal_menu_item/portal_menu_item.py b/frappe/website/doctype/portal_menu_item/portal_menu_item.py index 5fe8e9fcd7..5effb3a195 100644 --- a/frappe/website/doctype/portal_menu_item/portal_menu_item.py +++ b/frappe/website/doctype/portal_menu_item/portal_menu_item.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/portal_settings/portal_settings.py b/frappe/website/doctype/portal_settings/portal_settings.py index 1bfbc70d60..589656bbf0 100644 --- a/frappe/website/doctype/portal_settings/portal_settings.py +++ b/frappe/website/doctype/portal_settings/portal_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/portal_settings/test_portal_settings.py b/frappe/website/doctype/portal_settings/test_portal_settings.py index 3dd4aa0c35..40f6eaac2c 100644 --- a/frappe/website/doctype/portal_settings/test_portal_settings.py +++ b/frappe/website/doctype/portal_settings/test_portal_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/social_link_settings/social_link_settings.py b/frappe/website/doctype/social_link_settings/social_link_settings.py index b382afac99..093a21ea10 100644 --- a/frappe/website/doctype/social_link_settings/social_link_settings.py +++ b/frappe/website/doctype/social_link_settings/social_link_settings.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/top_bar_item/__init__.py b/frappe/website/doctype/top_bar_item/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/website/doctype/top_bar_item/__init__.py +++ b/frappe/website/doctype/top_bar_item/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/website/doctype/top_bar_item/top_bar_item.py b/frappe/website/doctype/top_bar_item/top_bar_item.py index 6cda8e2beb..14e579dae2 100644 --- a/frappe/website/doctype/top_bar_item/top_bar_item.py +++ b/frappe/website/doctype/top_bar_item/top_bar_item.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/web_form/test_web_form.py b/frappe/website/doctype/web_form/test_web_form.py index 78f7fd6337..5ea18ed7cc 100644 --- a/frappe/website/doctype/web_form/test_web_form.py +++ b/frappe/website/doctype/web_form/test_web_form.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest, json diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index f78aaac934..213c2a84dd 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -1,14 +1,8 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import json import os - -from six import iteritems -from six.moves.urllib.parse import urlencode - import frappe from frappe import _, scrub from frappe.core.doctype.file.file import get_max_file_size, remove_file_by_url @@ -109,9 +103,7 @@ class WebForm(WebsiteGenerator): # py if not os.path.exists(path + '.py'): with open(path + '.py', 'w') as f: - f.write("""from __future__ import unicode_literals - -import frappe + f.write("""import frappe def get_context(context): # do your magic here @@ -219,7 +211,7 @@ def get_context(context): from decimal import Decimal if amount is None or Decimal(amount) <= 0: return frappe.utils.get_url(self.success_url or self.route) - + payment_details = { "amount": amount, "title": title, diff --git a/frappe/website/doctype/web_form_field/web_form_field.py b/frappe/website/doctype/web_form_field/web_form_field.py index ec3c3fbea4..44005d27e3 100644 --- a/frappe/website/doctype/web_form_field/web_form_field.py +++ b/frappe/website/doctype/web_form_field/web_form_field.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/web_page/__init__.py b/frappe/website/doctype/web_page/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/website/doctype/web_page/__init__.py +++ b/frappe/website/doctype/web_page/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index 7a2ddc6961..5dc2c9ff45 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import unittest import frappe from frappe.website.router import resolve_route diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index cce00564ff..cea14d3bbe 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import print_function, unicode_literals - import re import requests diff --git a/frappe/website/doctype/web_page_block/web_page_block.py b/frappe/website/doctype/web_page_block/web_page_block.py index 7561e55aa9..77e7dec155 100644 --- a/frappe/website/doctype/web_page_block/web_page_block.py +++ b/frappe/website/doctype/web_page_block/web_page_block.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - # import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/web_page_view/test_web_page_view.py b/frappe/website/doctype/web_page_view/test_web_page_view.py index d51727ec68..c3d05fcaab 100644 --- a/frappe/website/doctype/web_page_view/test_web_page_view.py +++ b/frappe/website/doctype/web_page_view/test_web_page_view.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/web_page_view/web_page_view.py b/frappe/website/doctype/web_page_view/web_page_view.py index d9794c6d99..e679b58043 100644 --- a/frappe/website/doctype/web_page_view/web_page_view.py +++ b/frappe/website/doctype/web_page_view/web_page_view.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/web_template/test_web_template.py b/frappe/website/doctype/web_template/test_web_template.py index b4ea9e2f97..45e35c4626 100644 --- a/frappe/website/doctype/web_template/test_web_template.py +++ b/frappe/website/doctype/web_template/test_web_template.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from bs4 import BeautifulSoup diff --git a/frappe/website/doctype/web_template/web_template.py b/frappe/website/doctype/web_template/web_template.py index 2fd5bfa179..891a0c3679 100644 --- a/frappe/website/doctype/web_template/web_template.py +++ b/frappe/website/doctype/web_template/web_template.py @@ -2,8 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals - import os from shutil import rmtree diff --git a/frappe/website/doctype/web_template_field/test_web_template_field.py b/frappe/website/doctype/web_template_field/test_web_template_field.py index 40f5d7a1cc..5628da37db 100644 --- a/frappe/website/doctype/web_template_field/test_web_template_field.py +++ b/frappe/website/doctype/web_template_field/test_web_template_field.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/web_template_field/web_template_field.py b/frappe/website/doctype/web_template_field/web_template_field.py index 8c25b619b6..8270ac7845 100644 --- a/frappe/website/doctype/web_template_field/web_template_field.py +++ b/frappe/website/doctype/web_template_field/web_template_field.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_meta_tag/website_meta_tag.py b/frappe/website/doctype/website_meta_tag/website_meta_tag.py index 2972e6d317..0856440663 100644 --- a/frappe/website/doctype/website_meta_tag/website_meta_tag.py +++ b/frappe/website/doctype/website_meta_tag/website_meta_tag.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_route_meta/test_website_route_meta.py b/frappe/website/doctype/website_route_meta/test_website_route_meta.py index 0ccedb0ca4..1f927abafc 100644 --- a/frappe/website/doctype/website_route_meta/test_website_route_meta.py +++ b/frappe/website/doctype/website_route_meta/test_website_route_meta.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.utils import set_request diff --git a/frappe/website/doctype/website_route_meta/website_route_meta.py b/frappe/website/doctype/website_route_meta/website_route_meta.py index f31784e9bc..78d440a1a1 100644 --- a/frappe/website/doctype/website_route_meta/website_route_meta.py +++ b/frappe/website/doctype/website_route_meta/website_route_meta.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class WebsiteRouteMeta(Document): diff --git a/frappe/website/doctype/website_route_redirect/website_route_redirect.py b/frappe/website/doctype/website_route_redirect/website_route_redirect.py index 7255008dd0..f721ab81cb 100644 --- a/frappe/website/doctype/website_route_redirect/website_route_redirect.py +++ b/frappe/website/doctype/website_route_redirect/website_route_redirect.py @@ -2,7 +2,6 @@ # Copyright (c) 2019, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_script/website_script.py b/frappe/website/doctype/website_script/website_script.py index 5648c27fd6..111beeaf2a 100644 --- a/frappe/website/doctype/website_script/website_script.py +++ b/frappe/website/doctype/website_script/website_script.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_settings/__init__.py b/frappe/website/doctype/website_settings/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/website/doctype/website_settings/__init__.py +++ b/frappe/website/doctype/website_settings/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/website/doctype/website_settings/test_website_settings.py b/frappe/website/doctype/website_settings/test_website_settings.py index 9eca957713..f7bf9d3bf1 100644 --- a/frappe/website/doctype/website_settings/test_website_settings.py +++ b/frappe/website/doctype/website_settings/test_website_settings.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - # import frappe import unittest diff --git a/frappe/website/doctype/website_settings/website_settings.py b/frappe/website/doctype/website_settings/website_settings.py index f7f22aa2df..03a1aecc5f 100644 --- a/frappe/website/doctype/website_settings/website_settings.py +++ b/frappe/website/doctype/website_settings/website_settings.py @@ -1,12 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import get_request_site_address, encode from frappe.model.document import Document -from six.moves.urllib.parse import quote +from urllib.parse import quote from frappe.website.router import resolve_route from frappe.website.doctype.website_theme.website_theme import add_website_theme from frappe.integrations.doctype.google_settings.google_settings import get_auth_url diff --git a/frappe/website/doctype/website_sidebar/test_website_sidebar.py b/frappe/website/doctype/website_sidebar/test_website_sidebar.py index d49ea84a35..bfaee51169 100644 --- a/frappe/website/doctype/website_sidebar/test_website_sidebar.py +++ b/frappe/website/doctype/website_sidebar/test_website_sidebar.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/website/doctype/website_sidebar/website_sidebar.py b/frappe/website/doctype/website_sidebar/website_sidebar.py index 87daf47680..f8a431ac15 100644 --- a/frappe/website/doctype/website_sidebar/website_sidebar.py +++ b/frappe/website/doctype/website_sidebar/website_sidebar.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py b/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py index 83e987ed09..f4d88e3259 100644 --- a/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py +++ b/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py @@ -2,7 +2,6 @@ # Copyright (c) 2015, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_slideshow/test_website_slideshow.py b/frappe/website/doctype/website_slideshow/test_website_slideshow.py index 9eccc71ad3..5e3ca3c617 100644 --- a/frappe/website/doctype/website_slideshow/test_website_slideshow.py +++ b/frappe/website/doctype/website_slideshow/test_website_slideshow.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest diff --git a/frappe/website/doctype/website_slideshow/website_slideshow.py b/frappe/website/doctype/website_slideshow/website_slideshow.py index 90f62d1bb1..d31adbf986 100644 --- a/frappe/website/doctype/website_slideshow/website_slideshow.py +++ b/frappe/website/doctype/website_slideshow/website_slideshow.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/website/doctype/website_slideshow_item/website_slideshow_item.py b/frappe/website/doctype/website_slideshow_item/website_slideshow_item.py index 3b809a7f65..beaa9ecf9e 100644 --- a/frappe/website/doctype/website_slideshow_item/website_slideshow_item.py +++ b/frappe/website/doctype/website_slideshow_item/website_slideshow_item.py @@ -3,7 +3,6 @@ # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/website/doctype/website_theme/test_website_theme.py b/frappe/website/doctype/website_theme/test_website_theme.py index 11956ba3d9..4ff4e269da 100644 --- a/frappe/website/doctype/website_theme/test_website_theme.py +++ b/frappe/website/doctype/website_theme/test_website_theme.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import os import frappe import unittest diff --git a/frappe/website/doctype/website_theme/website_theme.py b/frappe/website/doctype/website_theme/website_theme.py index dbc54782e1..248c4bc176 100644 --- a/frappe/website/doctype/website_theme/website_theme.py +++ b/frappe/website/doctype/website_theme/website_theme.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document diff --git a/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py b/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py index e91e91a68f..ec232c0c79 100644 --- a/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py +++ b/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py @@ -2,7 +2,6 @@ # Copyright (c) 2020, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals # import frappe from frappe.model.document import Document diff --git a/frappe/website/page/__init__.py b/frappe/website/page/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/website/page/__init__.py +++ b/frappe/website/page/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/website/purifycss.py b/frappe/website/purifycss.py index 39e989db6e..bac68b881b 100644 --- a/frappe/website/purifycss.py +++ b/frappe/website/purifycss.py @@ -1,4 +1,3 @@ -from __future__ import print_function, unicode_literals ''' Check for unused CSS Classes diff --git a/frappe/website/redirect.py b/frappe/website/redirect.py index 73e3c21727..3194895d95 100644 --- a/frappe/website/redirect.py +++ b/frappe/website/redirect.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import re, frappe def resolve_redirect(path): diff --git a/frappe/website/render.py b/frappe/website/render.py index 71382c18ff..2b4a5e2dab 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ import frappe.sessions @@ -9,8 +8,6 @@ from frappe.utils import cstr import os, mimetypes, json import re -import six -from six import iteritems from werkzeug.wrappers import Response from werkzeug.routing import Rule from werkzeug.wsgi import wrap_file @@ -131,7 +128,7 @@ def build_response(path, data, http_status_code, headers=None): add_preload_headers(response) if headers: - for key, val in iteritems(headers): + for key, val in headers.items(): response.headers[key] = val.encode("ascii", errors="xmlcharrefreplace") return response @@ -321,7 +318,7 @@ def clear_cache(path=None): frappe.get_attr(method)(path) def render_403(e, pathname): - frappe.local.message = cstr(e.message if six.PY2 else e) + frappe.local.message = cstr(e) frappe.local.message_title = _("Not Permitted") frappe.local.response['context'] = dict( indicator_color = 'red', diff --git a/frappe/website/report/website_analytics/website_analytics.py b/frappe/website/report/website_analytics/website_analytics.py index b7e0aab27b..d141972679 100644 --- a/frappe/website/report/website_analytics/website_analytics.py +++ b/frappe/website/report/website_analytics/website_analytics.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals import frappe from datetime import datetime from frappe.utils import getdate diff --git a/frappe/website/router.py b/frappe/website/router.py index f3518e179e..899f2722ab 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import io import os import re diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 0738c836f3..aa98595e2d 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - import re import os import frappe diff --git a/frappe/website/web_form/request_data/request_data.py b/frappe/website/web_form/request_data/request_data.py index 07616644d3..1224e3f095 100644 --- a/frappe/website/web_form/request_data/request_data.py +++ b/frappe/website/web_form/request_data/request_data.py @@ -1,4 +1,2 @@ -from __future__ import unicode_literals - def get_context(context): pass diff --git a/frappe/website/web_form/request_to_delete_data/request_to_delete_data.py b/frappe/website/web_form/request_to_delete_data/request_to_delete_data.py index 74908f4119..75b748913a 100644 --- a/frappe/website/web_form/request_to_delete_data/request_to_delete_data.py +++ b/frappe/website/web_form/request_to_delete_data/request_to_delete_data.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - def get_context(context): # do your magic here pass \ No newline at end of file diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index fc08abeed9..351f2f1832 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.website.utils import cleanup_page_name diff --git a/frappe/workflow/doctype/workflow/test_workflow.py b/frappe/workflow/doctype/workflow/test_workflow.py index 9ad0562a86..9bafd377fc 100644 --- a/frappe/workflow/doctype/workflow/test_workflow.py +++ b/frappe/workflow/doctype/workflow/test_workflow.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals - import frappe import unittest from frappe.utils import random_string diff --git a/frappe/workflow/doctype/workflow/workflow.py b/frappe/workflow/doctype/workflow/workflow.py index b4d7293fed..4959ee5639 100644 --- a/frappe/workflow/doctype/workflow/workflow.py +++ b/frappe/workflow/doctype/workflow/workflow.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 8c10af8251..b70ffb2406 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document from frappe.utils.background_jobs import enqueue diff --git a/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py b/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py index df1123f786..b438a708dc 100644 --- a/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py +++ b/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py @@ -2,7 +2,6 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt -from __future__ import unicode_literals from frappe.model.document import Document class WorkflowActionMaster(Document): diff --git a/frappe/workflow/doctype/workflow_document_state/workflow_document_state.py b/frappe/workflow/doctype/workflow_document_state/workflow_document_state.py index 6e2ac212ae..ae7372f5c2 100644 --- a/frappe/workflow/doctype/workflow_document_state/workflow_document_state.py +++ b/frappe/workflow/doctype/workflow_document_state/workflow_document_state.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/workflow/doctype/workflow_state/test_workflow_state.py b/frappe/workflow/doctype/workflow_state/test_workflow_state.py index 63a2f9b151..eeb0807d52 100644 --- a/frappe/workflow/doctype/workflow_state/test_workflow_state.py +++ b/frappe/workflow/doctype/workflow_state/test_workflow_state.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe test_records = frappe.get_test_records('Workflow State') \ No newline at end of file diff --git a/frappe/workflow/doctype/workflow_state/workflow_state.py b/frappe/workflow/doctype/workflow_state/workflow_state.py index c446a4445e..40f7d370dd 100644 --- a/frappe/workflow/doctype/workflow_state/workflow_state.py +++ b/frappe/workflow/doctype/workflow_state/workflow_state.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/workflow/doctype/workflow_transition/workflow_transition.py b/frappe/workflow/doctype/workflow_transition/workflow_transition.py index 4c07d700c6..e49a90f9d6 100644 --- a/frappe/workflow/doctype/workflow_transition/workflow_transition.py +++ b/frappe/workflow/doctype/workflow_transition/workflow_transition.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.model.document import Document diff --git a/frappe/www/404.py b/frappe/www/404.py index c9de234743..f064a66c17 100644 --- a/frappe/www/404.py +++ b/frappe/www/404.py @@ -1,4 +1,2 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - diff --git a/frappe/www/__init__.py b/frappe/www/__init__.py index baffc48825..8b13789179 100644 --- a/frappe/www/__init__.py +++ b/frappe/www/__init__.py @@ -1 +1 @@ -from __future__ import unicode_literals + diff --git a/frappe/www/about.py b/frappe/www/about.py index e7a7be23e8..05fe34b162 100644 --- a/frappe/www/about.py +++ b/frappe/www/about.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe sitemap = 1 diff --git a/frappe/www/app.py b/frappe/www/app.py index 5f19712cd3..b0fa19df9b 100644 --- a/frappe/www/app.py +++ b/frappe/www/app.py @@ -1,8 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function - no_cache = 1 base_template_path = "templates/www/app.html" diff --git a/frappe/www/complete_signup.py b/frappe/www/complete_signup.py index 00c499e786..0e57cb68c3 100644 --- a/frappe/www/complete_signup.py +++ b/frappe/www/complete_signup.py @@ -1,5 +1,3 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - diff --git a/frappe/www/contact.py b/frappe/www/contact.py index d976350075..53b0666be8 100644 --- a/frappe/www/contact.py +++ b/frappe/www/contact.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe.utils import now from frappe import _ diff --git a/frappe/www/error.py b/frappe/www/error.py index 161038373d..dcbfb38e1f 100644 --- a/frappe/www/error.py +++ b/frappe/www/error.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt - -from __future__ import unicode_literals, print_function import frappe no_cache = 1 diff --git a/frappe/www/list.py b/frappe/www/list.py index fc4dc602c3..881aaf085b 100644 --- a/frappe/www/list.py +++ b/frappe/www/list.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe, json from frappe.utils import cint, quoted from frappe.website.render import resolve_path diff --git a/frappe/www/login.py b/frappe/www/login.py index 1ce25a81d9..6542b29d42 100644 --- a/frappe/www/login.py +++ b/frappe/www/login.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe import frappe.utils from frappe.utils.oauth import get_oauth2_authorize_url, get_oauth_keys, login_via_oauth2, login_via_oauth2_id_token, login_oauth_user as _login_oauth_user, redirect_post_login diff --git a/frappe/www/me.py b/frappe/www/me.py index 2191f28bca..f8356b6d07 100644 --- a/frappe/www/me.py +++ b/frappe/www/me.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe import _ import frappe.www.list diff --git a/frappe/www/message.py b/frappe/www/message.py index ea45b9c4b5..3658261503 100644 --- a/frappe/www/message.py +++ b/frappe/www/message.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import strip_html_tags diff --git a/frappe/www/printview.py b/frappe/www/printview.py index 132d863375..6b879e2452 100644 --- a/frappe/www/printview.py +++ b/frappe/www/printview.py @@ -1,15 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe, os, copy, json, re from frappe import _ from frappe.modules import get_doc_path from frappe.core.doctype.access_log.access_log import make_access_log from frappe.utils import cint, sanitize_html, strip_html -from six import string_types no_cache = 1 @@ -73,7 +70,7 @@ def get_rendered_template(doc, name=None, print_format=None, meta=None, print_settings = frappe.get_single("Print Settings").as_dict() print_settings.update(settings or {}) - if isinstance(no_letterhead, string_types): + if isinstance(no_letterhead, str): no_letterhead = cint(no_letterhead) elif no_letterhead is None: @@ -186,10 +183,10 @@ def get_html_and_style(doc, name=None, print_format=None, meta=None, settings=None, templates=None): """Returns `html` and `style` of print format, used in PDF etc""" - if isinstance(doc, string_types) and isinstance(name, string_types): + if isinstance(doc, str) and isinstance(name, str): doc = frappe.get_doc(doc, name) - if isinstance(doc, string_types): + if isinstance(doc, str): doc = frappe.get_doc(json.loads(doc)) print_format = get_print_format_doc(print_format, meta=meta or frappe.get_meta(doc.doctype)) @@ -211,10 +208,10 @@ def get_html_and_style(doc, name=None, print_format=None, meta=None, def get_rendered_raw_commands(doc, name=None, print_format=None, meta=None, lang=None): """Returns Rendered Raw Commands of print format, used to send directly to printer""" - if isinstance(doc, string_types) and isinstance(name, string_types): + if isinstance(doc, str) and isinstance(name, str): doc = frappe.get_doc(doc, name) - if isinstance(doc, string_types): + if isinstance(doc, str): doc = frappe.get_doc(json.loads(doc)) print_format = get_print_format_doc(print_format, meta=meta or frappe.get_meta(doc.doctype)) @@ -380,7 +377,7 @@ def has_value(df, doc): if value in (None, ""): return False - elif isinstance(value, string_types) and not strip_html(value).strip(): + elif isinstance(value, str) and not strip_html(value).strip(): if df.fieldtype in ["Text", "Text Editor"]: return True @@ -480,7 +477,7 @@ def column_has_value(data, fieldname, col_df): for row in data: value = row.get(fieldname) if value: - if isinstance(value, string_types): + if isinstance(value, str): if strip_html(value).strip(): has_value = True break diff --git a/frappe/www/profile.py b/frappe/www/profile.py index e1badf10e5..7db7beb7d8 100644 --- a/frappe/www/profile.py +++ b/frappe/www/profile.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - no_cache = 1 diff --git a/frappe/www/qrcode.py b/frappe/www/qrcode.py index ddee635ded..37ee204925 100644 --- a/frappe/www/qrcode.py +++ b/frappe/www/qrcode.py @@ -1,11 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe import _ -from six.moves.urllib.parse import parse_qsl +from urllib.parse import parse_qsl from frappe.twofactor import get_qr_svg_code def get_context(context): diff --git a/frappe/www/robots.py b/frappe/www/robots.py index 6a7c74cf41..487f378415 100644 --- a/frappe/www/robots.py +++ b/frappe/www/robots.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe base_template_path = "templates/www/robots.txt" diff --git a/frappe/www/rss.py b/frappe/www/rss.py index a389304e5e..033c341137 100644 --- a/frappe/www/rss.py +++ b/frappe/www/rss.py @@ -1,10 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import escape_html, get_request_site_address, now, cstr -from six.moves.urllib.parse import quote, urljoin +from urllib.parse import quote, urljoin no_cache = 1 base_template_path = "templates/www/rss.xml" diff --git a/frappe/www/search.py b/frappe/www/search.py index a8bb1a5294..292c9e532f 100644 --- a/frappe/www/search.py +++ b/frappe/www/search.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.global_search import web_search from html2text import html2text diff --git a/frappe/www/sitemap.py b/frappe/www/sitemap.py index f8f03c45f8..9eb36e5335 100644 --- a/frappe/www/sitemap.py +++ b/frappe/www/sitemap.py @@ -1,14 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import frappe from frappe.model.document import get_controller from frappe.utils import get_datetime, nowdate, get_url from frappe.website.router import get_pages, get_all_page_context_from_doctypes -from six import iteritems -from six.moves.urllib.parse import quote, urljoin +from urllib.parse import quote no_cache = 1 base_template_path = "templates/www/sitemap.xml" @@ -22,14 +19,14 @@ def get_context(context): host = frappe.utils.get_host_name_from_request() links = [] - for route, page in iteritems(get_pages()): + for route, page in get_pages().items(): if page.sitemap: links.append({ "loc": get_url(quote(page.name.encode("utf-8"))), "lastmod": nowdate() }) - for route, data in iteritems(get_public_pages_from_doctypes()): + for route, data in get_public_pages_from_doctypes().items: links.append({ "loc": get_url(quote((route or "").encode("utf-8"))), "lastmod": get_datetime(data.get("modified")).strftime("%Y-%m-%d") diff --git a/frappe/www/third_party_apps.py b/frappe/www/third_party_apps.py index 77928af511..2668923449 100644 --- a/frappe/www/third_party_apps.py +++ b/frappe/www/third_party_apps.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe import _ import frappe.www.list diff --git a/frappe/www/unsubscribe.py b/frappe/www/unsubscribe.py index 8bf0741fef..4ebaa35991 100644 --- a/frappe/www/unsubscribe.py +++ b/frappe/www/unsubscribe.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals + import frappe from frappe.utils.verified_command import verify_request from frappe.email.doctype.newsletter.newsletter import confirmed_unsubscribe diff --git a/frappe/www/update_password.py b/frappe/www/update_password.py index f81098b916..4c7d3d5401 100644 --- a/frappe/www/update_password.py +++ b/frappe/www/update_password.py @@ -1,7 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - from frappe import _ no_cache = 1 diff --git a/frappe/www/website_script.py b/frappe/www/website_script.py index 0bb5a8a80b..915ef23367 100644 --- a/frappe/www/website_script.py +++ b/frappe/www/website_script.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe from frappe.utils import strip from frappe.website.doctype.website_theme.website_theme import get_active_theme diff --git a/setup.py b/setup.py index 515e9448c2..f4f826d6b1 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - # imports - standard imports import os, shutil from distutils.command.clean import clean as Clean From 71632073ecbb88996ce355a353715eba02b50304 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 26 May 2021 15:45:02 +0530 Subject: [PATCH 180/868] chore: Fix status badge link --- README.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e00bea7857..11343a632a 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,21 @@
From d236a931693fccc0a59852cf18833afe24ce09d9 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 15:45:34 +0530 Subject: [PATCH 181/868] chore: Replacing and updating bleach source list * The library bleach-whitelist was deprecated and renamed to bleach-allowlist. * Updated the usages and requirements for the same. --- frappe/utils/html_utils.py | 10 ++++++---- requirements.txt | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frappe/utils/html_utils.py b/frappe/utils/html_utils.py index 24def07c63..ccb374fbcc 100644 --- a/frappe/utils/html_utils.py +++ b/frappe/utils/html_utils.py @@ -1,8 +1,10 @@ - -import frappe import json import re -import bleach_whitelist.bleach_whitelist as bleach_whitelist + +from bleach_allowlist import bleach_allowlist + +import frappe + def clean_html(html): import bleach @@ -71,7 +73,7 @@ def sanitize_html(html, linkify=False): tags = (acceptable_elements + svg_elements + mathml_elements + ["html", "head", "meta", "link", "body", "style", "o:p"]) attributes = {"*": acceptable_attributes, 'svg': svg_attributes} - styles = bleach_whitelist.all_styles + styles = bleach_allowlist.all_styles strip_comments = False # returns html with escaped tags, escaped orphan >, <, etc. diff --git a/requirements.txt b/requirements.txt index 769d8c3e7b..b3bfc12567 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ Babel~=2.9.0 beautifulsoup4~=4.9.3 -bleach-whitelist~=0.0.11 +bleach-allowlist~=1.0.3 bleach~=3.3.0 boto3~=1.17.53 braintree~=4.8.0 From ab9b6bf36ec142fe4fc3bb47b46c9455fb4fa8b1 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 26 May 2021 15:46:41 +0530 Subject: [PATCH 182/868] ci: Run ui tests after PR merge for status badge --- .github/workflows/ui-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index d9ccb07da0..f2f43f10f8 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -3,6 +3,8 @@ name: UI on: pull_request: workflow_dispatch: + push: + branches: [ develop ] jobs: test: From 1acb2ddd2f7b671816f83790f5b2a5c7231c38d2 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 15:54:36 +0530 Subject: [PATCH 183/868] fix: Use context managers to stream data While executing git commands in the shell via Frappe processes, use context managers to ensure files get closed after usage. This fixes the ResourceWarning errors due to unclosed files. --- frappe/utils/change_log.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/utils/change_log.py b/frappe/utils/change_log.py index 6cb71c6ac5..ddd11265eb 100644 --- a/frappe/utils/change_log.py +++ b/frappe/utils/change_log.py @@ -118,9 +118,9 @@ def get_versions(): def get_app_branch(app): '''Returns branch of an app''' try: - null_stream = open(os.devnull, 'wb') - result = subprocess.check_output('cd ../apps/{0} && git rev-parse --abbrev-ref HEAD'.format(app), - shell=True, stdin=null_stream, stderr=null_stream) + with open(os.devnull, 'wb') as null_stream: + result = subprocess.check_output(f'cd ../apps/{app} && git rev-parse --abbrev-ref HEAD', + shell=True, stdin=null_stream, stderr=null_stream) result = safe_decode(result) result = result.strip() return result @@ -129,9 +129,9 @@ def get_app_branch(app): def get_app_last_commit_ref(app): try: - null_stream = open(os.devnull, 'wb') - result = subprocess.check_output('cd ../apps/{0} && git rev-parse HEAD --short 7'.format(app), - shell=True, stdin=null_stream, stderr=null_stream) + with open(os.devnull, 'wb') as null_stream: + result = subprocess.check_output(f'cd ../apps/{app} && git rev-parse HEAD --short 7', + shell=True, stdin=null_stream, stderr=null_stream) result = safe_decode(result) result = result.strip() return result From 1e9b0cf38611f7358d1e920352992ce6c2dbb7f7 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 16:02:27 +0530 Subject: [PATCH 184/868] fix: Use dict.items instead of six.iteritems --- frappe/utils/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index cb02035299..e776d9945a 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -618,7 +618,7 @@ def get_installed_apps_info(): out = [] from frappe.utils.change_log import get_versions - for app, version_details in iteritems(get_versions()): + for app, version_details in get_versions().items(): out.append({ 'app_name': app, 'version': version_details.get('branch_version') or version_details.get('version'), From feea2f3c44dd653efd106476777add1975fbe3ae Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 16:32:41 +0530 Subject: [PATCH 185/868] fix: Use raw string to avoid invalid escape sequence errors --- .github/helper/roulette.py | 2 +- frappe/utils/__init__.py | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/helper/roulette.py b/.github/helper/roulette.py index ba775d6794..ea4f07b9f7 100644 --- a/.github/helper/roulette.py +++ b/.github/helper/roulette.py @@ -18,7 +18,7 @@ def is_js(file): return file.endswith("js") def is_docs(file): - regex = re.compile('\.(md|png|jpg|jpeg)$|^.github|LICENSE') + regex = re.compile(r'\.(md|png|jpg|jpeg)$|^.github|LICENSE') return bool(regex.search(file)) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index e776d9945a..94eed0b2bb 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -117,7 +117,10 @@ def validate_email_address(email_str, throw=False): else: email_id = extract_email_id(e) - match = re.match("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", email_id.lower()) if email_id else None + match = re.match( + r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", + email_id.lower() + ) if email_id else None if not match: _valid = False @@ -287,7 +290,7 @@ def remove_blanks(d): def strip_html_tags(text): """Remove html tags from text""" - return re.sub("\<[^>]*\>", "", text) + return re.sub(r"\<[^>]*\>", "", text) def get_file_timestamp(fn): """ @@ -499,7 +502,7 @@ def is_markdown(text): elif "" in text: return False else: - return not re.search("|", text) + return not re.search(r"|", text) def get_sites(sites_path=None): if not sites_path: @@ -609,7 +612,7 @@ def check_format(email_id): def get_name_from_email_string(email_string, email_id, name): name = email_string.replace(email_id, '') - name = re.sub('[^A-Za-z0-9\u00C0-\u024F\/\_\' ]+', '', name).strip() + name = re.sub(r'[^A-Za-z0-9\u00C0-\u024F\/\_\' ]+', '', name).strip() if not name: name = email_id return name From bd6fcddd0446e6da56b5ae71e48aab0bc9a66bee Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 16:41:32 +0530 Subject: [PATCH 186/868] chore: Drop unreachable code --- frappe/contacts/doctype/address/address.py | 5 +---- frappe/utils/__init__.py | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index 9aced0dacb..b3150aa75a 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -171,14 +171,11 @@ def get_address_list(doctype, txt, filters, limit_start, limit_page_length = 20, def has_website_permission(doc, ptype, user, verbose=False): """Returns true if there is a related lead or contact related to this document""" contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user}) + if contact_name: contact = frappe.get_doc('Contact', contact_name) return contact.has_common_link(doc) - lead_name = frappe.db.get_value("Lead", {"email_id": frappe.session.user}) - if lead_name: - return doc.has_link('Lead', lead_name) - return False def get_address_templates(address): diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 94eed0b2bb..8d4905edd6 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -371,7 +371,7 @@ def get_path(*path, **kwargs): base = frappe.local.site_path return os.path.join(base, *path) -def get_site_base_path(sites_dir=None, hostname=None): +def get_site_base_path(): return frappe.local.site_path def get_site_path(*path): From 3adb84eb8d550f46fb7738dcd5f9db0d6d6d047d Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 17:04:28 +0530 Subject: [PATCH 187/868] chore: Drop watchdog dependency Watchdog isn't used by Frappe, and there wasn't any mechanism to access it directly either. By default, bench serve (or start) uses Werkzeug's watchdogreloader --- frappe/utils/__init__.py | 38 +++++++------------------------------- requirements.txt | 1 - 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 8d4905edd6..9985d2dcf3 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -520,42 +520,18 @@ def get_sites(sites_path=None): return sorted(sites) -def get_request_session(max_retries=3): +def get_request_session(max_retries=5): import requests from urllib3.util import Retry + session = requests.Session() - session.mount("http://", requests.adapters.HTTPAdapter(max_retries=Retry(total=5, status_forcelist=[500]))) - session.mount("https://", requests.adapters.HTTPAdapter(max_retries=Retry(total=5, status_forcelist=[500]))) + http_adapter = requests.adapters.HTTPAdapter(max_retries=Retry(total=max_retries, status_forcelist=[500])) + + session.mount("http://", http_adapter) + session.mount("https://", http_adapter) + return session -def watch(path, handler=None, debug=True): - import time - - from watchdog.events import FileSystemEventHandler - from watchdog.observers import Observer - - class Handler(FileSystemEventHandler): - def on_any_event(self, event): - if debug: - print("File {0}: {1}".format(event.event_type, event.src_path)) - - if not handler: - print("No handler specified") - return - - handler(event.src_path, event.event_type) - - event_handler = Handler() - observer = Observer() - observer.schedule(event_handler, path, recursive=True) - observer.start() - try: - while True: - time.sleep(1) - except KeyboardInterrupt: - observer.stop() - observer.join() - def markdown(text, sanitize=True, linkify=True): html = text if is_html(text) else frappe.utils.md_to_html(text) diff --git a/requirements.txt b/requirements.txt index b3bfc12567..9c61e500ef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -72,7 +72,6 @@ stripe~=2.56.0 terminaltables~=3.1.0 unittest-xml-reporting~=3.0.4 urllib3~=1.26.4 -watchdog~=2.0.2 Werkzeug~=0.16.1 Whoosh~=2.7.4 wrapt~=1.12.1 From 131cfaee8bd8a51a18af7f780086dd617c040622 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 07:51:12 +0530 Subject: [PATCH 188/868] fix: Close file after read This fixes the ResourceWarning errors due to unclosed files while utilizing the website router --- frappe/website/router.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/website/router.py b/frappe/website/router.py index 899f2722ab..aa74d140c1 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -372,7 +372,8 @@ def setup_index(page_info): # load index.txt if loading all pages index_txt_path = os.path.join(page_info.basepath, 'index.txt') if os.path.exists(index_txt_path): - page_info.index = open(index_txt_path, 'r').read().splitlines() + with open(index_txt_path, 'r') as f: + page_info.index = f.read().splitlines() def load_properties_from_source(page_info): '''Load properties like no_cache, title from source html''' From cb5543665fc7b1e1a658e60601f1b4178d84bfda Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 26 May 2021 18:27:26 +0530 Subject: [PATCH 189/868] fix: minor fixes --- .../internal_wiki_page/internal_wiki_page.py | 6 +- frappe/public/js/frappe/views/wiki.js | 95 +++++++++++++------ 2 files changed, 66 insertions(+), 35 deletions(-) diff --git a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py index a53473e1fe..6be92f835d 100644 --- a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py +++ b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py @@ -11,10 +11,8 @@ from frappe.model.document import Document class InternalWikiPage(Document): def before_insert(self): - if frappe.db.count('Internal Wiki Page') == 0: - self.sequence_id = 1 - else: - self.sequence_id = frappe.get_last_doc('Internal Wiki Page').sequence_id + 1 + sequence_id_list = frappe.get_all('Internal Wiki Page', {'sequence_id'}) + self.sequence_id = max([page.sequence_id for page in sequence_id_list]) + 1 @frappe.whitelist() def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, save=True): diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index b0ec3c1882..955476861b 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -10,12 +10,10 @@ frappe.views.Wiki = class Wiki { this.sidebar_items = {}; this.sorted_sidebar_items = []; this.deleted_sidebar_items = []; - this.tools = {}; this.isReadOnly = true; this.new_page = null; this.prepare_container(); this.setup_wiki_pages(); - this.tools = { header: { class: frappe.wiki_block.blocks['header'], @@ -63,16 +61,16 @@ frappe.views.Wiki = class Wiki { if (this.all_pages) { frappe.wiki_pages = {}; let root_pages = this.all_pages.filter(page => page.parent_page == '' || page.parent_page == null); - for (let page of this.all_pages || []) { + for (let page of this.all_pages) { frappe.wiki_pages[frappe.router.slug(page.name)] = page; } + if (this.new_page) { + frappe.set_route(`wiki/${frappe.router.slug(this.new_page)}`); + this.new_page = null; + } this.make_sidebar(root_pages); + frappe.router.route(); } - if (this.new_page) { - frappe.set_route(`wiki/${frappe.router.slug(this.new_page)}`); - this.new_page = null; - } - frappe.router.route(); }); } @@ -96,30 +94,13 @@ frappe.views.Wiki = class Wiki { } append_item(item, container) { - let is_current_page = frappe.router.slug(item.name) == frappe.router.slug(this.get_page_to_show()) || item.name == this.new_page; + let is_current_page = frappe.router.slug(item.name) == frappe.router.slug(this.get_page_to_show()); if (is_current_page) { item.selected = true; this.current_page_name = item.name; } - const item_container = function (item) { - return $(` - - `); - }; - - let $item_container = item_container(item); + let $item_container = this.sidebar_item_container(item); let sidebar_control = $item_container.find('.sidebar-item-control'); this.add_sidebar_actions(item, sidebar_control); @@ -151,6 +132,23 @@ frappe.views.Wiki = class Wiki { } } + sidebar_item_container(item) { + return $(` + + `); + } + show() { if (!this.all_pages) { // pages not yet loaded, call again after a bit @@ -256,9 +254,7 @@ frappe.views.Wiki = class Wiki { this.editor.readOnly.toggle(); this.editor.isReady .then(() => { - this.undo = new Undo({ editor: this.editor }); - this.undo.initialize({blocks: JSON.parse(this.content)}); - this.undo.readOnly = false; + this.initialize_editorjs_undo(); this.setup_customization_buttons(); this.show_sidebar_actions(); this.make_sidebar_sortable(); @@ -272,6 +268,12 @@ frappe.views.Wiki = class Wiki { }); } + initialize_editorjs_undo() { + this.undo = new Undo({ editor: this.editor }); + this.undo.initialize({blocks: JSON.parse(this.content)}); + this.undo.readOnly = false; + } + show_sidebar_actions() { this.sidebar.find('.standard-sidebar-section').addClass('show-control'); } @@ -326,7 +328,7 @@ frappe.views.Wiki = class Wiki { animation: 150, fallbackOnBody: true, swapThreshold: 0.65, - onEnd: function (evt) { + onEnd: function () { me.sorted_sidebar_items = []; for (let page of $('.standard-sidebar-section').find('.sidebar-item-container')) { let parent_page = ""; @@ -410,6 +412,7 @@ frappe.views.Wiki = class Wiki { primary_action_label: __('Create'), primary_action: (values) => { d.hide(); + this.initialize_editorjs_undo(); this.setup_customization_buttons(); this.title = values.title; this.parent = values.parent; @@ -428,6 +431,8 @@ frappe.views.Wiki = class Wiki { this.isReadOnly = false; this.editor.readOnly.toggle(); } + this.add_page_to_sidebar(values); + this.show_sidebar_actions(); this.make_sidebar_sortable(); this.make_blocks_sortable(); }); @@ -436,6 +441,32 @@ frappe.views.Wiki = class Wiki { d.show(); } + add_page_to_sidebar({title, parent}) { + let $sidebar = $('.standard-sidebar-section'); + let item = { + name: title, + parent_page: parent, + }; + let $sidebar_item = this.sidebar_item_container(item); + + this.add_custom_button( + frappe.utils.icon('drag', 'xs'), + null, + "drag-handle", + `${__('Drag')}`, + null, + $sidebar_item.find('.sidebar-item-control') + ); + + if (!parent) { + $sidebar_item.appendTo($sidebar); + } else { + let $child_section = $sidebar.find(`[item-name="${parent}"] .sidebar-child-item`); + $sidebar_item.appendTo($child_section); + $child_section.removeClass('hidden'); + } + } + initialize_editorjs(blocks) { const data = { blocks: blocks || [] @@ -456,6 +487,8 @@ frappe.views.Wiki = class Wiki { if (!this.title && this.current_page_name) { this.title = this.current_page_name; save = ''; + } else { + this.current_page_name = this.title; } let me = this; this.editor.save().then((outputData) => { From f6b215938a9758f7c1e54ddc19161280a37dbe68 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 19:30:08 +0530 Subject: [PATCH 190/868] fix: Use raw string to avoid invalid sequence errors Escaped when proven easier --- frappe/translate.py | 2 +- frappe/utils/__init__.py | 2 +- frappe/utils/data.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/translate.py b/frappe/translate.py index f95fdad015..b7b780e594 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -589,7 +589,7 @@ def is_translatable(m): def add_line_number(messages, code): ret = [] messages = sorted(messages, key=lambda x: x[0]) - newlines = [m.start() for m in re.compile('\\n').finditer(code)] + newlines = [m.start() for m in re.compile(r'\n').finditer(code)] line = 1 newline_i = 0 for pos, message, context in messages: diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 9985d2dcf3..2d3637d527 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -151,7 +151,7 @@ def split_emails(txt): # emails can be separated by comma or newline s = re.sub(r'[\t\n\r]', ' ', cstr(txt)) - for email in re.split('''[,\\n](?=(?:[^"]|"[^"]*")*$)''', s): + for email in re.split(r'[,\n](?=(?:[^"]|"[^"]*")*$)', s): email = strip(cstr(email)) if email: email_list.append(email) diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 09b02a918a..df36524c16 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -454,7 +454,7 @@ def duration_to_seconds(duration): def validate_duration_format(duration): import re - is_valid_duration = re.match("^(?:(\d+d)?((^|\s)\d+h)?((^|\s)\d+m)?((^|\s)\d+s)?)$", duration) + is_valid_duration = re.match(r"^(?:(\d+d)?((^|\s)\d+h)?((^|\s)\d+m)?((^|\s)\d+s)?)$", duration) if not is_valid_duration: frappe.throw(frappe._("Value {0} must be in the valid duration format: d h m s").format(frappe.bold(duration))) @@ -1341,10 +1341,10 @@ def expand_relative_urls(html): return "".join(to_expand) - html = re.sub('(href|src){1}([\s]*=[\s]*[\'"]?)((?!http)[^\'" >]+)([\'"]?)', _expand_relative_urls, html) + html = re.sub(r'(href|src){1}([\s]*=[\s]*[\'"]?)((?!http)[^\'" >]+)([\'"]?)', _expand_relative_urls, html) # background-image: url('/assets/...') - html = re.sub('(:[\s]?url)(\([\'"]?)((?!http)[^\'" >]+)([\'"]?\))', _expand_relative_urls, html) + html = re.sub(r'(:[\s]?url)(\([\'"]?)((?!http)[^\'" >]+)([\'"]?\))', _expand_relative_urls, html) return html def quoted(url): @@ -1355,7 +1355,7 @@ def quote_urls(html): groups = list(match.groups()) groups[2] = quoted(groups[2]) return "".join(groups) - return re.sub('(href|src){1}([\s]*=[\s]*[\'"]?)((?:http)[^\'">]+)([\'"]?)', + return re.sub(r'(href|src){1}([\s]*=[\s]*[\'"]?)((?:http)[^\'">]+)([\'"]?)', _quote_url, html) def unique(seq): From 295d44cee500d24f9556099e87120493983ae23c Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 19:31:17 +0530 Subject: [PATCH 191/868] chore: Drop future from requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9c61e500ef..4f4614955b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,6 @@ cryptography~=3.4.7 dropbox~=11.7.0 email-reply-parser~=0.5.12 Faker~=8.1.0 -future==0.18.2 git-url-parse~=1.2.2 gitdb~=4.0.7 GitPython~=3.1.14 From 88ef41bc58a2e9df5efd3441aacbf3f6beb6d952 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 19:49:22 +0530 Subject: [PATCH 192/868] fix(typo): Let's try executing bound method instead --- frappe/utils/bench_helper.py | 1 + frappe/www/sitemap.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/utils/bench_helper.py b/frappe/utils/bench_helper.py index ec08d2a15e..2ee1e6691f 100644 --- a/frappe/utils/bench_helper.py +++ b/frappe/utils/bench_helper.py @@ -100,4 +100,5 @@ def get_apps(): if __name__ == "__main__": if not frappe._dev_server: warnings.simplefilter('ignore') + warnings.simplefilter('always') main() diff --git a/frappe/www/sitemap.py b/frappe/www/sitemap.py index 9eb36e5335..1606e91200 100644 --- a/frappe/www/sitemap.py +++ b/frappe/www/sitemap.py @@ -26,7 +26,7 @@ def get_context(context): "lastmod": nowdate() }) - for route, data in get_public_pages_from_doctypes().items: + for route, data in get_public_pages_from_doctypes().items(): links.append({ "loc": get_url(quote((route or "").encode("utf-8"))), "lastmod": get_datetime(data.get("modified")).strftime("%Y-%m-%d") From eca30667d2f10d793e93383cbc1ebd6317b218ff Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 26 May 2021 22:21:23 +0530 Subject: [PATCH 193/868] chore: Drop FileNotFoundError handling for PY2 --- frappe/exceptions.py | 8 -------- frappe/model/delete_doc.py | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 0f111fdcf9..13abd8f4f8 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -1,17 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -import sys - # BEWARE don't put anything in this file except exceptions from werkzeug.exceptions import NotFound - -if sys.version_info.major == 2: - class FileNotFoundError(Exception): pass -else: - from builtins import FileNotFoundError - class SiteNotSpecifiedError(Exception): def __init__(self, *args, **kwargs): self.message = "Please specify --site sitename" diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index c01439d330..cc88cfa106 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -15,7 +15,7 @@ from frappe.utils.password import delete_all_passwords_for from frappe.model.naming import revert_series_if_last from frappe.utils.global_search import delete_for_document from frappe.desk.doctype.tag.tag import delete_tags_for_document -from frappe.exceptions import FileNotFoundError + doctypes_to_skip = ("Communication", "ToDo", "DocShare", "Email Unsubscribe", "Activity Log", "File", "Version", "Document Follow", "Comment" , "View Log", "Tag Link", "Notification Log", "Email Queue") From 2ccea73aa28af560ebc7eae31c9f49e0a891937f Mon Sep 17 00:00:00 2001 From: Krishna Kant Hati Date: Thu, 27 May 2021 01:52:28 +0530 Subject: [PATCH 194/868] fix: tooltip displays correct title --- frappe/public/js/frappe/form/controls/link.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index 43bd7443ab..af92f3b7a9 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -200,10 +200,11 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat if(frappe.model.can_create(doctype)) { // new item r.results.push({ - label: "" + html: "" + " " + __("Create a new {0}", [__(me.get_options())]) + "", + label: __("Create a new {0}", [__(me.get_options())]), value: "create_new__link_option", action: me.new_doc }); @@ -213,10 +214,11 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat if (locals && locals['DocType']) { // not applicable in web forms r.results.push({ - label: "" + html: "" + " " + __("Advanced Search") + "", + label: __("Advanced Search"), value: "advanced_search__link_option", action: me.open_advanced_search }); From 23406d031a7b6f849424f12203cf20537d94ff2e Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 27 May 2021 11:50:56 +0530 Subject: [PATCH 195/868] fix: Store assets.json directly in assets folder assets.json stores assets of all apps, so doesn't make sense to put it in frappe folder --- esbuild/esbuild.js | 7 +------ frappe/build.py | 2 +- frappe/utils/__init__.py | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/esbuild/esbuild.js b/esbuild/esbuild.js index ecf0d49511..5154adb634 100644 --- a/esbuild/esbuild.js +++ b/esbuild/esbuild.js @@ -343,12 +343,7 @@ async function write_assets_json(metafile) { } } - let assets_json_path = path.resolve( - assets_path, - "frappe", - "dist", - "assets.json" - ); + let assets_json_path = path.resolve(assets_path, "assets.json"); let assets_json; try { assets_json = await fs.promises.readFile(assets_json_path, "utf-8"); diff --git a/frappe/build.py b/frappe/build.py index c970ae3a28..1df42ca2e6 100644 --- a/frappe/build.py +++ b/frappe/build.py @@ -50,7 +50,7 @@ def build_missing_files(): development = frappe.local.conf.developer_mode or frappe.local.dev_server build_mode = "development" if development else "production" - assets_json = frappe.read_file(frappe.get_app_path('frappe', 'public', 'dist', 'assets.json')) + assets_json = frappe.read_file("assets/assets.json") if assets_json: assets_json = frappe.parse_json(assets_json) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 436dcba028..1470616ca9 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -809,7 +809,7 @@ def get_assets_json(): assets_json = None if not assets_json: - assets_json = frappe.read_file("assets/frappe/dist/assets.json") + assets_json = frappe.read_file("assets/assets.json") cache.set_value("assets_json", assets_json, shared=True) frappe.local.assets_json = frappe.safe_decode(assets_json) From d7af6173e742be615187728bc248fd8b243d41d7 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Thu, 27 May 2021 12:08:55 +0530 Subject: [PATCH 196/868] fix: new child page not visible fix --- frappe/public/js/desk.bundle.js | 3 + frappe/public/js/frappe/views/wiki.js | 31 +- yarn.lock | 1685 +++++++++---------------- 3 files changed, 624 insertions(+), 1095 deletions(-) diff --git a/frappe/public/js/desk.bundle.js b/frappe/public/js/desk.bundle.js index 66eb72cda0..0f75ae2d6a 100644 --- a/frappe/public/js/desk.bundle.js +++ b/frappe/public/js/desk.bundle.js @@ -67,6 +67,7 @@ import "./frappe/views/container.js"; import "./frappe/views/breadcrumbs.js"; import "./frappe/views/factory.js"; import "./frappe/views/pageview.js"; +import "./frappe/views/wiki.js"; import "./frappe/ui/toolbar/awesome_bar.js"; // import "./frappe/ui/toolbar/energy_points_notifications.js"; @@ -85,6 +86,8 @@ import "./frappe/views/workspace/workspace.js"; import "./frappe/widgets/widget_group.js"; +import "./frappe/wiki_blocks/blocks.js"; + import "./frappe/ui/sort_selector.html"; import "./frappe/ui/sort_selector.js"; diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index 955476861b..a0635f5494 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -118,16 +118,20 @@ frappe.views.Wiki = class Wiki { $item_container.parent().toggleClass('hidden'); } - let $drop_icon = $(``); - $drop_icon.appendTo(sidebar_control); - let drop_icon = $item_container.find('.drop-icon').get(0); - let child_item_section = $item_container.find('.sidebar-child-item').get(0); + this.add_drop_icon(item, sidebar_control, $item_container); + } + + add_drop_icon(item, sidebar_control, $item_container) { + let $child_item_section = $item_container.find('.sidebar-child-item'); + let $drop_icon = $(``) + .appendTo(sidebar_control); + if (this.all_pages.some(e => e.parent_page == item.name)) { - drop_icon.classList.remove('hidden'); - drop_icon.addEventListener('click', () => { - child_item_section.classList.toggle("hidden"); - let icon = $(drop_icon).find("use").attr("href")==="#icon-small-down" ? "#icon-small-up" : "#icon-small-down"; - $(drop_icon).find("use").attr("href", icon); + $drop_icon.removeClass('hidden'); + $drop_icon.on('click', () => { + let icon = $drop_icon.find("use").attr("href")==="#icon-small-down" ? "#icon-small-up" : "#icon-small-down"; + $drop_icon.find("use").attr("href", icon); + $child_item_section.toggleClass("hidden"); }); } } @@ -461,7 +465,14 @@ frappe.views.Wiki = class Wiki { if (!parent) { $sidebar_item.appendTo($sidebar); } else { - let $child_section = $sidebar.find(`[item-name="${parent}"] .sidebar-child-item`); + let $item_container = $sidebar.find(`[item-name="${parent}"]`); + let $child_section = $item_container.find('.sidebar-child-item'); + let $drop_icon = $item_container.find('.drop-icon'); + if (!$child_section[0]) { + $child_section = $(``) + .appendTo($item_container); + $drop_icon.toggleClass('hidden'); + } $sidebar_item.appendTo($child_section); $child_section.removeClass('hidden'); } diff --git a/yarn.lock b/yarn.lock index d902fedd10..04e2d35012 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,156 +2,120 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - "integrity" "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==" - "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz" - "version" "7.0.0" - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/highlight@^7.0.0": - "integrity" "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==" - "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz" - "version" "7.0.0" - dependencies: - "chalk" "^2.0.0" - "esutils" "^2.0.2" - "js-tokens" "^4.0.0" - -"@babel/runtime@^7.0.0-beta.46": - "integrity" "sha512-IvfvnMdSaLBateu0jfsYIpZTxAc2cKEXEMiezGGN75QcBcecDUKd3PgLAncT0oOgxKy8dd8hrJKj9MfzgfZd6g==" - "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.4.tgz" - "version" "7.3.4" - dependencies: - "regenerator-runtime" "^0.12.0" - -"@dabh/diagnostics@^2.0.2": - "integrity" "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==" - "resolved" "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "colorspace" "1.1.x" - "enabled" "2.0.x" - "kuler" "^2.0.0" +"@assemblyscript/loader@^0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.10.1.tgz#70e45678f06c72fa2e350e8553ec4a4d72b92e06" + integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg== "@deepcode/dcignore@^1.0.2": - "integrity" "sha512-DPgxtHuJwBORpqRkPXzzOT+uoPRVJmaN7LR+pmeL6DQM90kj6G6GFUH1i/YpRH8NbML8ZGEDwB9f9u4UwD2pzg==" - "resolved" "https://registry.npmjs.org/@deepcode/dcignore/-/dcignore-1.0.2.tgz" - "version" "1.0.2" + version "1.0.2" + resolved "https://registry.npmjs.org/@deepcode/dcignore/-/dcignore-1.0.2.tgz" + integrity sha512-DPgxtHuJwBORpqRkPXzzOT+uoPRVJmaN7LR+pmeL6DQM90kj6G6GFUH1i/YpRH8NbML8ZGEDwB9f9u4UwD2pzg== "@editorjs/checklist@^1.3.0": - "integrity" "sha512-087oW0oOIE5HX8llj4Eap/reFDFw8VCLlp6GU0E9GEp7f3zy2aV6KdFR+6dbYhZ50w7tSnkMpCAcSq1NXJeB4Q==" - "resolved" "https://registry.npmjs.org/@editorjs/checklist/-/checklist-1.3.0.tgz" - "version" "1.3.0" + version "1.3.0" + resolved "https://registry.npmjs.org/@editorjs/checklist/-/checklist-1.3.0.tgz" + integrity sha512-087oW0oOIE5HX8llj4Eap/reFDFw8VCLlp6GU0E9GEp7f3zy2aV6KdFR+6dbYhZ50w7tSnkMpCAcSq1NXJeB4Q== "@editorjs/editorjs@^2.20.0": - "integrity" "sha512-e6DWi8bMypFhovq9R6cefaDWVfrlVU++Q7ABp79+MxZIuC/SKAW5EtxBbKPL22H/Mc3bJIhZCxOqEl70HBh2yw==" - "resolved" "https://registry.npmjs.org/@editorjs/editorjs/-/editorjs-2.20.0.tgz" - "version" "2.20.0" + version "2.20.0" + resolved "https://registry.npmjs.org/@editorjs/editorjs/-/editorjs-2.20.0.tgz" + integrity sha512-e6DWi8bMypFhovq9R6cefaDWVfrlVU++Q7ABp79+MxZIuC/SKAW5EtxBbKPL22H/Mc3bJIhZCxOqEl70HBh2yw== dependencies: - "codex-notifier" "^1.1.2" - "codex-tooltip" "^1.0.1" + codex-notifier "^1.1.2" + codex-tooltip "^1.0.1" "@editorjs/header@^2.6.1": - "integrity" "sha512-EsnyVFv5uThpU9tbQ/dUPFCQoa/sBFy2n+9tN3wOXJGx7sjea4fdcacJ2UYhO+7pCgZ+aSgmMOyGLYHUFbchvA==" - "resolved" "https://registry.npmjs.org/@editorjs/header/-/header-2.6.1.tgz" - "version" "2.6.1" + version "2.6.1" + resolved "https://registry.npmjs.org/@editorjs/header/-/header-2.6.1.tgz" + integrity sha512-EsnyVFv5uThpU9tbQ/dUPFCQoa/sBFy2n+9tN3wOXJGx7sjea4fdcacJ2UYhO+7pCgZ+aSgmMOyGLYHUFbchvA== "@editorjs/list@^1.6.2": - "integrity" "sha512-OxowV0yuE11G01czYM1dEQlz1F37ehX0ak5vAbZ9ncSXrPh0fDRw/fBxTY654FlmrsQ40UFom3owSG++tLvVGw==" - "resolved" "https://registry.npmjs.org/@editorjs/list/-/list-1.6.2.tgz" - "version" "1.6.2" + version "1.6.2" + resolved "https://registry.npmjs.org/@editorjs/list/-/list-1.6.2.tgz" + integrity sha512-OxowV0yuE11G01czYM1dEQlz1F37ehX0ak5vAbZ9ncSXrPh0fDRw/fBxTY654FlmrsQ40UFom3owSG++tLvVGw== "@nodelib/fs.scandir@2.1.4": - "integrity" "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==" - "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz" - "version" "2.1.4" + version "2.1.4" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz" + integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== dependencies: "@nodelib/fs.stat" "2.0.4" - "run-parallel" "^1.1.9" + run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.4": - "integrity" "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==" - "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz" - "version" "2.0.4" +"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": + version "2.0.4" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz" + integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== "@nodelib/fs.walk@^1.2.3": - "integrity" "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==" - "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz" - "version" "1.2.6" + version "1.2.6" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz" + integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== dependencies: "@nodelib/fs.scandir" "2.1.4" - "fastq" "^1.6.0" + fastq "^1.6.0" "@octetstream/promisify@2.0.2": - "integrity" "sha512-7XHoRB61hxsz8lBQrjC1tq/3OEIgpvGWg6DKAdwi7WRzruwkmsdwmOoUXbU4Dtd4RSOMDwed0SkP3y8UlMt1Bg==" - "resolved" "https://registry.npmjs.org/@octetstream/promisify/-/promisify-2.0.2.tgz" - "version" "2.0.2" + version "2.0.2" + resolved "https://registry.npmjs.org/@octetstream/promisify/-/promisify-2.0.2.tgz" + integrity sha512-7XHoRB61hxsz8lBQrjC1tq/3OEIgpvGWg6DKAdwi7WRzruwkmsdwmOoUXbU4Dtd4RSOMDwed0SkP3y8UlMt1Bg== "@open-policy-agent/opa-wasm@^1.2.0": - "integrity" "sha512-CtUBTnzvDrT0NASa8IuGQTxFGgt2vxbLnMYuTA+uDFxOcA4uK4mGFgrhHJtxUZnWHiwemOvKKSY3BMCo7qiAsQ==" - "resolved" "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.2.0.tgz" - "version" "1.2.0" + version "1.2.0" + resolved "https://registry.npmjs.org/@open-policy-agent/opa-wasm/-/opa-wasm-1.2.0.tgz" + integrity sha512-CtUBTnzvDrT0NASa8IuGQTxFGgt2vxbLnMYuTA+uDFxOcA4uK4mGFgrhHJtxUZnWHiwemOvKKSY3BMCo7qiAsQ== dependencies: - "sprintf-js" "^1.1.2" - "utf8" "^3.0.0" + sprintf-js "^1.1.2" + utf8 "^3.0.0" "@sindresorhus/is@^0.14.0": - "integrity" "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" - "version" "0.14.0" + version "0.14.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@sindresorhus/is@^2.1.1": - "integrity" "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==" - "resolved" "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz" - "version" "2.1.1" + version "2.1.1" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz" + integrity sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg== -"@snyk/cli-interface@^2.0.3": - "integrity" "sha512-jmZyxVHqzYU1GfdnWCGdd68WY/lAzpPVyqalHazPj4tFJehrSfEFc82RMTYAMgXEJuvFRFIwhsvXh3sWUhIQmg==" - "resolved" "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.3.2.tgz" - "version" "2.3.2" - dependencies: - "tslib" "^1.9.3" - -"@snyk/cli-interface@^2.11.0", "@snyk/cli-interface@2.11.0": - "integrity" "sha512-T3xfDqrEFKclHGdJx4/5+D5F7e76/99f33guE4RTlVITBhy7VVnjz4t/NDr3UYqcC0MgAmiC4bSVYHnlshuwJw==" - "resolved" "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.11.0.tgz" - "version" "2.11.0" +"@snyk/cli-interface@2.11.0", "@snyk/cli-interface@^2.11.0": + version "2.11.0" + resolved "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.11.0.tgz" + integrity sha512-T3xfDqrEFKclHGdJx4/5+D5F7e76/99f33guE4RTlVITBhy7VVnjz4t/NDr3UYqcC0MgAmiC4bSVYHnlshuwJw== dependencies: "@types/graphlib" "^2" -"@snyk/cli-interface@^2.9.1": - "integrity" "sha512-C64bGtcQbh7941l7qgXFJ+FJIZdQtBHkPhKfGtUlCCMbC0FK0oaUmp6d7YPQxT4dEnkQdtlBT/eA2F6qIKbEng==" - "resolved" "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.9.2.tgz" - "version" "2.9.2" +"@snyk/cli-interface@^2.0.3": + version "2.3.2" + resolved "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.3.2.tgz" + integrity sha512-jmZyxVHqzYU1GfdnWCGdd68WY/lAzpPVyqalHazPj4tFJehrSfEFc82RMTYAMgXEJuvFRFIwhsvXh3sWUhIQmg== dependencies: - "@snyk/dep-graph" "1.19.4" - "@types/graphlib" "^2.1.7" - "tslib" "^1.9.3" + tslib "^1.9.3" -"@snyk/cli-interface@^2.9.2": - "integrity" "sha512-C64bGtcQbh7941l7qgXFJ+FJIZdQtBHkPhKfGtUlCCMbC0FK0oaUmp6d7YPQxT4dEnkQdtlBT/eA2F6qIKbEng==" - "resolved" "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.9.2.tgz" - "version" "2.9.2" +"@snyk/cli-interface@^2.9.1", "@snyk/cli-interface@^2.9.2": + version "2.9.2" + resolved "https://registry.npmjs.org/@snyk/cli-interface/-/cli-interface-2.9.2.tgz" + integrity sha512-C64bGtcQbh7941l7qgXFJ+FJIZdQtBHkPhKfGtUlCCMbC0FK0oaUmp6d7YPQxT4dEnkQdtlBT/eA2F6qIKbEng== dependencies: "@snyk/dep-graph" "1.19.4" "@types/graphlib" "^2.1.7" - "tslib" "^1.9.3" + tslib "^1.9.3" "@snyk/cocoapods-lockfile-parser@3.6.2": - "integrity" "sha512-ca2JKOnSRzYHJkhOB9gYmdRZHmd02b/uBd/S0D5W+L9nIMS7sUBV5jfhKwVgrYPIpVNIc0XCI9rxK4TfkQRpiA==" - "resolved" "https://registry.npmjs.org/@snyk/cocoapods-lockfile-parser/-/cocoapods-lockfile-parser-3.6.2.tgz" - "version" "3.6.2" + version "3.6.2" + resolved "https://registry.npmjs.org/@snyk/cocoapods-lockfile-parser/-/cocoapods-lockfile-parser-3.6.2.tgz" + integrity sha512-ca2JKOnSRzYHJkhOB9gYmdRZHmd02b/uBd/S0D5W+L9nIMS7sUBV5jfhKwVgrYPIpVNIc0XCI9rxK4TfkQRpiA== dependencies: "@snyk/dep-graph" "^1.23.1" "@types/js-yaml" "^3.12.1" - "js-yaml" "^3.13.1" - "tslib" "^1.10.0" + js-yaml "^3.13.1" + tslib "^1.10.0" "@snyk/code-client@3.4.0": - "integrity" "sha512-RY2IftAiWB7tp36Mcq7WiEwqoD8A/mqrD6N7oDWTxBOIqsH0t4djo/UibiWDJotaffO9aXXndOf3iZ/kTt+Rdg==" - "resolved" "https://registry.npmjs.org/@snyk/code-client/-/code-client-3.4.0.tgz" - "version" "3.4.0" + version "3.4.0" + resolved "https://registry.npmjs.org/@snyk/code-client/-/code-client-3.4.0.tgz" + integrity sha512-RY2IftAiWB7tp36Mcq7WiEwqoD8A/mqrD6N7oDWTxBOIqsH0t4djo/UibiWDJotaffO9aXXndOf3iZ/kTt+Rdg== dependencies: "@deepcode/dcignore" "^1.0.2" "@snyk/fast-glob" "^3.2.6-patch" @@ -162,275 +126,263 @@ "@types/micromatch" "^4.0.1" "@types/sarif" "^2.1.3" "@types/uuid" "^8.3.0" - "axios" "^0.21.1" - "ignore" "^5.1.8" - "lodash.chunk" "^4.2.0" - "lodash.omit" "^4.5.0" - "lodash.union" "^4.6.0" - "micromatch" "^4.0.2" - "queue" "^6.0.1" - "uuid" "^8.3.2" + axios "^0.21.1" + ignore "^5.1.8" + lodash.chunk "^4.2.0" + lodash.omit "^4.5.0" + lodash.union "^4.6.0" + micromatch "^4.0.2" + queue "^6.0.1" + uuid "^8.3.2" "@snyk/composer-lockfile-parser@^1.4.1": - "integrity" "sha512-wNANv235j95NFsQuODIXCiQZ9kcyg9fz92Kg1zoGvaP3kN/ma7fgCnvQL/dyml6iouQJR5aZovjhrrfEFoKtiQ==" - "resolved" "https://registry.npmjs.org/@snyk/composer-lockfile-parser/-/composer-lockfile-parser-1.4.1.tgz" - "version" "1.4.1" + version "1.4.1" + resolved "https://registry.npmjs.org/@snyk/composer-lockfile-parser/-/composer-lockfile-parser-1.4.1.tgz" + integrity sha512-wNANv235j95NFsQuODIXCiQZ9kcyg9fz92Kg1zoGvaP3kN/ma7fgCnvQL/dyml6iouQJR5aZovjhrrfEFoKtiQ== dependencies: - "lodash.findkey" "^4.6.0" - "lodash.get" "^4.4.2" - "lodash.invert" "^4.3.0" - "lodash.isempty" "^4.4.0" + lodash.findkey "^4.6.0" + lodash.get "^4.4.2" + lodash.invert "^4.3.0" + lodash.isempty "^4.4.0" -"@snyk/dep-graph@^1.19.3": - "integrity" "sha512-h3MMhjVm3BuIruwpDBqnMowKOG9viwr3TJHdIxTHulWKWSsPTTW1AAP3/RaK+UBp1y/Ua9yzeHncKIrzBdT5Nw==" - "resolved" "https://registry.npmjs.org/@snyk/dep-graph/-/dep-graph-1.19.4.tgz" - "version" "1.19.4" +"@snyk/dep-graph@1.19.4", "@snyk/dep-graph@^1.19.3": + version "1.19.4" + resolved "https://registry.npmjs.org/@snyk/dep-graph/-/dep-graph-1.19.4.tgz" + integrity sha512-h3MMhjVm3BuIruwpDBqnMowKOG9viwr3TJHdIxTHulWKWSsPTTW1AAP3/RaK+UBp1y/Ua9yzeHncKIrzBdT5Nw== dependencies: - "graphlib" "^2.1.8" - "lodash.isequal" "^4.5.0" - "object-hash" "^2.0.3" - "semver" "^6.0.0" - "source-map-support" "^0.5.19" - "tslib" "^1.13.0" + graphlib "^2.1.8" + lodash.isequal "^4.5.0" + object-hash "^2.0.3" + semver "^6.0.0" + source-map-support "^0.5.19" + tslib "^1.13.0" -"@snyk/dep-graph@^1", "@snyk/dep-graph@^1.21.0", "@snyk/dep-graph@^1.23.0", "@snyk/dep-graph@^1.23.1", "@snyk/dep-graph@^1.27.1", "@snyk/dep-graph@^1.28.0": - "integrity" "sha512-Oup9nAvb558jdNvbZah/vaBtOtCcizkdeS+OBQeBIqIffyer4mc4juSn4b1SFjCpu7AG7piio8Lj8k1B9ps6Tg==" - "resolved" "https://registry.npmjs.org/@snyk/dep-graph/-/dep-graph-1.28.0.tgz" - "version" "1.28.0" +"@snyk/dep-graph@^1.21.0", "@snyk/dep-graph@^1.23.0", "@snyk/dep-graph@^1.23.1", "@snyk/dep-graph@^1.27.1", "@snyk/dep-graph@^1.28.0": + version "1.28.0" + resolved "https://registry.npmjs.org/@snyk/dep-graph/-/dep-graph-1.28.0.tgz" + integrity sha512-Oup9nAvb558jdNvbZah/vaBtOtCcizkdeS+OBQeBIqIffyer4mc4juSn4b1SFjCpu7AG7piio8Lj8k1B9ps6Tg== dependencies: - "event-loop-spinner" "^2.1.0" - "lodash.clone" "^4.5.0" - "lodash.constant" "^3.0.0" - "lodash.filter" "^4.6.0" - "lodash.foreach" "^4.5.0" - "lodash.isempty" "^4.4.0" - "lodash.isequal" "^4.5.0" - "lodash.isfunction" "^3.0.9" - "lodash.isundefined" "^3.0.1" - "lodash.keys" "^4.2.0" - "lodash.map" "^4.6.0" - "lodash.reduce" "^4.6.0" - "lodash.size" "^4.2.0" - "lodash.transform" "^4.6.0" - "lodash.union" "^4.6.0" - "lodash.values" "^4.3.0" - "object-hash" "^2.0.3" - "semver" "^7.0.0" - "tslib" "^1.13.0" - -"@snyk/dep-graph@1.19.4": - "integrity" "sha512-h3MMhjVm3BuIruwpDBqnMowKOG9viwr3TJHdIxTHulWKWSsPTTW1AAP3/RaK+UBp1y/Ua9yzeHncKIrzBdT5Nw==" - "resolved" "https://registry.npmjs.org/@snyk/dep-graph/-/dep-graph-1.19.4.tgz" - "version" "1.19.4" - dependencies: - "graphlib" "^2.1.8" - "lodash.isequal" "^4.5.0" - "object-hash" "^2.0.3" - "semver" "^6.0.0" - "source-map-support" "^0.5.19" - "tslib" "^1.13.0" + event-loop-spinner "^2.1.0" + lodash.clone "^4.5.0" + lodash.constant "^3.0.0" + lodash.filter "^4.6.0" + lodash.foreach "^4.5.0" + lodash.isempty "^4.4.0" + lodash.isequal "^4.5.0" + lodash.isfunction "^3.0.9" + lodash.isundefined "^3.0.1" + lodash.keys "^4.2.0" + lodash.map "^4.6.0" + lodash.reduce "^4.6.0" + lodash.size "^4.2.0" + lodash.transform "^4.6.0" + lodash.union "^4.6.0" + lodash.values "^4.3.0" + object-hash "^2.0.3" + semver "^7.0.0" + tslib "^1.13.0" "@snyk/docker-registry-v2-client@1.13.9": - "integrity" "sha512-DIFLEhr8m1GrAwsLGInJmpcQMacjuhf3jcbpQTR+LeMvZA9IuKq+B7kqw2O2FzMiHMZmUb5z+tV+BR7+IUHkFQ==" - "resolved" "https://registry.npmjs.org/@snyk/docker-registry-v2-client/-/docker-registry-v2-client-1.13.9.tgz" - "version" "1.13.9" + version "1.13.9" + resolved "https://registry.npmjs.org/@snyk/docker-registry-v2-client/-/docker-registry-v2-client-1.13.9.tgz" + integrity sha512-DIFLEhr8m1GrAwsLGInJmpcQMacjuhf3jcbpQTR+LeMvZA9IuKq+B7kqw2O2FzMiHMZmUb5z+tV+BR7+IUHkFQ== dependencies: - "needle" "^2.5.0" - "parse-link-header" "^1.0.1" - "tslib" "^1.10.0" + needle "^2.5.0" + parse-link-header "^1.0.1" + tslib "^1.10.0" "@snyk/fast-glob@^3.2.6-patch": - "integrity" "sha512-E/Pfdze/WFfxwyuTFcfhQN1SwyUsc43yuCoW63RVBCaxTD6OzhVD2Pvc/Sy7BjiWUfmelzyKkIBpoow8zZX7Zg==" - "resolved" "https://registry.npmjs.org/@snyk/fast-glob/-/fast-glob-3.2.6-patch.tgz" - "version" "3.2.6-patch" + version "3.2.6-patch" + resolved "https://registry.npmjs.org/@snyk/fast-glob/-/fast-glob-3.2.6-patch.tgz" + integrity sha512-E/Pfdze/WFfxwyuTFcfhQN1SwyUsc43yuCoW63RVBCaxTD6OzhVD2Pvc/Sy7BjiWUfmelzyKkIBpoow8zZX7Zg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" "@snyk/glob-parent" "^5.1.2-patch.1" - "merge2" "^1.3.0" - "micromatch" "^4.0.2" - "picomatch" "^2.2.1" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" "@snyk/fix@1.518.0": - "integrity" "sha512-Cwh0wU8SxZgx1+qRgcGkMctNx9F6UCdUJYcCvKaYJNDEYQwpQat4nsLZsJeODYNx7Byh0ZnPrqakUck4qFrPvA==" - "resolved" "https://registry.npmjs.org/@snyk/fix/-/fix-1.518.0.tgz" - "version" "1.518.0" + version "1.518.0" + resolved "https://registry.npmjs.org/@snyk/fix/-/fix-1.518.0.tgz" + integrity sha512-Cwh0wU8SxZgx1+qRgcGkMctNx9F6UCdUJYcCvKaYJNDEYQwpQat4nsLZsJeODYNx7Byh0ZnPrqakUck4qFrPvA== dependencies: "@snyk/dep-graph" "^1.21.0" - "chalk" "4.1.0" - "debug" "^4.3.1" - "micromatch" "4.0.2" - "ora" "5.3.0" - "p-map" "^4.0.0" - "strip-ansi" "6.0.0" + chalk "4.1.0" + debug "^4.3.1" + micromatch "4.0.2" + ora "5.3.0" + p-map "^4.0.0" + strip-ansi "6.0.0" "@snyk/gemfile@1.2.0": - "integrity" "sha512-nI7ELxukf7pT4/VraL4iabtNNMz8mUo7EXlqCFld8O5z6mIMLX9llps24iPpaIZOwArkY3FWA+4t+ixyvtTSIA==" - "resolved" "https://registry.npmjs.org/@snyk/gemfile/-/gemfile-1.2.0.tgz" - "version" "1.2.0" + version "1.2.0" + resolved "https://registry.npmjs.org/@snyk/gemfile/-/gemfile-1.2.0.tgz" + integrity sha512-nI7ELxukf7pT4/VraL4iabtNNMz8mUo7EXlqCFld8O5z6mIMLX9llps24iPpaIZOwArkY3FWA+4t+ixyvtTSIA== "@snyk/glob-parent@^5.1.2-patch.1": - "integrity" "sha512-OkUPdHgxIWKAAzceG1nraNA0kgI+eS0I9wph8tll9UL0slD2mIWSj4mAqroGovaEXm8nHedoUfuDRGEb6wnzCQ==" - "resolved" "https://registry.npmjs.org/@snyk/glob-parent/-/glob-parent-5.1.2-patch.1.tgz" - "version" "5.1.2-patch.1" + version "5.1.2-patch.1" + resolved "https://registry.npmjs.org/@snyk/glob-parent/-/glob-parent-5.1.2-patch.1.tgz" + integrity sha512-OkUPdHgxIWKAAzceG1nraNA0kgI+eS0I9wph8tll9UL0slD2mIWSj4mAqroGovaEXm8nHedoUfuDRGEb6wnzCQ== dependencies: - "is-glob" "^4.0.1" + is-glob "^4.0.1" -"@snyk/graphlib@^2.1.9-patch.3", "@snyk/graphlib@2.1.9-patch.3": - "integrity" "sha512-bBY9b9ulfLj0v2Eer0yFYa3syVeIxVKl2EpxSrsVeT4mjA0CltZyHsF0JjoaGXP27nItTdJS5uVsj1NA+3aE+Q==" - "resolved" "https://registry.npmjs.org/@snyk/graphlib/-/graphlib-2.1.9-patch.3.tgz" - "version" "2.1.9-patch.3" +"@snyk/graphlib@2.1.9-patch.3", "@snyk/graphlib@^2.1.9-patch.3": + version "2.1.9-patch.3" + resolved "https://registry.npmjs.org/@snyk/graphlib/-/graphlib-2.1.9-patch.3.tgz" + integrity sha512-bBY9b9ulfLj0v2Eer0yFYa3syVeIxVKl2EpxSrsVeT4mjA0CltZyHsF0JjoaGXP27nItTdJS5uVsj1NA+3aE+Q== dependencies: - "lodash.clone" "^4.5.0" - "lodash.constant" "^3.0.0" - "lodash.filter" "^4.6.0" - "lodash.foreach" "^4.5.0" - "lodash.has" "^4.5.2" - "lodash.isempty" "^4.4.0" - "lodash.isfunction" "^3.0.9" - "lodash.isundefined" "^3.0.1" - "lodash.keys" "^4.2.0" - "lodash.map" "^4.6.0" - "lodash.reduce" "^4.6.0" - "lodash.size" "^4.2.0" - "lodash.transform" "^4.6.0" - "lodash.union" "^4.6.0" - "lodash.values" "^4.3.0" + lodash.clone "^4.5.0" + lodash.constant "^3.0.0" + lodash.filter "^4.6.0" + lodash.foreach "^4.5.0" + lodash.has "^4.5.2" + lodash.isempty "^4.4.0" + lodash.isfunction "^3.0.9" + lodash.isundefined "^3.0.1" + lodash.keys "^4.2.0" + lodash.map "^4.6.0" + lodash.reduce "^4.6.0" + lodash.size "^4.2.0" + lodash.transform "^4.6.0" + lodash.union "^4.6.0" + lodash.values "^4.3.0" "@snyk/inquirer@^7.3.3-patch": - "integrity" "sha512-aWiQSOacH2lOpJ1ard9ErABcH4tdJogdr+mg1U67iZJOPO9n2gFgAwz1TQJDyPkv4/A5mh4hT2rg03Uq+KBn2Q==" - "resolved" "https://registry.npmjs.org/@snyk/inquirer/-/inquirer-7.3.3-patch.tgz" - "version" "7.3.3-patch" + version "7.3.3-patch" + resolved "https://registry.npmjs.org/@snyk/inquirer/-/inquirer-7.3.3-patch.tgz" + integrity sha512-aWiQSOacH2lOpJ1ard9ErABcH4tdJogdr+mg1U67iZJOPO9n2gFgAwz1TQJDyPkv4/A5mh4hT2rg03Uq+KBn2Q== dependencies: - "ansi-escapes" "^4.2.1" - "chalk" "^4.1.0" - "cli-cursor" "^3.1.0" - "cli-width" "^3.0.0" - "external-editor" "^3.0.3" - "figures" "^3.0.0" - "lodash.assign" "^4.2.0" - "lodash.assignin" "^4.2.0" - "lodash.clone" "^4.5.0" - "lodash.defaults" "^4.2.0" - "lodash.filter" "^4.6.0" - "lodash.find" "^4.6.0" - "lodash.findindex" "^4.6.0" - "lodash.flatten" "^4.4.0" - "lodash.isboolean" "^3.0.3" - "lodash.isfunction" "^3.0.9" - "lodash.isnumber" "^3.0.3" - "lodash.isplainobject" "^4.0.6" - "lodash.isstring" "^4.0.1" - "lodash.last" "^3.0.0" - "lodash.map" "^4.6.0" - "lodash.omit" "^4.5.0" - "lodash.set" "^4.3.2" - "lodash.sum" "^4.0.2" - "lodash.uniq" "^4.5.0" - "mute-stream" "0.0.8" - "run-async" "^2.4.0" - "rxjs" "^6.6.0" - "string-width" "^4.1.0" - "strip-ansi" "^6.0.0" - "through" "^2.3.6" + ansi-escapes "^4.2.1" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash.assign "^4.2.0" + lodash.assignin "^4.2.0" + lodash.clone "^4.5.0" + lodash.defaults "^4.2.0" + lodash.filter "^4.6.0" + lodash.find "^4.6.0" + lodash.findindex "^4.6.0" + lodash.flatten "^4.4.0" + lodash.isboolean "^3.0.3" + lodash.isfunction "^3.0.9" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.last "^3.0.0" + lodash.map "^4.6.0" + lodash.omit "^4.5.0" + lodash.set "^4.3.2" + lodash.sum "^4.0.2" + lodash.uniq "^4.5.0" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.6.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" "@snyk/java-call-graph-builder@1.19.1": - "integrity" "sha512-bxjHef5Qm3pNc+BrFlxMudmSSbOjA395ZqBddc+dvsFHoHeyNbiY56Y1JSGUlTgjRM+PKNPBiCuELTSMaROeZg==" - "resolved" "https://registry.npmjs.org/@snyk/java-call-graph-builder/-/java-call-graph-builder-1.19.1.tgz" - "version" "1.19.1" + version "1.19.1" + resolved "https://registry.npmjs.org/@snyk/java-call-graph-builder/-/java-call-graph-builder-1.19.1.tgz" + integrity sha512-bxjHef5Qm3pNc+BrFlxMudmSSbOjA395ZqBddc+dvsFHoHeyNbiY56Y1JSGUlTgjRM+PKNPBiCuELTSMaROeZg== dependencies: "@snyk/graphlib" "2.1.9-patch.3" - "ci-info" "^2.0.0" - "debug" "^4.1.1" - "glob" "^7.1.6" - "jszip" "^3.2.2" - "needle" "^2.3.3" - "progress" "^2.0.3" - "snyk-config" "^4.0.0-rc.2" - "source-map-support" "^0.5.7" - "temp-dir" "^2.0.0" - "tmp" "^0.2.1" - "tslib" "^1.9.3" - "xml-js" "^1.6.11" + ci-info "^2.0.0" + debug "^4.1.1" + glob "^7.1.6" + jszip "^3.2.2" + needle "^2.3.3" + progress "^2.0.3" + snyk-config "^4.0.0-rc.2" + source-map-support "^0.5.7" + temp-dir "^2.0.0" + tmp "^0.2.1" + tslib "^1.9.3" + xml-js "^1.6.11" "@snyk/java-call-graph-builder@1.20.0": - "integrity" "sha512-NX8bpIu7oG5cuSSm6WvtxqcCuJs2gRjtKhtuSeF1p5TYXyESs3FXQ0nHjfY90LiyTTc+PW/UBq6SKbBA6bCBww==" - "resolved" "https://registry.npmjs.org/@snyk/java-call-graph-builder/-/java-call-graph-builder-1.20.0.tgz" - "version" "1.20.0" + version "1.20.0" + resolved "https://registry.npmjs.org/@snyk/java-call-graph-builder/-/java-call-graph-builder-1.20.0.tgz" + integrity sha512-NX8bpIu7oG5cuSSm6WvtxqcCuJs2gRjtKhtuSeF1p5TYXyESs3FXQ0nHjfY90LiyTTc+PW/UBq6SKbBA6bCBww== dependencies: "@snyk/graphlib" "2.1.9-patch.3" - "ci-info" "^2.0.0" - "debug" "^4.1.1" - "glob" "^7.1.6" - "jszip" "^3.2.2" - "needle" "^2.3.3" - "progress" "^2.0.3" - "snyk-config" "^4.0.0-rc.2" - "source-map-support" "^0.5.7" - "temp-dir" "^2.0.0" - "tmp" "^0.2.1" - "tslib" "^1.9.3" - "xml-js" "^1.6.11" + ci-info "^2.0.0" + debug "^4.1.1" + glob "^7.1.6" + jszip "^3.2.2" + needle "^2.3.3" + progress "^2.0.3" + snyk-config "^4.0.0-rc.2" + source-map-support "^0.5.7" + temp-dir "^2.0.0" + tmp "^0.2.1" + tslib "^1.9.3" + xml-js "^1.6.11" "@snyk/mix-parser@^1.1.0": - "integrity" "sha512-KmX4Le+1M01m6kM2UeDColzMZctrSqoMGajqcRHR3dLpCyHE3nzZzPeOWjbUVgjQlTX07oQvq9udSJGZJ/+Gdg==" - "resolved" "https://registry.npmjs.org/@snyk/mix-parser/-/mix-parser-1.1.1.tgz" - "version" "1.1.1" + version "1.1.1" + resolved "https://registry.npmjs.org/@snyk/mix-parser/-/mix-parser-1.1.1.tgz" + integrity sha512-KmX4Le+1M01m6kM2UeDColzMZctrSqoMGajqcRHR3dLpCyHE3nzZzPeOWjbUVgjQlTX07oQvq9udSJGZJ/+Gdg== dependencies: "@snyk/dep-graph" "^1.28.0" - "tslib" "^2.0.0" + tslib "^2.0.0" "@snyk/rpm-parser@^2.0.0": - "integrity" "sha512-bWjQY5Xk3TcfVpeo8M5BhhSUEdPr2P19AWW13CHPu6sFZkckLWEcjQycnBsVD6RBmxGXecJ1YNui8dq6soHoYQ==" - "resolved" "https://registry.npmjs.org/@snyk/rpm-parser/-/rpm-parser-2.0.0.tgz" - "version" "2.0.0" + version "2.0.0" + resolved "https://registry.npmjs.org/@snyk/rpm-parser/-/rpm-parser-2.0.0.tgz" + integrity sha512-bWjQY5Xk3TcfVpeo8M5BhhSUEdPr2P19AWW13CHPu6sFZkckLWEcjQycnBsVD6RBmxGXecJ1YNui8dq6soHoYQ== dependencies: - "event-loop-spinner" "^2.0.0" + event-loop-spinner "^2.0.0" "@snyk/snyk-cocoapods-plugin@2.5.2": - "integrity" "sha512-WHhnwyoGOhjFOjBXqUfszD84SErrtjHjium/4xFbqKpEE+yuwxs8OwV/S29BtxhYiGtjpD1azv5QtH30VUMl0A==" - "resolved" "https://registry.npmjs.org/@snyk/snyk-cocoapods-plugin/-/snyk-cocoapods-plugin-2.5.2.tgz" - "version" "2.5.2" + version "2.5.2" + resolved "https://registry.npmjs.org/@snyk/snyk-cocoapods-plugin/-/snyk-cocoapods-plugin-2.5.2.tgz" + integrity sha512-WHhnwyoGOhjFOjBXqUfszD84SErrtjHjium/4xFbqKpEE+yuwxs8OwV/S29BtxhYiGtjpD1azv5QtH30VUMl0A== dependencies: "@snyk/cli-interface" "^2.11.0" "@snyk/cocoapods-lockfile-parser" "3.6.2" "@snyk/dep-graph" "^1.23.1" - "source-map-support" "^0.5.7" - "tslib" "^2.0.0" + source-map-support "^0.5.7" + tslib "^2.0.0" "@snyk/snyk-docker-pull@3.2.3": - "integrity" "sha512-hiFiSmWGLc2tOI7FfgIhVdFzO2f69im8O6p3OV4xEZ/Ss1l58vwtqudItoswsk7wj/azRlgfBW8wGu2MjoudQg==" - "resolved" "https://registry.npmjs.org/@snyk/snyk-docker-pull/-/snyk-docker-pull-3.2.3.tgz" - "version" "3.2.3" + version "3.2.3" + resolved "https://registry.npmjs.org/@snyk/snyk-docker-pull/-/snyk-docker-pull-3.2.3.tgz" + integrity sha512-hiFiSmWGLc2tOI7FfgIhVdFzO2f69im8O6p3OV4xEZ/Ss1l58vwtqudItoswsk7wj/azRlgfBW8wGu2MjoudQg== dependencies: "@snyk/docker-registry-v2-client" "1.13.9" - "child-process" "^1.0.2" - "tar-stream" "^2.1.2" - "tmp" "^0.1.0" + child-process "^1.0.2" + tar-stream "^2.1.2" + tmp "^0.1.0" "@snyk/snyk-hex-plugin@1.0.0": - "integrity" "sha512-ZydVdZ5kDpPDoehQnNHN3wZ6c470k5DPLJtWMoyfzlnCU2+y1rsUEdn4yhttn60RPx3JiLGwmckeDvZw8BqnGQ==" - "resolved" "https://registry.npmjs.org/@snyk/snyk-hex-plugin/-/snyk-hex-plugin-1.0.0.tgz" - "version" "1.0.0" + version "1.0.0" + resolved "https://registry.npmjs.org/@snyk/snyk-hex-plugin/-/snyk-hex-plugin-1.0.0.tgz" + integrity sha512-ZydVdZ5kDpPDoehQnNHN3wZ6c470k5DPLJtWMoyfzlnCU2+y1rsUEdn4yhttn60RPx3JiLGwmckeDvZw8BqnGQ== dependencies: "@snyk/dep-graph" "^1.28.0" "@snyk/mix-parser" "^1.1.0" - "debug" "^4.3.1" - "tslib" "^2.0.0" + debug "^4.3.1" + tslib "^2.0.0" "@szmarczak/http-timer@^1.1.2": - "integrity" "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==" - "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" - "version" "1.1.2" + version "1.1.2" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== dependencies: - "defer-to-connect" "^1.0.1" + defer-to-connect "^1.0.1" "@szmarczak/http-timer@^4.0.5": - "integrity" "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==" - "resolved" "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz" - "version" "4.0.5" + version "4.0.5" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz" + integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== dependencies: - "defer-to-connect" "^2.0.0" + defer-to-connect "^2.0.0" "@types/babel-types@*", "@types/babel-types@^7.0.0": version "7.0.9" @@ -445,14 +397,14 @@ "@types/babel-types" "*" "@types/braces@*": - "integrity" "sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw==" - "resolved" "https://registry.npmjs.org/@types/braces/-/braces-3.0.0.tgz" - "version" "3.0.0" + version "3.0.0" + resolved "https://registry.npmjs.org/@types/braces/-/braces-3.0.0.tgz" + integrity sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw== "@types/cacheable-request@^6.0.1": - "integrity" "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==" - "resolved" "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz" - "version" "6.0.1" + version "6.0.1" + resolved "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz" + integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== dependencies: "@types/http-cache-semantics" "*" "@types/keyv" "*" @@ -460,106 +412,101 @@ "@types/responselike" "*" "@types/color-name@^1.1.1": - "integrity" "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - "resolved" "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz" - "version" "1.1.1" + version "1.1.1" + resolved "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== "@types/debug@^4.1.4": - "integrity" "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" - "resolved" "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz" - "version" "4.1.5" + version "4.1.5" + resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz" + integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== "@types/flat-cache@^2.0.0": - "integrity" "sha512-fHeEsm9hvmZ+QHpw6Fkvf19KIhuqnYLU6vtWLjd5BsMd/qVi7iTkMioDZl0mQmfNRA1A6NwvhrSRNr9hGYZGww==" - "resolved" "https://registry.npmjs.org/@types/flat-cache/-/flat-cache-2.0.0.tgz" - "version" "2.0.0" + version "2.0.0" + resolved "https://registry.npmjs.org/@types/flat-cache/-/flat-cache-2.0.0.tgz" + integrity sha512-fHeEsm9hvmZ+QHpw6Fkvf19KIhuqnYLU6vtWLjd5BsMd/qVi7iTkMioDZl0mQmfNRA1A6NwvhrSRNr9hGYZGww== "@types/graphlib@^2", "@types/graphlib@^2.1.7": - "integrity" "sha512-K7T1n6U2HbTYu+SFHlBjz/RH74OA2D/zF1qlzn8uXbvB4uRg7knOM85ugS2bbXI1TXMh7rLqk4OVRwIwEBaixg==" - "resolved" "https://registry.npmjs.org/@types/graphlib/-/graphlib-2.1.7.tgz" - "version" "2.1.7" + version "2.1.7" + resolved "https://registry.npmjs.org/@types/graphlib/-/graphlib-2.1.7.tgz" + integrity sha512-K7T1n6U2HbTYu+SFHlBjz/RH74OA2D/zF1qlzn8uXbvB4uRg7knOM85ugS2bbXI1TXMh7rLqk4OVRwIwEBaixg== "@types/http-cache-semantics@*": - "integrity" "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" - "resolved" "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz" - "version" "4.0.0" + version "4.0.0" + resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz" + integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== "@types/js-yaml@^3.12.1": - "integrity" "sha512-0CFu/g4mDSNkodVwWijdlr8jH7RoplRWNgovjFLEZeT+QEbbZXjBmCe3HwaWheAlCbHwomTwzZoSedeOycABug==" - "resolved" "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.2.tgz" - "version" "3.12.2" + version "3.12.2" + resolved "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.2.tgz" + integrity sha512-0CFu/g4mDSNkodVwWijdlr8jH7RoplRWNgovjFLEZeT+QEbbZXjBmCe3HwaWheAlCbHwomTwzZoSedeOycABug== "@types/keyv@*": - "integrity" "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==" - "resolved" "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz" - "version" "3.1.1" + version "3.1.1" + resolved "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz" + integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== dependencies: "@types/node" "*" "@types/lodash.chunk@^4.2.6": - "integrity" "sha512-SPlusB7jxXyGcTXYcUdWr7WmhArO/rmTq54VN88iKMxGUhyg79I4Q8n4riGn3kjaTjOJrVlHhxgX/d7woak5BQ==" - "resolved" "https://registry.npmjs.org/@types/lodash.chunk/-/lodash.chunk-4.2.6.tgz" - "version" "4.2.6" + version "4.2.6" + resolved "https://registry.npmjs.org/@types/lodash.chunk/-/lodash.chunk-4.2.6.tgz" + integrity sha512-SPlusB7jxXyGcTXYcUdWr7WmhArO/rmTq54VN88iKMxGUhyg79I4Q8n4riGn3kjaTjOJrVlHhxgX/d7woak5BQ== dependencies: "@types/lodash" "*" "@types/lodash.omit@^4.5.6": - "integrity" "sha512-KXPpOSNX2h0DAG2w7ajpk7TXvWF28ZHs5nJhOJyP0BQHkehgr948RVsToItMme6oi0XJkp19CbuNXkIX8FiBlQ==" - "resolved" "https://registry.npmjs.org/@types/lodash.omit/-/lodash.omit-4.5.6.tgz" - "version" "4.5.6" + version "4.5.6" + resolved "https://registry.npmjs.org/@types/lodash.omit/-/lodash.omit-4.5.6.tgz" + integrity sha512-KXPpOSNX2h0DAG2w7ajpk7TXvWF28ZHs5nJhOJyP0BQHkehgr948RVsToItMme6oi0XJkp19CbuNXkIX8FiBlQ== dependencies: "@types/lodash" "*" "@types/lodash.union@^4.6.6": - "integrity" "sha512-Wu0ZEVNcyCz8eAn6TlUbYWZoGbH9E+iOHxAZbwUoCEXdUiy6qpcz5o44mMXViM4vlPLLCPlkAubEP1gokoSZaw==" - "resolved" "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.6.tgz" - "version" "4.6.6" + version "4.6.6" + resolved "https://registry.npmjs.org/@types/lodash.union/-/lodash.union-4.6.6.tgz" + integrity sha512-Wu0ZEVNcyCz8eAn6TlUbYWZoGbH9E+iOHxAZbwUoCEXdUiy6qpcz5o44mMXViM4vlPLLCPlkAubEP1gokoSZaw== dependencies: "@types/lodash" "*" "@types/lodash@*": - "integrity" "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==" - "resolved" "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz" - "version" "4.14.168" + version "4.14.168" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz" + integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q== "@types/micromatch@^4.0.1": - "integrity" "sha512-my6fLBvpY70KattTNzYOK6KU1oR1+UCz9ug/JbcF5UrEmeCt9P7DV2t7L8+t18mMPINqGQCE4O8PLOPbI84gxw==" - "resolved" "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.1.tgz" - "version" "4.0.1" + version "4.0.1" + resolved "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.1.tgz" + integrity sha512-my6fLBvpY70KattTNzYOK6KU1oR1+UCz9ug/JbcF5UrEmeCt9P7DV2t7L8+t18mMPINqGQCE4O8PLOPbI84gxw== dependencies: "@types/braces" "*" "@types/node@*": - "integrity" "sha512-oVeL12C6gQS/GAExndigSaLxTrKpQPxewx9bOcwfvJiJge4rr7wNaph4J+ns5hrmIV2as5qxqN8YKthn9qh0jw==" - "resolved" "https://registry.npmjs.org/@types/node/-/node-13.7.4.tgz" - "version" "13.7.4" + version "13.7.4" + resolved "https://registry.npmjs.org/@types/node/-/node-13.7.4.tgz" + integrity sha512-oVeL12C6gQS/GAExndigSaLxTrKpQPxewx9bOcwfvJiJge4rr7wNaph4J+ns5hrmIV2as5qxqN8YKthn9qh0jw== "@types/q@^1.5.1": - "integrity" "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==" - "resolved" "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz" - "version" "1.5.1" + version "1.5.1" + resolved "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz" + integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== "@types/responselike@*", "@types/responselike@^1.0.0": - "integrity" "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==" - "resolved" "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz" - "version" "1.0.0" + version "1.0.0" + resolved "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== dependencies: "@types/node" "*" "@types/sarif@^2.1.3": - "integrity" "sha512-zf+EoIplTkQW2TV2mwtJtlI0g540Z3Rs9tX9JqRAtyjnDCqkP+eMTgWCj3PGNbQpi+WXAjvC3Ou/dvvX2sLK4w==" - "resolved" "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.3.tgz" - "version" "2.1.3" + version "2.1.3" + resolved "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.3.tgz" + integrity sha512-zf+EoIplTkQW2TV2mwtJtlI0g540Z3Rs9tX9JqRAtyjnDCqkP+eMTgWCj3PGNbQpi+WXAjvC3Ou/dvvX2sLK4w== "@types/uuid@^8.3.0": - "integrity" "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==" - "resolved" "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz" - "version" "8.3.0" - -"editorjs-undo@^0.1.6": - "integrity" "sha512-zVHPnBf2mcI8hWT9Eu8H3bGDEcMj4gppXbQjJW11Aa8Kdy2SVBGhM6fS59OUlBsm8iHWLxuoG2NUIfy9Rd30sw==" - "resolved" "https://registry.npmjs.org/editorjs-undo/-/editorjs-undo-0.1.6.tgz" - "version" "0.1.6" + version "8.3.0" + resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz" + integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ== "@vue/component-compiler-utils@^3.0.0": version "3.2.0" @@ -1403,6 +1350,16 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +codex-notifier@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/codex-notifier/-/codex-notifier-1.1.2.tgz#a733079185f4c927fa296f1d71eb8753fe080895" + integrity sha512-DCp6xe/LGueJ1N5sXEwcBc3r3PyVkEEDNWCVigfvywAkeXcZMk9K41a31tkEFBW0Ptlwji6/JlAb49E3Yrxbtg== + +codex-tooltip@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/codex-tooltip/-/codex-tooltip-1.0.2.tgz#81a9d3e2937658c6e5312106b47b9f094ff7be63" + integrity sha512-oC+Bu5X/zyhbPydgMSLWKoM/+vkJMqaLWu3Dt/jZgXS3MWK23INwC5DMBrVXZSufAFk0i0SUni38k9rLMyZn/w== + color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2079,6 +2036,11 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +editorjs-undo@^0.1.6: + version "0.1.6" + resolved "https://registry.npmjs.org/editorjs-undo/-/editorjs-undo-0.1.6.tgz" + integrity sha512-zVHPnBf2mcI8hWT9Eu8H3bGDEcMj4gppXbQjJW11Aa8Kdy2SVBGhM6fS59OUlBsm8iHWLxuoG2NUIfy9Rd30sw== + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3747,7 +3709,7 @@ latest-version@^5.0.0: resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== dependencies: - "package-json" "^6.3.0" + package-json "^6.3.0" launch-editor@^2.2.1: version "2.2.1" @@ -4547,13 +4509,6 @@ node-sass@^4.14.1: stdout-stream "^1.4.0" "true-case-path" "^1.0.2" -"nopt@~1.0.10": - "integrity" "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=" - "resolved" "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz" - "version" "1.0.10" - dependencies: - "abbrev" "1" - "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -6323,271 +6278,271 @@ snyk-cpp-plugin@2.2.1: integrity sha512-NFwVLMCqKTocY66gcim0ukF6e31VRDJqDapg5sy3vCHqlD1OCNUXSK/aI4VQEEndDrsnFmQepsL5KpEU0dDRIQ== dependencies: "@snyk/dep-graph" "^1.19.3" - "chalk" "^4.1.0" - "debug" "^4.1.1" - "hosted-git-info" "^3.0.7" - "tslib" "^2.0.0" + chalk "^4.1.0" + debug "^4.1.1" + hosted-git-info "^3.0.7" + tslib "^2.0.0" -"snyk-docker-plugin@4.19.3": - "integrity" "sha512-5WkXyT7uY5NrTOvEqxeMqb6dDcskT3c/gbHUTOyPuvE6tMut+OOYK8RRXbwZFeLzpS8asq4e1R7U7syYG3VXwg==" - "resolved" "https://registry.npmjs.org/snyk-docker-plugin/-/snyk-docker-plugin-4.19.3.tgz" - "version" "4.19.3" +snyk-docker-plugin@4.19.3: + version "4.19.3" + resolved "https://registry.npmjs.org/snyk-docker-plugin/-/snyk-docker-plugin-4.19.3.tgz" + integrity sha512-5WkXyT7uY5NrTOvEqxeMqb6dDcskT3c/gbHUTOyPuvE6tMut+OOYK8RRXbwZFeLzpS8asq4e1R7U7syYG3VXwg== dependencies: "@snyk/dep-graph" "^1.21.0" "@snyk/rpm-parser" "^2.0.0" "@snyk/snyk-docker-pull" "3.2.3" - "chalk" "^2.4.2" - "debug" "^4.1.1" - "docker-modem" "2.1.3" - "dockerfile-ast" "0.2.0" - "elfy" "^1.0.0" - "event-loop-spinner" "^2.0.0" - "gunzip-maybe" "^1.4.2" - "mkdirp" "^1.0.4" - "semver" "^7.3.4" - "snyk-nodejs-lockfile-parser" "1.30.2" - "tar-stream" "^2.1.0" - "tmp" "^0.2.1" - "tslib" "^1" - "uuid" "^8.2.0" + chalk "^2.4.2" + debug "^4.1.1" + docker-modem "2.1.3" + dockerfile-ast "0.2.0" + elfy "^1.0.0" + event-loop-spinner "^2.0.0" + gunzip-maybe "^1.4.2" + mkdirp "^1.0.4" + semver "^7.3.4" + snyk-nodejs-lockfile-parser "1.30.2" + tar-stream "^2.1.0" + tmp "^0.2.1" + tslib "^1" + uuid "^8.2.0" -"snyk-go-parser@1.4.1": - "integrity" "sha512-StU3uHB85VMEkcgXta63M0Fgd+9cs5sMCjQXTBoYTdE4dxarPn7U67yCuwkRRdZdny1ZXtzfY8LKns9i0+dy9w==" - "resolved" "https://registry.npmjs.org/snyk-go-parser/-/snyk-go-parser-1.4.1.tgz" - "version" "1.4.1" +snyk-go-parser@1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/snyk-go-parser/-/snyk-go-parser-1.4.1.tgz" + integrity sha512-StU3uHB85VMEkcgXta63M0Fgd+9cs5sMCjQXTBoYTdE4dxarPn7U67yCuwkRRdZdny1ZXtzfY8LKns9i0+dy9w== dependencies: - "toml" "^3.0.0" - "tslib" "^1.10.0" + toml "^3.0.0" + tslib "^1.10.0" -"snyk-go-plugin@1.17.0": - "integrity" "sha512-1jAYPRgMapO2BYL+HWsUq5gsAiDGmI0Pn7omc0lk24tcUOMhUB+1hb0u9WBMNzHvXBjevBkjOctjpnt2hMKN6Q==" - "resolved" "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.17.0.tgz" - "version" "1.17.0" +snyk-go-plugin@1.17.0: + version "1.17.0" + resolved "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.17.0.tgz" + integrity sha512-1jAYPRgMapO2BYL+HWsUq5gsAiDGmI0Pn7omc0lk24tcUOMhUB+1hb0u9WBMNzHvXBjevBkjOctjpnt2hMKN6Q== dependencies: "@snyk/dep-graph" "^1.23.1" "@snyk/graphlib" "2.1.9-patch.3" - "debug" "^4.1.1" - "snyk-go-parser" "1.4.1" - "tmp" "0.2.1" - "tslib" "^1.10.0" + debug "^4.1.1" + snyk-go-parser "1.4.1" + tmp "0.2.1" + tslib "^1.10.0" -"snyk-gradle-plugin@3.14.0": - "integrity" "sha512-2A8ifM91TyzSx/U2fYvHXbaCRVsEx60hGFQjbSH9Hl9AokxEzMi2qti7wsObs1jUX2m198D1mdXu4k/Y1jWxXg==" - "resolved" "https://registry.npmjs.org/snyk-gradle-plugin/-/snyk-gradle-plugin-3.14.0.tgz" - "version" "3.14.0" +snyk-gradle-plugin@3.14.0: + version "3.14.0" + resolved "https://registry.npmjs.org/snyk-gradle-plugin/-/snyk-gradle-plugin-3.14.0.tgz" + integrity sha512-2A8ifM91TyzSx/U2fYvHXbaCRVsEx60hGFQjbSH9Hl9AokxEzMi2qti7wsObs1jUX2m198D1mdXu4k/Y1jWxXg== dependencies: "@snyk/cli-interface" "2.11.0" "@snyk/dep-graph" "^1.28.0" "@snyk/java-call-graph-builder" "1.20.0" "@types/debug" "^4.1.4" - "chalk" "^3.0.0" - "debug" "^4.1.1" - "tmp" "0.2.1" - "tslib" "^2.0.0" + chalk "^3.0.0" + debug "^4.1.1" + tmp "0.2.1" + tslib "^2.0.0" -"snyk-module@^3.0.0", "snyk-module@^3.1.0", "snyk-module@3.1.0": - "integrity" "sha512-HHuOYEAACpUpkFgU8HT57mmxmonaJ4O3YADoSkVhnhkmJ+AowqZyJOau703dYHNrq2DvQ7qYw81H7yyxS1Nfjw==" - "resolved" "https://registry.npmjs.org/snyk-module/-/snyk-module-3.1.0.tgz" - "version" "3.1.0" +snyk-module@3.1.0, snyk-module@^3.0.0, snyk-module@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/snyk-module/-/snyk-module-3.1.0.tgz" + integrity sha512-HHuOYEAACpUpkFgU8HT57mmxmonaJ4O3YADoSkVhnhkmJ+AowqZyJOau703dYHNrq2DvQ7qYw81H7yyxS1Nfjw== dependencies: - "debug" "^4.1.1" - "hosted-git-info" "^3.0.4" + debug "^4.1.1" + hosted-git-info "^3.0.4" -"snyk-mvn-plugin@2.25.3": - "integrity" "sha512-JAxOThX51JDbgMMjp3gQDVi07G9VgTYSF06QC7f5LNA0zoXNr743e2rm78RGw5bqE3JRjZxEghiLHPPuvS5DDg==" - "resolved" "https://registry.npmjs.org/snyk-mvn-plugin/-/snyk-mvn-plugin-2.25.3.tgz" - "version" "2.25.3" +snyk-mvn-plugin@2.25.3: + version "2.25.3" + resolved "https://registry.npmjs.org/snyk-mvn-plugin/-/snyk-mvn-plugin-2.25.3.tgz" + integrity sha512-JAxOThX51JDbgMMjp3gQDVi07G9VgTYSF06QC7f5LNA0zoXNr743e2rm78RGw5bqE3JRjZxEghiLHPPuvS5DDg== dependencies: "@snyk/cli-interface" "2.11.0" "@snyk/dep-graph" "^1.23.1" "@snyk/java-call-graph-builder" "1.19.1" - "debug" "^4.1.1" - "glob" "^7.1.6" - "needle" "^2.5.0" - "tmp" "^0.1.0" - "tslib" "1.11.1" + debug "^4.1.1" + glob "^7.1.6" + needle "^2.5.0" + tmp "^0.1.0" + tslib "1.11.1" -"snyk-nodejs-lockfile-parser@1.30.2": - "integrity" "sha512-wI3VXVYO/ok0uaQm5i+Koo4rKBNilYC/QRIQFlyGbZXf+WBdRcTBKVDfTy8uNfUhMRSGzd84lNclMnetU9Y+vw==" - "resolved" "https://registry.npmjs.org/snyk-nodejs-lockfile-parser/-/snyk-nodejs-lockfile-parser-1.30.2.tgz" - "version" "1.30.2" +snyk-nodejs-lockfile-parser@1.30.2: + version "1.30.2" + resolved "https://registry.npmjs.org/snyk-nodejs-lockfile-parser/-/snyk-nodejs-lockfile-parser-1.30.2.tgz" + integrity sha512-wI3VXVYO/ok0uaQm5i+Koo4rKBNilYC/QRIQFlyGbZXf+WBdRcTBKVDfTy8uNfUhMRSGzd84lNclMnetU9Y+vw== dependencies: "@snyk/graphlib" "2.1.9-patch.3" "@yarnpkg/lockfile" "^1.1.0" - "event-loop-spinner" "^2.0.0" - "got" "11.4.0" - "lodash.clonedeep" "^4.5.0" - "lodash.flatmap" "^4.5.0" - "lodash.isempty" "^4.4.0" - "lodash.set" "^4.3.2" - "lodash.topairs" "^4.3.0" - "p-map" "2.1.0" - "snyk-config" "^4.0.0-rc.2" - "tslib" "^1.9.3" - "uuid" "^8.3.0" - "yaml" "^1.9.2" + event-loop-spinner "^2.0.0" + got "11.4.0" + lodash.clonedeep "^4.5.0" + lodash.flatmap "^4.5.0" + lodash.isempty "^4.4.0" + lodash.set "^4.3.2" + lodash.topairs "^4.3.0" + p-map "2.1.0" + snyk-config "^4.0.0-rc.2" + tslib "^1.9.3" + uuid "^8.3.0" + yaml "^1.9.2" -"snyk-nodejs-lockfile-parser@1.31.1": - "integrity" "sha512-MU1V2zS5ziLGMUL6PXxPvJuZ281wvawjQQ1c8TW697Jjkhd8hPZcW4IzMu52ok0zsmQcVZh8sVniBEHIePCfLQ==" - "resolved" "https://registry.npmjs.org/snyk-nodejs-lockfile-parser/-/snyk-nodejs-lockfile-parser-1.31.1.tgz" - "version" "1.31.1" +snyk-nodejs-lockfile-parser@1.31.1: + version "1.31.1" + resolved "https://registry.npmjs.org/snyk-nodejs-lockfile-parser/-/snyk-nodejs-lockfile-parser-1.31.1.tgz" + integrity sha512-MU1V2zS5ziLGMUL6PXxPvJuZ281wvawjQQ1c8TW697Jjkhd8hPZcW4IzMu52ok0zsmQcVZh8sVniBEHIePCfLQ== dependencies: "@snyk/graphlib" "2.1.9-patch.3" "@yarnpkg/lockfile" "^1.1.0" - "event-loop-spinner" "^2.0.0" - "got" "11.4.0" - "lodash.clonedeep" "^4.5.0" - "lodash.flatmap" "^4.5.0" - "lodash.isempty" "^4.4.0" - "lodash.set" "^4.3.2" - "lodash.topairs" "^4.3.0" - "p-map" "2.1.0" - "snyk-config" "^4.0.0-rc.2" - "tslib" "^1.9.3" - "uuid" "^8.3.0" - "yaml" "^1.9.2" + event-loop-spinner "^2.0.0" + got "11.4.0" + lodash.clonedeep "^4.5.0" + lodash.flatmap "^4.5.0" + lodash.isempty "^4.4.0" + lodash.set "^4.3.2" + lodash.topairs "^4.3.0" + p-map "2.1.0" + snyk-config "^4.0.0-rc.2" + tslib "^1.9.3" + uuid "^8.3.0" + yaml "^1.9.2" -"snyk-nuget-plugin@1.21.0": - "integrity" "sha512-c/JYF3sZzMN/lYz171zrEkVcPqDVcUTVgKIKHiL8nhhuFKxZQ1gzqOgk+lnfN31TLoTNQsZ3DhW/WY+4zEALvw==" - "resolved" "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.21.0.tgz" - "version" "1.21.0" +snyk-nuget-plugin@1.21.0: + version "1.21.0" + resolved "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.21.0.tgz" + integrity sha512-c/JYF3sZzMN/lYz171zrEkVcPqDVcUTVgKIKHiL8nhhuFKxZQ1gzqOgk+lnfN31TLoTNQsZ3DhW/WY+4zEALvw== dependencies: - "debug" "^4.1.1" - "dotnet-deps-parser" "5.0.0" - "jszip" "3.4.0" - "snyk-paket-parser" "1.6.0" - "tslib" "^1.11.2" - "xml2js" "^0.4.17" + debug "^4.1.1" + dotnet-deps-parser "5.0.0" + jszip "3.4.0" + snyk-paket-parser "1.6.0" + tslib "^1.11.2" + xml2js "^0.4.17" -"snyk-paket-parser@1.6.0": - "integrity" "sha512-6htFynjBe/nakclEHUZ1A3j5Eu32/0pNve5Qm4MFn3YQmJgj7UcAO8hdyK3QfzEY29/kAv/rkJQg+SKshn+N9Q==" - "resolved" "https://registry.npmjs.org/snyk-paket-parser/-/snyk-paket-parser-1.6.0.tgz" - "version" "1.6.0" +snyk-paket-parser@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/snyk-paket-parser/-/snyk-paket-parser-1.6.0.tgz" + integrity sha512-6htFynjBe/nakclEHUZ1A3j5Eu32/0pNve5Qm4MFn3YQmJgj7UcAO8hdyK3QfzEY29/kAv/rkJQg+SKshn+N9Q== dependencies: - "tslib" "^1.9.3" + tslib "^1.9.3" -"snyk-php-plugin@1.9.2": - "integrity" "sha512-IQcdsQBqqXVRY5DatlI7ASy4flbhtU2V7cr4P2rK9rkFnVHO6LHcitwKXVZa9ocdOmpZDzk7U6iwHJkVFcR6OA==" - "resolved" "https://registry.npmjs.org/snyk-php-plugin/-/snyk-php-plugin-1.9.2.tgz" - "version" "1.9.2" +snyk-php-plugin@1.9.2: + version "1.9.2" + resolved "https://registry.npmjs.org/snyk-php-plugin/-/snyk-php-plugin-1.9.2.tgz" + integrity sha512-IQcdsQBqqXVRY5DatlI7ASy4flbhtU2V7cr4P2rK9rkFnVHO6LHcitwKXVZa9ocdOmpZDzk7U6iwHJkVFcR6OA== dependencies: "@snyk/cli-interface" "^2.9.1" "@snyk/composer-lockfile-parser" "^1.4.1" - "tslib" "1.11.1" + tslib "1.11.1" -"snyk-poetry-lockfile-parser@^1.1.6": - "integrity" "sha512-MoekbWOZPj9umfukjk2bd2o3eRj0OyO+58sxq9crMtHmTlze4h0/Uj4+fb0JFPBOtBO3c2zwbA+dvFQmpKoOTA==" - "resolved" "https://registry.npmjs.org/snyk-poetry-lockfile-parser/-/snyk-poetry-lockfile-parser-1.1.6.tgz" - "version" "1.1.6" +snyk-poetry-lockfile-parser@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/snyk-poetry-lockfile-parser/-/snyk-poetry-lockfile-parser-1.1.6.tgz" + integrity sha512-MoekbWOZPj9umfukjk2bd2o3eRj0OyO+58sxq9crMtHmTlze4h0/Uj4+fb0JFPBOtBO3c2zwbA+dvFQmpKoOTA== dependencies: "@snyk/cli-interface" "^2.9.2" "@snyk/dep-graph" "^1.23.0" - "debug" "^4.2.0" - "toml" "^3.0.0" - "tslib" "^2.0.0" + debug "^4.2.0" + toml "^3.0.0" + tslib "^2.0.0" -"snyk-policy@1.19.0": - "integrity" "sha512-XYjhOTRPFA7NfDUsH6uH1fbML2OgSFsqdUPbud7x01urNP9CHXgUgAD4NhKMi3dVQK+7IdYadWt0wrFWw4y+qg==" - "resolved" "https://registry.npmjs.org/snyk-policy/-/snyk-policy-1.19.0.tgz" - "version" "1.19.0" +snyk-policy@1.19.0: + version "1.19.0" + resolved "https://registry.npmjs.org/snyk-policy/-/snyk-policy-1.19.0.tgz" + integrity sha512-XYjhOTRPFA7NfDUsH6uH1fbML2OgSFsqdUPbud7x01urNP9CHXgUgAD4NhKMi3dVQK+7IdYadWt0wrFWw4y+qg== dependencies: - "debug" "^4.1.1" - "email-validator" "^2.0.4" - "js-yaml" "^3.13.1" - "lodash.clonedeep" "^4.5.0" - "promise-fs" "^2.1.1" - "semver" "^6.0.0" - "snyk-module" "^3.0.0" - "snyk-resolve" "^1.1.0" - "snyk-try-require" "^2.0.0" + debug "^4.1.1" + email-validator "^2.0.4" + js-yaml "^3.13.1" + lodash.clonedeep "^4.5.0" + promise-fs "^2.1.1" + semver "^6.0.0" + snyk-module "^3.0.0" + snyk-resolve "^1.1.0" + snyk-try-require "^2.0.0" -"snyk-python-plugin@1.19.7": - "integrity" "sha512-twAGoIgJVSLVzMkuT/n5l9ZDvhMbWH7De6flWiHQB/grthfl3vJDzLCxiTa+6H/IEEYNSv6F/nSrfNh9UbW5/A==" - "resolved" "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.19.7.tgz" - "version" "1.19.7" +snyk-python-plugin@1.19.7: + version "1.19.7" + resolved "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.19.7.tgz" + integrity sha512-twAGoIgJVSLVzMkuT/n5l9ZDvhMbWH7De6flWiHQB/grthfl3vJDzLCxiTa+6H/IEEYNSv6F/nSrfNh9UbW5/A== dependencies: "@snyk/cli-interface" "^2.0.3" - "snyk-poetry-lockfile-parser" "^1.1.6" - "tmp" "0.0.33" + snyk-poetry-lockfile-parser "^1.1.6" + tmp "0.0.33" -"snyk-resolve-deps@4.7.2": - "integrity" "sha512-Bmtr7QdRL2b3Js+mPDmvXbkprOpzO8aUFXqR0nJKAOlUVQqZ84yiuT0n/mssEiJJ0vP+k0kZvTeiTwgio4KZRg==" - "resolved" "https://registry.npmjs.org/snyk-resolve-deps/-/snyk-resolve-deps-4.7.2.tgz" - "version" "4.7.2" +snyk-resolve-deps@4.7.2: + version "4.7.2" + resolved "https://registry.npmjs.org/snyk-resolve-deps/-/snyk-resolve-deps-4.7.2.tgz" + integrity sha512-Bmtr7QdRL2b3Js+mPDmvXbkprOpzO8aUFXqR0nJKAOlUVQqZ84yiuT0n/mssEiJJ0vP+k0kZvTeiTwgio4KZRg== dependencies: - "ansicolors" "^0.3.2" - "debug" "^4.1.1" - "lodash.assign" "^4.2.0" - "lodash.assignin" "^4.2.0" - "lodash.clone" "^4.5.0" - "lodash.flatten" "^4.4.0" - "lodash.get" "^4.4.2" - "lodash.set" "^4.3.2" - "lru-cache" "^4.0.0" - "semver" "^5.5.1" - "snyk-module" "^3.1.0" - "snyk-resolve" "^1.0.0" - "snyk-tree" "^1.0.0" - "snyk-try-require" "^1.1.1" - "then-fs" "^2.0.0" + ansicolors "^0.3.2" + debug "^4.1.1" + lodash.assign "^4.2.0" + lodash.assignin "^4.2.0" + lodash.clone "^4.5.0" + lodash.flatten "^4.4.0" + lodash.get "^4.4.2" + lodash.set "^4.3.2" + lru-cache "^4.0.0" + semver "^5.5.1" + snyk-module "^3.1.0" + snyk-resolve "^1.0.0" + snyk-tree "^1.0.0" + snyk-try-require "^1.1.1" + then-fs "^2.0.0" -"snyk-resolve@^1.0.0": - "integrity" "sha512-7+i+LLhtBo1Pkth01xv+RYJU8a67zmJ8WFFPvSxyCjdlKIcsps4hPQFebhz+0gC5rMemlaeIV6cqwqUf9PEDpw==" - "resolved" "https://registry.npmjs.org/snyk-resolve/-/snyk-resolve-1.0.1.tgz" - "version" "1.0.1" +snyk-resolve@1.1.0, snyk-resolve@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/snyk-resolve/-/snyk-resolve-1.1.0.tgz" + integrity sha512-OZMF8I8TOu0S58Z/OS9mr8jkEzGAPByCsAkrWlcmZgPaE0RsxVKVIFPhbMNy/JlYswgGDYYIEsNw+e0j1FnTrw== dependencies: - "debug" "^3.1.0" - "then-fs" "^2.0.0" + debug "^4.1.1" + promise-fs "^2.1.1" -"snyk-resolve@^1.1.0", "snyk-resolve@1.1.0": - "integrity" "sha512-OZMF8I8TOu0S58Z/OS9mr8jkEzGAPByCsAkrWlcmZgPaE0RsxVKVIFPhbMNy/JlYswgGDYYIEsNw+e0j1FnTrw==" - "resolved" "https://registry.npmjs.org/snyk-resolve/-/snyk-resolve-1.1.0.tgz" - "version" "1.1.0" +snyk-resolve@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/snyk-resolve/-/snyk-resolve-1.0.1.tgz" + integrity sha512-7+i+LLhtBo1Pkth01xv+RYJU8a67zmJ8WFFPvSxyCjdlKIcsps4hPQFebhz+0gC5rMemlaeIV6cqwqUf9PEDpw== dependencies: - "debug" "^4.1.1" - "promise-fs" "^2.1.1" + debug "^3.1.0" + then-fs "^2.0.0" -"snyk-sbt-plugin@2.11.0": - "integrity" "sha512-wUqHLAa3MzV6sVO+05MnV+lwc+T6o87FZZaY+43tQPytBI2Wq23O3j4POREM4fa2iFfiQJoEYD6c7xmhiEUsSA==" - "resolved" "https://registry.npmjs.org/snyk-sbt-plugin/-/snyk-sbt-plugin-2.11.0.tgz" - "version" "2.11.0" +snyk-sbt-plugin@2.11.0: + version "2.11.0" + resolved "https://registry.npmjs.org/snyk-sbt-plugin/-/snyk-sbt-plugin-2.11.0.tgz" + integrity sha512-wUqHLAa3MzV6sVO+05MnV+lwc+T6o87FZZaY+43tQPytBI2Wq23O3j4POREM4fa2iFfiQJoEYD6c7xmhiEUsSA== dependencies: - "debug" "^4.1.1" - "semver" "^6.1.2" - "tmp" "^0.1.0" - "tree-kill" "^1.2.2" - "tslib" "^1.10.0" + debug "^4.1.1" + semver "^6.1.2" + tmp "^0.1.0" + tree-kill "^1.2.2" + tslib "^1.10.0" -"snyk-tree@^1.0.0": - "integrity" "sha1-D7cxdtvzLngvGRAClBYESPkRHMg=" - "resolved" "https://registry.npmjs.org/snyk-tree/-/snyk-tree-1.0.0.tgz" - "version" "1.0.0" +snyk-tree@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/snyk-tree/-/snyk-tree-1.0.0.tgz" + integrity sha1-D7cxdtvzLngvGRAClBYESPkRHMg= dependencies: - "archy" "^1.0.0" + archy "^1.0.0" -"snyk-try-require@^1.1.1", "snyk-try-require@1.3.1": - "integrity" "sha1-bgJvkuZK9/zM6h7lPVJIQeQYohI=" - "resolved" "https://registry.npmjs.org/snyk-try-require/-/snyk-try-require-1.3.1.tgz" - "version" "1.3.1" +snyk-try-require@1.3.1, snyk-try-require@^1.1.1: + version "1.3.1" + resolved "https://registry.npmjs.org/snyk-try-require/-/snyk-try-require-1.3.1.tgz" + integrity sha1-bgJvkuZK9/zM6h7lPVJIQeQYohI= dependencies: - "debug" "^3.1.0" - "lodash.clonedeep" "^4.3.0" - "lru-cache" "^4.0.0" - "then-fs" "^2.0.0" + debug "^3.1.0" + lodash.clonedeep "^4.3.0" + lru-cache "^4.0.0" + then-fs "^2.0.0" -"snyk-try-require@^2.0.0": - "integrity" "sha512-VCOfFIvqLMXgCXEdooQgu3A40XYIFBnj0X8Y01RJ5iAbu08b4WKGN/uAKaRVF30dABS4EcjsalmCO+YlKUPEIA==" - "resolved" "https://registry.npmjs.org/snyk-try-require/-/snyk-try-require-2.0.1.tgz" - "version" "2.0.1" +snyk-try-require@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/snyk-try-require/-/snyk-try-require-2.0.1.tgz" + integrity sha512-VCOfFIvqLMXgCXEdooQgu3A40XYIFBnj0X8Y01RJ5iAbu08b4WKGN/uAKaRVF30dABS4EcjsalmCO+YlKUPEIA== dependencies: - "debug" "^4.1.1" - "lodash.clonedeep" "^4.3.0" - "lru-cache" "^5.1.1" + debug "^4.1.1" + lodash.clonedeep "^4.3.0" + lru-cache "^5.1.1" -"snyk@^1.518.0": - "integrity" "sha512-+NSZDb1sbG+AxzK//GLAKHF0oyPyDlUzQgwy8tyet4tiUsnDKKEruCsX4R9c0outy5qfAExKG77aZego3N9p/Q==" - "resolved" "https://registry.npmjs.org/snyk/-/snyk-1.520.0.tgz" - "version" "1.520.0" +snyk@^1.518.0: + version "1.520.0" + resolved "https://registry.npmjs.org/snyk/-/snyk-1.520.0.tgz" + integrity sha512-+NSZDb1sbG+AxzK//GLAKHF0oyPyDlUzQgwy8tyet4tiUsnDKKEruCsX4R9c0outy5qfAExKG77aZego3N9p/Q== dependencies: "@open-policy-agent/opa-wasm" "^1.2.0" "@snyk/cli-interface" "2.11.0" @@ -6920,7 +6875,7 @@ string-width@^4.2.0: string.prototype.trimend@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz" integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== dependencies: define-properties "^1.1.3" @@ -6928,7 +6883,7 @@ string.prototype.trimend@^1.0.0: string.prototype.trimleft@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" + resolved "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz" integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== dependencies: define-properties "^1.1.3" @@ -6937,7 +6892,7 @@ string.prototype.trimleft@^2.1.1: string.prototype.trimright@^2.1.1: version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" + resolved "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz" integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== dependencies: define-properties "^1.1.3" @@ -6946,7 +6901,7 @@ string.prototype.trimright@^2.1.1: string.prototype.trimstart@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz" integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== dependencies: define-properties "^1.1.3" @@ -6968,59 +6923,59 @@ string_decoder@~1.1.1: strip-ansi@6.0.0, strip-ansi@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== dependencies: ansi-regex "^5.0.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" strip-bom@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= dependencies: is-utf8 "^0.2.0" strip-eof@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-indent@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= dependencies: get-stdin "^4.0.1" strip-json-comments@~2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= stylehacks@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + resolved "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz" integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== dependencies: browserslist "^4.0.0" @@ -7043,7 +6998,7 @@ stylus@^0.54.5, stylus@^0.x: superagent@^3.8.2: version "3.8.3" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" + resolved "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz" integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== dependencies: component-emitter "^1.2.0" @@ -7059,40 +7014,40 @@ superagent@^3.8.2: supports-color@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= supports-color@^3.2.3: version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz" integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== dependencies: has-flag "^4.0.0" svgo@^1.0.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.0.tgz#305a8fc0f4f9710828c65039bb93d5793225ffc3" + resolved "https://registry.npmjs.org/svgo/-/svgo-1.2.0.tgz" integrity sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw== dependencies: chalk "^2.4.1" @@ -7112,7 +7067,7 @@ svgo@^1.0.0: tar-stream@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz" integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw== dependencies: bl "^3.0.0" @@ -7123,7 +7078,7 @@ tar-stream@^2.1.0: tar-stream@^2.1.2: version "2.1.3" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.3.tgz" integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA== dependencies: bl "^4.0.1" @@ -7134,7 +7089,7 @@ tar-stream@^2.1.2: tar@^2.0.0: version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + resolved "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz" integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== dependencies: block-stream "*" @@ -7143,7 +7098,7 @@ tar@^2.0.0: tar@^6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" + resolved "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz" integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== dependencies: chownr "^2.0.0" @@ -7155,17 +7110,17 @@ tar@^6.1.0: temp-dir@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" + resolved "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz" integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= temp-dir@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + resolved "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz" integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== tempfile@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" + resolved "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz" integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= dependencies: temp-dir "^1.0.0" @@ -7173,19 +7128,19 @@ tempfile@^2.0.0: term-size@^2.1.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" + resolved "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz" integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== then-fs@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/then-fs/-/then-fs-2.0.0.tgz#72f792dd9d31705a91ae19ebfcf8b3f968c81da2" + resolved "https://registry.npmjs.org/then-fs/-/then-fs-2.0.0.tgz" integrity sha1-cveS3Z0xcFqRrhnr/Piz+WjIHaI= dependencies: promise ">=3.2 <8" through2@^2.0.3: version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: readable-stream "~2.3.6" @@ -7193,38 +7148,38 @@ through2@^2.0.3: through@^2.3.4, through@^2.3.6: version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= timsort@^0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= tmp@0.0.33, tmp@^0.0.33: version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" tmp@0.2.1, tmp@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== dependencies: rimraf "^3.0.0" tmp@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz" integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== dependencies: rimraf "^2.6.3" to-array@0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + resolved "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= to-fast-properties@^1.0.3: @@ -7234,26 +7189,26 @@ to-fast-properties@^1.0.3: to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-readable-stream@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" toidentifier@1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== token-stream@0.0.1: @@ -7263,481 +7218,41 @@ token-stream@0.0.1: toml@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + resolved "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz" integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== -"string.prototype.trimend@^1.0.0": - "integrity" "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==" - "resolved" "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz" - "version" "1.0.1" +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== dependencies: - "define-properties" "^1.1.3" - "es-abstract" "^1.17.5" + nopt "~1.0.10" -"string.prototype.trimleft@^2.1.1": - "integrity" "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==" - "resolved" "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz" - "version" "2.1.2" +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== dependencies: - "define-properties" "^1.1.3" - "es-abstract" "^1.17.5" - "string.prototype.trimstart" "^1.0.0" + psl "^1.1.24" + punycode "^1.4.1" -"string.prototype.trimright@^2.1.1": - "integrity" "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==" - "resolved" "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz" - "version" "2.1.2" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: - "define-properties" "^1.1.3" - "es-abstract" "^1.17.5" - "string.prototype.trimend" "^1.0.0" + psl "^1.1.28" + punycode "^2.1.1" -"string.prototype.trimstart@^1.0.0": - "integrity" "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==" - "resolved" "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz" - "version" "1.0.1" - dependencies: - "define-properties" "^1.1.3" - "es-abstract" "^1.17.5" +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -"strip-ansi@^3.0.0", "strip-ansi@^3.0.1": - "integrity" "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - "version" "3.0.1" - dependencies: - "ansi-regex" "^2.0.0" - -"strip-ansi@^4.0.0": - "integrity" "sha1-qEeQIusaw2iocTibY1JixQXuNo8=" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "ansi-regex" "^3.0.0" - -"strip-ansi@^5.0.0": - "integrity" "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" - "version" "5.2.0" - dependencies: - "ansi-regex" "^4.1.0" - -"strip-ansi@^5.1.0": - "integrity" "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" - "version" "5.2.0" - dependencies: - "ansi-regex" "^4.1.0" - -"strip-ansi@^5.2.0": - "integrity" "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" - "version" "5.2.0" - dependencies: - "ansi-regex" "^4.1.0" - -"strip-ansi@^6.0.0": - "integrity" "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "ansi-regex" "^5.0.0" - -"strip-ansi@6.0.0": - "integrity" "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "ansi-regex" "^5.0.0" - -"strip-bom@^2.0.0": - "integrity" "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" - "resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "is-utf8" "^0.2.0" - -"strip-eof@^1.0.0": - "integrity" "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" - "resolved" "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" - "version" "1.0.0" - -"strip-indent@^1.0.1": - "integrity" "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=" - "resolved" "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" - "version" "1.0.1" - dependencies: - "get-stdin" "^4.0.1" - -"strip-json-comments@~2.0.1": - "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" - "version" "2.0.1" - -"style-inject@^0.3.0": - "integrity" "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==" - "resolved" "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz" - "version" "0.3.0" - -"stylehacks@^4.0.0": - "integrity" "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==" - "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz" - "version" "4.0.3" - dependencies: - "browserslist" "^4.0.0" - "postcss" "^7.0.0" - "postcss-selector-parser" "^3.0.0" - -"superagent@^3.8.2": - "integrity" "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==" - "resolved" "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz" - "version" "3.8.3" - dependencies: - "component-emitter" "^1.2.0" - "cookiejar" "^2.1.0" - "debug" "^3.1.0" - "extend" "^3.0.0" - "form-data" "^2.3.1" - "formidable" "^1.2.0" - "methods" "^1.1.1" - "mime" "^1.4.1" - "qs" "^6.5.1" - "readable-stream" "^2.3.5" - -"supports-color@^2.0.0": - "integrity" "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - "version" "2.0.0" - -"supports-color@^3.2.3": - "integrity" "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" - "version" "3.2.3" - dependencies: - "has-flag" "^1.0.0" - -"supports-color@^5.3.0": - "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - "version" "5.5.0" - dependencies: - "has-flag" "^3.0.0" - -"supports-color@^5.4.0": - "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - "version" "5.5.0" - dependencies: - "has-flag" "^3.0.0" - -"supports-color@^6.1.0": - "integrity" "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "has-flag" "^3.0.0" - -"supports-color@^7.1.0": - "integrity" "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz" - "version" "7.1.0" - dependencies: - "has-flag" "^4.0.0" - -"supports-color@5.4.0": - "integrity" "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz" - "version" "5.4.0" - dependencies: - "has-flag" "^3.0.0" - -"svg-sprite@^1.5.0": - "integrity" "sha512-0mE5BLY3K8wg3+HrYfzpiKbIM44IGcg8uINED8ri22EdQbLvGecOHjRtkrNAlphbiU5kyGyqoBlIaukL45fs2Q==" - "resolved" "https://registry.npmjs.org/svg-sprite/-/svg-sprite-1.5.0.tgz" - "version" "1.5.0" - dependencies: - "async" "^2.6.1" - "css-selector-parser" "^1.3.0" - "cssmin" "^0.4.3" - "cssom" "^0.3.4" - "dateformat" "^3.0.3" - "glob" "^7.1.3" - "js-yaml" "^3.12.0" - "lodash" "^4.17.11" - "lodash.pluck" "^3.1.2" - "mkdirp" "^0.5.1" - "mocha" "^5.2.0" - "mustache" "^3.0.0" - "phantomjs-prebuilt" "^2.1.16" - "prettysize" "^1.1.0" - "should" "^13.2.3" - "svgo" "^1.1.1" - "vinyl" "^2.2.0" - "winston" "^3.1.0" - "xmldom" "0.1.27" - "xpath" "^0.0.27" - "yargs" "^12.0.2" - -"svgo@^1.0.0": - "integrity" "sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw==" - "resolved" "https://registry.npmjs.org/svgo/-/svgo-1.2.0.tgz" - "version" "1.2.0" - dependencies: - "chalk" "^2.4.1" - "coa" "^2.0.2" - "css-select" "^2.0.0" - "css-select-base-adapter" "^0.1.1" - "css-tree" "1.0.0-alpha.28" - "css-url-regex" "^1.1.0" - "csso" "^3.5.1" - "js-yaml" "^3.12.0" - "mkdirp" "~0.5.1" - "object.values" "^1.1.0" - "sax" "~1.2.4" - "stable" "^0.1.8" - "unquote" "~1.1.1" - "util.promisify" "~1.0.0" - -"svgo@^1.1.1": - "integrity" "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==" - "resolved" "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz" - "version" "1.3.2" - dependencies: - "chalk" "^2.4.1" - "coa" "^2.0.2" - "css-select" "^2.0.0" - "css-select-base-adapter" "^0.1.1" - "css-tree" "1.0.0-alpha.37" - "csso" "^4.0.2" - "js-yaml" "^3.13.1" - "mkdirp" "~0.5.1" - "object.values" "^1.1.0" - "sax" "~1.2.4" - "stable" "^0.1.8" - "unquote" "~1.1.1" - "util.promisify" "~1.0.0" - -"tar-stream@^2.1.0": - "integrity" "sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==" - "resolved" "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "bl" "^3.0.0" - "end-of-stream" "^1.4.1" - "fs-constants" "^1.0.0" - "inherits" "^2.0.3" - "readable-stream" "^3.1.1" - -"tar-stream@^2.1.2": - "integrity" "sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA==" - "resolved" "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.3.tgz" - "version" "2.1.3" - dependencies: - "bl" "^4.0.1" - "end-of-stream" "^1.4.1" - "fs-constants" "^1.0.0" - "inherits" "^2.0.3" - "readable-stream" "^3.1.1" - -"tar@^2.0.0": - "integrity" "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==" - "resolved" "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz" - "version" "2.2.2" - dependencies: - "block-stream" "*" - "fstream" "^1.0.12" - "inherits" "2" - -"tar@^6.1.0": - "integrity" "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==" - "resolved" "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz" - "version" "6.1.0" - dependencies: - "chownr" "^2.0.0" - "fs-minipass" "^2.0.0" - "minipass" "^3.0.0" - "minizlib" "^2.1.1" - "mkdirp" "^1.0.3" - "yallist" "^4.0.0" - -"temp-dir@^1.0.0": - "integrity" "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=" - "resolved" "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz" - "version" "1.0.0" - -"temp-dir@^2.0.0": - "integrity" "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" - "resolved" "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz" - "version" "2.0.0" - -"tempfile@^2.0.0": - "integrity" "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=" - "resolved" "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "temp-dir" "^1.0.0" - "uuid" "^3.0.1" - -"term-size@^2.1.0": - "integrity" "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" - "resolved" "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz" - "version" "2.2.0" - -"terser@^3.14.1": - "integrity" "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==" - "resolved" "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz" - "version" "3.17.0" - dependencies: - "commander" "^2.19.0" - "source-map" "~0.6.1" - "source-map-support" "~0.5.10" - -"text-hex@1.0.x": - "integrity" "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - "resolved" "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz" - "version" "1.0.0" - -"then-fs@^2.0.0": - "integrity" "sha1-cveS3Z0xcFqRrhnr/Piz+WjIHaI=" - "resolved" "https://registry.npmjs.org/then-fs/-/then-fs-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "promise" ">=3.2 <8" - -"throttleit@^1.0.0": - "integrity" "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=" - "resolved" "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz" - "version" "1.0.0" - -"through@^2.3.4", "through@^2.3.6": - "integrity" "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - "version" "2.3.8" - -"through2@^2.0.3": - "integrity" "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==" - "resolved" "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" - "version" "2.0.5" - dependencies: - "readable-stream" "~2.3.6" - "xtend" "~4.0.1" - -"timsort@^0.3.0": - "integrity" "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" - "resolved" "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" - "version" "0.3.0" - -"tmp@^0.0.33": - "integrity" "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==" - "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" - "version" "0.0.33" - dependencies: - "os-tmpdir" "~1.0.2" - -"tmp@^0.1.0": - "integrity" "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==" - "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz" - "version" "0.1.0" - dependencies: - "rimraf" "^2.6.3" - -"tmp@^0.2.1", "tmp@0.2.1": - "integrity" "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==" - "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" - "version" "0.2.1" - dependencies: - "rimraf" "^3.0.0" - -"tmp@0.0.33": - "integrity" "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==" - "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" - "version" "0.0.33" - dependencies: - "os-tmpdir" "~1.0.2" - -"to-array@0.1.4": - "integrity" "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - "resolved" "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" - "version" "0.1.4" - -"to-object-path@^0.3.0": - "integrity" "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=" - "resolved" "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" - "version" "0.3.0" - dependencies: - "kind-of" "^3.0.2" - -"to-readable-stream@^1.0.0": - "integrity" "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - "resolved" "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" - "version" "1.0.0" - -"to-regex-range@^2.1.0": - "integrity" "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=" - "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" - "version" "2.1.1" - dependencies: - "is-number" "^3.0.0" - "repeat-string" "^1.6.1" - -"to-regex-range@^5.0.1": - "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" - "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "is-number" "^7.0.0" - -"to-regex@^3.0.1", "to-regex@^3.0.2": - "integrity" "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==" - "resolved" "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" - "version" "3.0.2" - dependencies: - "define-property" "^2.0.2" - "extend-shallow" "^3.0.2" - "regex-not" "^1.0.2" - "safe-regex" "^1.1.0" - -"toidentifier@1.0.0": - "integrity" "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz" - "version" "1.0.0" - -"toml@^3.0.0": - "integrity" "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" - "resolved" "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz" - "version" "3.0.0" - -"touch@^3.1.0": - "integrity" "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==" - "resolved" "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "nopt" "~1.0.10" - -"tough-cookie@~2.4.3": - "integrity" "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==" - "resolved" "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz" - "version" "2.4.3" - dependencies: - "psl" "^1.1.24" - "punycode" "^1.4.1" - -"tough-cookie@~2.5.0": - "integrity" "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==" - "resolved" "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" - "version" "2.5.0" - dependencies: - "psl" "^1.1.28" - "punycode" "^2.1.1" - -"tree-kill@^1.2.2": - "integrity" "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" - "resolved" "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" - "version" "1.2.2" - -"trim-newlines@^1.0.0": - "integrity" "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - "resolved" "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" - "version" "1.0.0" +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" + integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= "true-case-path@^1.0.2": version "1.0.3" From 793b5638d3c4baa34673017ff757e2c9cea85031 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 12:48:01 +0530 Subject: [PATCH 197/868] style: Fix E201, E202, E401, E701 reported by sider: https://sider.review/gh/repos/1864194/pulls/13344?statuses#issues --- frappe/desk/form/linked_with.py | 5 ++++- frappe/desk/form/meta.py | 15 ++++++++------- frappe/permissions.py | 10 ++++------ frappe/tests/test_pdf.py | 8 +++++--- frappe/translate.py | 17 ++++++++++++----- frappe/utils/redis_wrapper.py | 7 ++++++- 6 files changed, 39 insertions(+), 23 deletions(-) diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py index 12880604a2..ae48b7fc6b 100644 --- a/frappe/desk/form/linked_with.py +++ b/frappe/desk/form/linked_with.py @@ -2,6 +2,7 @@ # MIT License. See license.txt import json from collections import defaultdict + import frappe import frappe.desk.form.load import frappe.desk.form.meta @@ -9,6 +10,7 @@ from frappe import _ from frappe.model.meta import is_single from frappe.modules import load_doctype_module + @frappe.whitelist() def get_submitted_linked_docs(doctype, name, docs=None, visited=None): """ @@ -200,7 +202,8 @@ def get_linked_docs(doctype, name, linkinfo=None, for_doctype=None): else: link_fieldnames = link.get("fieldname") if link_fieldnames: - if isinstance(link_fieldnames, str): link_fieldnames = [link_fieldnames] + if isinstance(link_fieldnames, str): + link_fieldnames = [link_fieldnames] or_filters = [[dt, fieldname, '=', name] for fieldname in link_fieldnames] # dynamic link if link.get("doctype_fieldname"): diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index 947a9e5d4b..cf3606e785 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -1,14 +1,15 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt +import io +import os -# metadata -import frappe, os, io -from frappe.model.meta import Meta -from frappe.modules import scrub, get_module_path, load_doctype_module -from frappe.utils import get_html_format -from frappe.translate import make_dict_from_messages, extract_messages_from_code -from frappe.model.utils import render_include +import frappe from frappe.build import scrub_html_template +from frappe.model.meta import Meta +from frappe.model.utils import render_include +from frappe.modules import get_module_path, load_doctype_module, scrub +from frappe.translate import extract_messages_from_code, make_dict_from_messages +from frappe.utils import get_html_format def get_meta(doctype, cached=True): diff --git a/frappe/permissions.py b/frappe/permissions.py index e139b04a4e..c25a7c3947 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -1,17 +1,15 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -import frappe, copy +import copy + +import frappe +import frappe.share from frappe import _, msgprint from frappe.utils import cint -import frappe.share rights = ("select", "read", "write", "create", "delete", "submit", "cancel", "amend", "print", "email", "report", "import", "export", "set_user_permissions", "share") -# TODO: - -# optimize: meta.get_link_map (check if the doctype link exists for the given permission type) - def check_admin_or_system_manager(user=None): if not user: user = frappe.session.user diff --git a/frappe/tests/test_pdf.py b/frappe/tests/test_pdf.py index b67aee7a68..9e22b9ddbf 100644 --- a/frappe/tests/test_pdf.py +++ b/frappe/tests/test_pdf.py @@ -1,12 +1,14 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt +import io import unittest -import frappe.utils.pdf as pdfgen -import frappe, io from PyPDF2 import PdfFileReader -#class TestPdfBorders(unittest.TestCase): +import frappe +import frappe.utils.pdf as pdfgen + + class TestPdf(unittest.TestCase): @property def html(self): diff --git a/frappe/translate.py b/frappe/translate.py index b7b780e594..a407ad9579 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -7,12 +7,19 @@ Translation tools for frappe """ -import frappe, os, re, io, json -from frappe.model.utils import render_include, InvalidIncludePath -from frappe.utils import strip, strip_html_tags, is_html -import itertools, operator +import io +import itertools +import json +import operator +import os +import re from csv import reader +import frappe +from frappe.model.utils import InvalidIncludePath, render_include +from frappe.utils import is_html, strip, strip_html_tags + + def guess_language(lang_list=None): """Set `frappe.local.lang` from HTTP headers at beginning of request""" user_preferred_language = frappe.request.cookies.get('preferred_language') @@ -606,7 +613,7 @@ def read_csv_file(path): with io.open(path, mode='r', encoding='utf-8', newline='') as msgfile: data = reader(msgfile) - newdata = [[ val for val in row ] for row in data] + newdata = [[val for val in row] for row in data] return newdata diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index 41aa4e7ad1..8a7ff8334b 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -1,6 +1,11 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -import redis, frappe, re, pickle +import pickle +import re + +import redis + +import frappe from frappe.utils import cstr From d13eac6f50ad727c1e77a66b828c7f60f5b4bbcc Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 27 May 2021 12:56:38 +0530 Subject: [PATCH 198/868] fix: Breadcrumbs for a page --- .../website/page_renderers/template_page.py | 25 +++++++++++++------ frappe/website/page_renderers/web_page.py | 9 ++++--- frappe/website/router.py | 2 +- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index 2b326d7383..8f613ae9bd 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -3,6 +3,7 @@ import os import click import frappe +from frappe.website.router import get_page_info from frappe.website.page_renderers.base_template_page import BaseTemplatePage from frappe.website.router import get_base_template from frappe.website.utils import (extract_comment_tag, extract_title, get_next_link, @@ -37,11 +38,11 @@ class TemplatePage(BaseTemplatePage): for dirname in folders: search_path = os.path.join(app_path, dirname, self.path) - for p in self.get_index_path_options(search_path): - file_path = frappe.as_unicode(p) - if os.path.exists(file_path) and not os.path.isdir(file_path): + for file_path in self.get_index_path_options(search_path): + if os.path.isfile(file_path): self.app = app self.app_path = app_path + self.file_dir = dirname self.basename = os.path.splitext(file_path)[0] self.template_path = os.path.relpath(file_path, self.app_path) self.basepath = os.path.dirname(file_path) @@ -52,8 +53,9 @@ class TemplatePage(BaseTemplatePage): def can_render(self): return hasattr(self, 'template_path') and bool(self.template_path) - def get_index_path_options(self, search_path): - return (f'{search_path}{d}' for d in ('', '.html', '.md', '/index.html', '/index.md')) + @staticmethod + def get_index_path_options(search_path): + return (frappe.as_unicode(f'{search_path}{d}') for d in ('.html', '.md', '/index.html', '/index.md')) def render(self): return build_response(self.path, self.get_html(), self.http_status_code, self.headers) @@ -85,9 +87,18 @@ class TemplatePage(BaseTemplatePage): self.context.sidebar_items = get_sidebar_items(self.context.website_sidebar, self.basepath) if self.context.add_breadcrumbs and not self.context.parents: - # TODO: set correct title and route for breadcrumbs parent_path = os.path.dirname(self.path) - self.context.parents = [dict(route=parent_path, title=extract_title(source='', path=parent_path))] + if self.path.endswith('index'): + # in case of index page move one directory up for parent path + parent_path = os.path.dirname(parent_path) + + for parent_file_path in self.get_index_path_options(parent_path): + parent_file_path = os.path.join(self.app_path, self.file_dir, parent_file_path) + if os.path.isfile(parent_file_path): + parent_page_context = get_page_info(parent_file_path, self.app, self.file_dir) + if parent_page_context: + self.context.parents = [dict(route=os.path.dirname(self.path), title=parent_page_context.title)] + break def set_pymodule(self): ''' diff --git a/frappe/website/page_renderers/web_page.py b/frappe/website/page_renderers/web_page.py index 6e738e8df9..1814a9615a 100644 --- a/frappe/website/page_renderers/web_page.py +++ b/frappe/website/page_renderers/web_page.py @@ -7,10 +7,11 @@ class WebPage(object): if not path: path = frappe.local.request.path self.path = path.strip('/ ') - self.basepath = '' - self.basename = '' - self.name = '' - self.route = '' + self.basepath = None + self.basename = None + self.name = None + self.route = None + self.file_dir = None def can_render(self): pass diff --git a/frappe/website/router.py b/frappe/website/router.py index 23fd5cb21f..6d803886ef 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -107,7 +107,7 @@ def get_page_info(path, app, start, basepath=None, app_path=None, fname=None): if basepath is None: basepath = os.path.dirname(path) - page_name, extn = fname.rsplit(".", 1) + page_name, extn = os.path.splitext(fname) # add website route page_info = frappe._dict() From 9ec451b28e2e92589bb7d29a3aaf861776f75a98 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 27 May 2021 12:57:55 +0530 Subject: [PATCH 199/868] test: Add test case to check breadcrumbs --- frappe/templates/includes/full_index.html | 5 ----- frappe/templates/test/_test_base.html | 1 + frappe/website/doctype/web_page/test_web_page.py | 8 +++++++- frappe/www/_test/_test_folder/_test_page.py | 1 + frappe/www/_test/_test_folder/index.md | 6 ++++++ frappe/www/_test/index.html | 1 + 6 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 frappe/www/_test/index.html diff --git a/frappe/templates/includes/full_index.html b/frappe/templates/includes/full_index.html index a7443c482a..eb8fb322f6 100644 --- a/frappe/templates/includes/full_index.html +++ b/frappe/templates/includes/full_index.html @@ -3,11 +3,6 @@ {% for item in children_map[route] %}
  • {{ item.title }} - {# - {% if children_map[item.route] %} - {{ make_item_list(item.route, children_map) }} - {% endif %} - #}
  • {% endfor %} diff --git a/frappe/templates/test/_test_base.html b/frappe/templates/test/_test_base.html index 5a88584a5d..17caf8df1b 100644 --- a/frappe/templates/test/_test_base.html +++ b/frappe/templates/test/_test_base.html @@ -8,6 +8,7 @@ {%- endblock -%} + {% include "templates/includes/breadcrumbs.html" %}

    This is for testing

    {% block content %}{% endblock %} {%- block script %} diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index d213fd57a8..d097ceb083 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -113,7 +113,13 @@ class TestWebPage(unittest.TestCase): frappe.as_unicode(content)) def test_breadcrumbs(self): - pass + content = get_response_content('/_test/_test_folder/_test_page') + self.assertIn('Test TOC', content) + self.assertIn(' Test Page', content) + + content = get_response_content('/_test/_test_folder/index') + self.assertIn(' Test', content) + self.assertIn('Test TOC', content) def test_downloadable_file(self): pass diff --git a/frappe/www/_test/_test_folder/_test_page.py b/frappe/www/_test/_test_folder/_test_page.py index fa7b5f5727..1813a06bac 100644 --- a/frappe/www/_test/_test_folder/_test_page.py +++ b/frappe/www/_test/_test_folder/_test_page.py @@ -1,2 +1,3 @@ def get_context(context): context.base_template_path = 'frappe/templates/test/_test_base.html' + context.add_breadcrumbs = 1 diff --git a/frappe/www/_test/_test_folder/index.md b/frappe/www/_test/_test_folder/index.md index d0b531a642..1a5a9e7f81 100644 --- a/frappe/www/_test/_test_folder/index.md +++ b/frappe/www/_test/_test_folder/index.md @@ -1,3 +1,9 @@ +--- +title: Test TOC +add_breadcrumbs: 1 +show_sidebar: 1 +--- + # Index {index} \ No newline at end of file diff --git a/frappe/www/_test/index.html b/frappe/www/_test/index.html new file mode 100644 index 0000000000..0dff60b400 --- /dev/null +++ b/frappe/www/_test/index.html @@ -0,0 +1 @@ +{index} \ No newline at end of file From 6e9207cd626a373d7e6488c56ec4d027458ede9e Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 27 May 2021 12:58:48 +0530 Subject: [PATCH 200/868] test: Refactor webpage test to remove unnecessary operations --- .../website/doctype/web_page/test_web_page.py | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index d097ceb083..67b3cdbe89 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -2,16 +2,10 @@ from __future__ import unicode_literals import unittest import frappe from frappe.website.path_resolver import PathResolver -from frappe.website.serve import get_response, get_response_content -from frappe.utils import set_request +from frappe.website.serve import get_response_content test_records = frappe.get_test_records('Web Page') -def get_page_content(route): - set_request(method='GET', path = route) - response = get_response() - return frappe.as_unicode(response.data) - class TestWebPage(unittest.TestCase): def setUp(self): frappe.db.sql("delete from `tabWeb Page`") @@ -25,13 +19,13 @@ class TestWebPage(unittest.TestCase): self.assertFalse(PathResolver("test-web-page-1/test-web-page-Random").is_valid_path()) def test_base_template(self): - content = get_page_content('/_test/_test_custom_base.html') + content = get_response_content('/_test/_test_custom_base.html') # assert the text in base template is rendered - self.assertIn('

    This is for testing

    ', frappe.as_unicode(content)) + self.assertIn('

    This is for testing

    ', content) # assert template block rendered - self.assertIn('

    Test content

    ', frappe.as_unicode(content)) + self.assertIn('

    Test content

    ', content) def test_content_type(self): web_page = frappe.get_doc(dict( @@ -44,15 +38,15 @@ class TestWebPage(unittest.TestCase): main_section_html = '
    html content
    ' )).insert() - self.assertIn('rich text', get_page_content('/test-content-type')) + self.assertIn('rich text', get_response_content('/test-content-type')) web_page.content_type = 'Markdown' web_page.save() - self.assertIn('markdown content', get_page_content('/test-content-type')) + self.assertIn('markdown content', get_response_content('/test-content-type')) web_page.content_type = 'HTML' web_page.save() - self.assertIn('html content', get_page_content('/test-content-type')) + self.assertIn('html content', get_response_content('/test-content-type')) web_page.delete() @@ -67,9 +61,9 @@ class TestWebPage(unittest.TestCase): dynamic_template = 1, main_section_html = '
    {{ frappe.form_dict.doctype }}
    ' )).insert() - try: - content = get_page_content('/doctype-view/DocField') + from frappe.utils import get_html_for_route + content = get_html_for_route('/doctype-view/DocField') self.assertIn('
    DocField
    ', content) finally: web_page.delete() @@ -77,40 +71,35 @@ class TestWebPage(unittest.TestCase): def test_custom_base_template_path(self): content = get_response_content('/_test/_test_folder/_test_page') # assert the text in base template is rendered - self.assertIn('

    This is for testing

    ', frappe.as_unicode(content)) + self.assertIn('

    This is for testing

    ', content) # assert template block rendered - self.assertIn('

    Test content

    ', frappe.as_unicode(content)) + self.assertIn('

    Test content

    ', content) def test_json_sidebar_data(self): frappe.flags.look_for_sidebar = False content = get_response_content('/_test/_test_folder/_test_page') - self.assertNotIn('Test Sidebar', frappe.as_unicode(content)) + self.assertNotIn('Test Sidebar', content) frappe.flags.look_for_sidebar = True content = get_response_content('/_test/_test_folder/_test_page') - self.assertIn('Test Sidebar', frappe.as_unicode(content)) + self.assertIn('Test Sidebar', content) frappe.flags.look_for_sidebar = False def test_index_and_next_comment(self): content = get_response_content('/_test/_test_folder') # test if {index} was rendered - self.assertIn(' Test Page', - frappe.as_unicode(content)) + self.assertIn(' Test Page', content) - self.assertIn('Test TOC', - frappe.as_unicode(content)) + self.assertIn('Test TOC', content) content = get_response_content('/_test/_test_folder/_test_page') # test if {next} was rendered - self.assertIn('Next: Test TOC', - frappe.as_unicode(content)) + self.assertIn('Next: Test TOC', content) def test_colocated_assets(self): content = get_response_content('/_test/_test_folder/_test_page') - self.assertIn("", - frappe.as_unicode(content)) - self.assertIn("background-color: var(--bg-color);", - frappe.as_unicode(content)) + self.assertIn("", content) + self.assertIn("background-color: var(--bg-color);", content) def test_breadcrumbs(self): content = get_response_content('/_test/_test_folder/_test_page') From e2ee75e3cbc9a72140ba33416638569c332b983a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 13:44:53 +0530 Subject: [PATCH 201/868] fix: Translate strings passed in frappe.throw * Remove trailing whitespaces in translatable strings * Sort imports appropriately --- frappe/desk/doctype/dashboard/dashboard.py | 2 +- frappe/desk/doctype/dashboard_chart/dashboard_chart.py | 5 ++--- frappe/model/mapper.py | 6 ++++-- frappe/utils/jinja.py | 4 ++-- frappe/utils/password.py | 2 +- frappe/www/search.py | 9 +++++---- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/frappe/desk/doctype/dashboard/dashboard.py b/frappe/desk/doctype/dashboard/dashboard.py index d2e79279d9..1d333609db 100644 --- a/frappe/desk/doctype/dashboard/dashboard.py +++ b/frappe/desk/doctype/dashboard/dashboard.py @@ -21,7 +21,7 @@ class Dashboard(Document): def validate(self): if not frappe.conf.developer_mode and self.is_standard: - frappe.throw('Cannot edit Standard Dashboards') + frappe.throw(_("Cannot edit Standard Dashboards")) if self.is_standard: non_standard_docs_map = { diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py index 3bea6eded9..db5964e7b2 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py @@ -8,8 +8,7 @@ import datetime import json from frappe.utils.dashboard import cache_source from frappe.utils import nowdate, getdate, get_datetime, cint, now_datetime -from frappe.utils.dateutils import\ - get_period, get_period_beginning, get_from_date_from_timespan, get_dates_from_timegrain +from frappe.utils.dateutils import get_period, get_period_beginning, get_from_date_from_timespan, get_dates_from_timegrain from frappe.model.naming import append_number_if_name_exists from frappe.boot import get_allowed_reports from frappe.config import get_modules_from_all_apps_for_user @@ -325,7 +324,7 @@ class DashboardChart(Document): def validate(self): if not frappe.conf.developer_mode and self.is_standard: - frappe.throw('Cannot edit Standard charts') + frappe.throw(_("Cannot edit Standard charts")) if self.chart_type != 'Custom' and self.chart_type != 'Report': self.check_required_field() self.check_document_type() diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index eb685fb840..8b1543c99e 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -1,10 +1,12 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt +import json -import frappe, json +import frappe from frappe import _ -from frappe.utils import cstr from frappe.model import default_fields, table_fields +from frappe.utils import cstr + @frappe.whitelist() def make_mapped_doc(method, source_name, selected_children=None, args=None): diff --git a/frappe/utils/jinja.py b/frappe/utils/jinja.py index 685208e71f..65ea2c20b8 100644 --- a/frappe/utils/jinja.py +++ b/frappe/utils/jinja.py @@ -65,7 +65,7 @@ def render_template(template, context, is_path=None, safe_render=True): :param safe_render: (optional) prevent server side scripting via jinja templating ''' - from frappe import get_traceback, throw + from frappe import _, get_traceback, throw from jinja2 import TemplateError if not template: @@ -75,7 +75,7 @@ def render_template(template, context, is_path=None, safe_render=True): return get_jenv().get_template(template).render(context) else: if safe_render and ".__" in template: - throw("Illegal template") + throw(_("Illegal template")) try: return get_jenv().from_string(template).render(context) except TemplateError: diff --git a/frappe/utils/password.py b/frappe/utils/password.py index 005a3cede6..d86275c39c 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -60,7 +60,7 @@ def set_encrypted_password(doctype, name, pwd, fieldname='password'): except frappe.db.DataError as e: if ((frappe.db.db_type == 'mariadb' and e.args[0] == DATA_TOO_LONG) or (frappe.db.db_type == 'postgres' and e.pgcode == STRING_DATA_RIGHT_TRUNCATION)): - frappe.throw("Most probably your password is too long.", exc=e) + frappe.throw(_("Most probably your password is too long."), exc=e) raise e diff --git a/frappe/www/search.py b/frappe/www/search.py index 292c9e532f..db3a8eb118 100644 --- a/frappe/www/search.py +++ b/frappe/www/search.py @@ -1,16 +1,17 @@ +from html2text import html2text +from jinja2 import utils import frappe -from frappe.utils.global_search import web_search -from html2text import html2text from frappe import _ -from jinja2 import utils from frappe.utils import sanitize_html +from frappe.utils.global_search import web_search + def get_context(context): context.no_cache = 1 if frappe.form_dict.q: query = str(utils.escape(sanitize_html(frappe.form_dict.q))) - context.title = _('Search Results for ') + context.title = _('Search Results for') context.query = query context.route = '/search' context.update(get_search_results(query, frappe.utils.sanitize_html(frappe.form_dict.scope))) From 6fb14120d9dcce31a080aaa68e21616c44b3ca35 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 13:47:55 +0530 Subject: [PATCH 202/868] fix: Remove trailing whitespace in translatable str Simplify conditional block and str appending --- frappe/model/mapper.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index 8b1543c99e..fa8858d950 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -137,10 +137,8 @@ def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None, def map_doc(source_doc, target_doc, table_map, source_parent=None): if table_map.get("validation"): for key, condition in table_map["validation"].items(): - if condition[0]=="=": - if source_doc.get(key) != condition[1]: - frappe.throw(_("Cannot map because following condition fails: ") - + key + "=" + cstr(condition[1])) + if condition[0] == "=" and source_doc.get(key) != condition[1]: + frappe.throw(_("Cannot map because following condition fails:") + f" {key}={cstr(condition[1])}") map_fields(source_doc, target_doc, table_map, source_parent) From 96c03fd26dfb46738572de8a0bc5db4b80014b10 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 13:48:58 +0530 Subject: [PATCH 203/868] chore: Drop commented out test_translation file --- frappe/tests/test_translation.py | 63 -------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 frappe/tests/test_translation.py diff --git a/frappe/tests/test_translation.py b/frappe/tests/test_translation.py deleted file mode 100644 index 94af1bb870..0000000000 --- a/frappe/tests/test_translation.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt -import frappe, unittest, os -import frappe.translate - -# class TestTranslations(unittest.TestCase): -# def test_doctype(self, messages=None): -# if not messages: -# messages = frappe.translate.get_messages_from_doctype("Role") -# self.assertTrue("Role Name" in messages) -# -# def test_page(self, messages=None): -# if not messages: -# messages = frappe.translate.get_messages_from_page("finder") -# self.assertTrue("Finder" in messages) -# -# def test_report(self, messages=None): -# if not messages: -# messages = frappe.translate.get_messages_from_report("ToDo") -# self.assertTrue("Test" in messages) -# -# def test_include_js(self, messages=None): -# if not messages: -# messages = frappe.translate.get_messages_from_include_files("frappe") -# self.assertTrue("History" in messages) -# -# def test_server(self, messages=None): -# if not messages: -# messages = frappe.translate.get_server_messages("frappe") -# self.assertTrue("Login" in messages) -# self.assertTrue("Did not save" in messages) -# -# def test_all_app(self): -# messages = frappe.translate.get_messages_for_app("frappe") -# self.test_doctype(messages) -# self.test_page(messages) -# self.test_report(messages) -# self.test_include_js(messages) -# self.test_server(messages) -# -# def test_load_translations(self): -# frappe.translate.clear_cache() -# self.assertFalse(frappe.cache().hget("lang_full_dict", "de")) -# -# langdict = frappe.translate.get_full_dict("de") -# self.assertEqual(langdict['Row'], 'Reihe') -# -# def test_write_csv(self): -# tpath = frappe.get_pymodule_path("frappe", "translations", "de.csv") -# if os.path.exists(tpath): -# os.remove(tpath) -# frappe.translate.write_translations_file("frappe", "de") -# self.assertTrue(os.path.exists(tpath)) -# self.assertEqual(dict(frappe.translate.read_csv_file(tpath)).get("Row"), "Reihe") -# -# def test_get_dict(self): -# frappe.local.lang = "de" -# self.assertEqual(frappe.get_lang_dict("doctype", "Role").get("Role"), "Rolle") -# frappe.local.lang = "en" -# -# if __name__=="__main__": -# frappe.connect("site1") -# unittest.main() From c8749bcc72a48abd7815dea3c4fc2aa59d223e2a Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 27 May 2021 14:27:30 +0530 Subject: [PATCH 204/868] fix: get_index_path_options method --- frappe/website/page_renderers/template_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index 8f613ae9bd..d1f0b47032 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -55,7 +55,7 @@ class TemplatePage(BaseTemplatePage): @staticmethod def get_index_path_options(search_path): - return (frappe.as_unicode(f'{search_path}{d}') for d in ('.html', '.md', '/index.html', '/index.md')) + return (frappe.as_unicode(f'{search_path}{d}') for d in ('', '.html', '.md', '/index.html', '/index.md')) def render(self): return build_response(self.path, self.get_html(), self.http_status_code, self.headers) From 369adf5a3a303612edf9f0169c7b37b7c711a852 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 27 May 2021 14:44:47 +0530 Subject: [PATCH 205/868] fix: Set default value as empty string --- frappe/website/page_renderers/web_page.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/website/page_renderers/web_page.py b/frappe/website/page_renderers/web_page.py index 1814a9615a..20e5bab062 100644 --- a/frappe/website/page_renderers/web_page.py +++ b/frappe/website/page_renderers/web_page.py @@ -7,10 +7,10 @@ class WebPage(object): if not path: path = frappe.local.request.path self.path = path.strip('/ ') - self.basepath = None - self.basename = None - self.name = None - self.route = None + self.basepath = '' + self.basename = '' + self.name = '' + self.route = '' self.file_dir = None def can_render(self): From 1a41e16e2a5d724b04b5ef0acaced5887f2db658 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 27 May 2021 15:14:27 +0530 Subject: [PATCH 206/868] fix: Blog post style --- frappe/public/scss/website/blog.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frappe/public/scss/website/blog.scss b/frappe/public/scss/website/blog.scss index 9918b490c5..ea82efed21 100644 --- a/frappe/public/scss/website/blog.scss +++ b/frappe/public/scss/website/blog.scss @@ -14,6 +14,10 @@ position: relative; width: 100%; + .card { + border: 1px solid var(--border-color) + } + .card-body { display: flex; flex-direction: column; From 821e7513fff3f9386782c0492aae24e24c91d94e Mon Sep 17 00:00:00 2001 From: shariquerik Date: Thu, 27 May 2021 15:59:03 +0530 Subject: [PATCH 207/868] fix: tune button missing & sidebar drop-icon fix --- frappe/desk/doctype/workspace/workspace.py | 2 +- frappe/public/js/frappe/views/wiki.js | 7 +++ frappe/public/js/frappe/wiki_blocks/card.js | 53 ++++++++++++------- frappe/public/js/frappe/wiki_blocks/chart.js | 53 ++++++++++++------- frappe/public/js/frappe/wiki_blocks/header.js | 4 ++ .../public/js/frappe/wiki_blocks/shortcut.js | 53 ++++++++++++------- 6 files changed, 111 insertions(+), 61 deletions(-) diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index d9bf5fa618..52007b00cd 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -116,7 +116,7 @@ class Workspace(Document): "icon": card.get('icon'), "hidden": card.get('hidden') or False, "link_count": card.get('link_count'), - "idx": self.links[-1].idx + 1 + "idx": 1 if not self.links else self.links[-1].idx + 1 }) for link in links: diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index a0635f5494..83f80e8769 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -233,6 +233,12 @@ frappe.views.Wiki = class Wiki { if (this.sidebar_items && this.sidebar_items[this.current_page_name]) { this.sidebar_items[this.current_page_name][0].firstElementChild.classList.remove("selected"); this.sidebar_items[page][0].firstElementChild.classList.add("selected"); + if (this.sidebar_items[page].parents('.sidebar-item-container')[0]) { + this.sidebar_items[page] + .parents('.sidebar-item-container') + .find('.drop-icon use') + .attr("href", "#icon-small-up"); + } } this.current_page_name = page; localStorage.current_wiki_page = page; @@ -475,6 +481,7 @@ frappe.views.Wiki = class Wiki { } $sidebar_item.appendTo($child_section); $child_section.removeClass('hidden'); + $item_container.find('.drop-icon use').attr("href", "#icon-small-up"); } } diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index 820056a6ab..ecde804be2 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -42,31 +42,35 @@ export default class Card { } if (!this.readOnly) { - let $widget_control = $(this.wrapper).find('.widget-control'); - this.add_custom_button( - frappe.utils.icon('dot-horizontal', 'xs'), - (event) => { - let evn = event; - !$('.ce-settings.ce-settings--opened').length && - setTimeout(() => { - this.api.toolbar.toggleBlockSettings(); - var position = $(evn.target).offset(); - $('.ce-settings.ce-settings--opened').offset({ - top: position.top + 25, - left: position.left - 77 - }); - }, 50); - }, - "tune-btn", - `${__('Tune')}`, - null, - $widget_control - ); + this._add_tune_button(); } return this.wrapper; } + _add_tune_button() { + let $widget_control = $(this.wrapper).find('.widget-control'); + this.add_custom_button( + frappe.utils.icon('dot-horizontal', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50); + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control + ); + } + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { if (!btn_type) btn_type = 'btn-secondary'; let button = $( @@ -79,6 +83,14 @@ export default class Card { wrapper.prepend(button); } + validate(savedData) { + if (!savedData.card_name) { + return false; + } + + return true; + } + save(blockContent) { return { card_name: blockContent.getAttribute('card_name'), @@ -120,6 +132,7 @@ export default class Card { this.card_widget.customize(this.options); this.wrapper.setAttribute("card_name", this.card_widget.label); this.new_card_widget = this.card_widget.get_config(); + this._add_tune_button(); }, }); diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index c7f92222c0..c562b453ed 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -42,31 +42,35 @@ export default class Chart { } if (!this.readOnly) { - let $widget_control = $(this.wrapper).find('.widget-control'); - this.add_custom_button( - frappe.utils.icon('dot-horizontal', 'xs'), - (event) => { - let evn = event; - !$('.ce-settings.ce-settings--opened').length && - setTimeout(() => { - this.api.toolbar.toggleBlockSettings(); - var position = $(evn.target).offset(); - $('.ce-settings.ce-settings--opened').offset({ - top: position.top + 25, - left: position.left - 77 - }); - }, 50); - }, - "tune-btn", - `${__('Tune')}`, - null, - $widget_control - ); + this._add_tune_button(); } return this.wrapper; } + _add_tune_button() { + let $widget_control = $(this.wrapper).find('.widget-control'); + this.add_custom_button( + frappe.utils.icon('dot-horizontal', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50); + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control + ); + } + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { if (!btn_type) btn_type = 'btn-secondary'; let button = $( @@ -79,6 +83,14 @@ export default class Chart { wrapper.prepend(button); } + validate(savedData) { + if (!savedData.chart_name) { + return false; + } + + return true; + } + save(blockContent) { return { chart_name: blockContent.getAttribute('chart_name'), @@ -120,6 +132,7 @@ export default class Chart { this.chart_widget.customize(this.options); this.wrapper.setAttribute("chart_name", this.chart_widget.label); this.new_chart_widget = this.chart_widget.get_config(); + this._add_tune_button(); }, }); diff --git a/frappe/public/js/frappe/wiki_blocks/header.js b/frappe/public/js/frappe/wiki_blocks/header.js index 727f495a42..a3fcc39175 100644 --- a/frappe/public/js/frappe/wiki_blocks/header.js +++ b/frappe/public/js/frappe/wiki_blocks/header.js @@ -296,6 +296,10 @@ export default class Header { tag.classList.add(this._CSS.wrapper); + if (!this.readOnly) { + tag.contentEditable = true; + } + tag.dataset.placeholder = this.api.i18n.t(this._settings.placeholder || ''); return tag; diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index c6d01a8800..dc1cbb5b5a 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -41,30 +41,34 @@ export default class Shortcut { } if (!this.readOnly) { - let $widget_control = $(this.wrapper).find('.widget-control'); - this.add_custom_button( - frappe.utils.icon('dot-horizontal', 'xs'), - (event) => { - let evn = event; - !$('.ce-settings.ce-settings--opened').length && - setTimeout(() => { - this.api.toolbar.toggleBlockSettings(); - var position = $(evn.target).offset(); - $('.ce-settings.ce-settings--opened').offset({ - top: position.top + 25, - left: position.left - 77 - }); - }, 50); - }, - "tune-btn", - `${__('Tune')}`, - null, - $widget_control - ); + this._add_tune_button(); } return this.wrapper; } + _add_tune_button() { + let $widget_control = $(this.wrapper).find('.widget-control'); + this.add_custom_button( + frappe.utils.icon('dot-horizontal', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50); + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control + ); + } + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { if (!btn_type) btn_type = 'btn-secondary'; let button = $( @@ -77,6 +81,14 @@ export default class Shortcut { wrapper.prepend(button); } + validate(savedData) { + if (!savedData.shortcut_name) { + return false; + } + + return true; + } + save(blockContent) { return { shortcut_name: blockContent.getAttribute('shortcut_name'), @@ -118,6 +130,7 @@ export default class Shortcut { this.shortcut_widget.customize(this.options); this.wrapper.setAttribute("shortcut_name", this.shortcut_widget.label); this.new_shortcut_widget = this.shortcut_widget.get_config(); + this._add_tune_button(); }, }); From 72c239342ed31e7bb3e1a7e0e07672872ea81000 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 27 May 2021 16:40:02 +0530 Subject: [PATCH 208/868] chore: Remove temporary warnings filter --- frappe/utils/bench_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/bench_helper.py b/frappe/utils/bench_helper.py index 2ee1e6691f..b406c7e427 100644 --- a/frappe/utils/bench_helper.py +++ b/frappe/utils/bench_helper.py @@ -100,5 +100,5 @@ def get_apps(): if __name__ == "__main__": if not frappe._dev_server: warnings.simplefilter('ignore') - warnings.simplefilter('always') + main() From 38efba692db8461df920bff5102b5ed9ab0b5b31 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 28 May 2021 08:44:41 +0530 Subject: [PATCH 209/868] fix: Conditionally set css variables --- .../website_theme/website_theme_template.scss | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/frappe/website/doctype/website_theme/website_theme_template.scss b/frappe/website/doctype/website_theme/website_theme_template.scss index 2a67baf541..34cd66a4fe 100644 --- a/frappe/website/doctype/website_theme/website_theme_template.scss +++ b/frappe/website/doctype/website_theme/website_theme_template.scss @@ -1,13 +1,13 @@ {% if google_font %} @import url("https://fonts.googleapis.com/css2?family={{ google_font.replace(' ', '+') }}:{{ font_properties }}&display=swap"); $font-family-sans-serif: "{{ google_font }}", -apple-system, BlinkMacSystemFont, - "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", - "Droid Sans", "Helvetica Neue", sans-serif; + "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", + "Droid Sans", "Helvetica Neue", sans-serif; {% endif -%} {% if primary_color %}$primary: {{ frappe.db.get_value('Color', primary_color, 'color') }};{% endif -%} {% if dark_color %}$dark: {{ frappe.db.get_value('Color', dark_color, 'color') }};{% endif -%} -{% if text_color %}$body-color: {{ frappe.db.get_value('Color', text_color, 'color') }};{% endif -%} +{% if text_color %}$body-text-color: {{ frappe.db.get_value('Color', text_color, 'color') }};{% endif -%} {% if background_color %}$body-bg: {{ frappe.db.get_value('Color', background_color, 'color') }};{% endif -%} $enable-shadows: {{ button_shadows and "true" or "false" }}; @@ -24,7 +24,7 @@ $enable-rounded: {{ button_rounded_corners and "true" or "false" }}; {% if font_size -%} body { - font-size: {{ font_size }}; + font-size: {{ font_size }}; } {%- endif %} @@ -32,12 +32,16 @@ body { {{ custom_scss or '' }} :root { + {% if primary_color %} --primary: #{$primary}; --primary-color: #{$primary}; - --primary-light: #{$primary-light}; - --light: #{$light}; + {% endif -%} + {% if background_color %} --bg-color: #{$body-bg}; - --text-color: #{$body-color}; - --text-light: #{$body-color}; + {% endif -%} + {% if text_color %} + --text-color: #{$body-text-color}; + --text-light: #{$body-text-color}; + {% endif -%} } From a4402868774af0ac1721fd48520cd12c158e0eb7 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 28 May 2021 09:14:27 +0530 Subject: [PATCH 210/868] fix: check if salutation already exists in email body (backport #13196) (#13358) --- frappe/public/js/frappe/views/communication.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index f65f1a83c2..e2aaec553d 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -724,9 +724,14 @@ frappe.views.CommunicationComposer = class { } message += await this.get_signature(); - if (this.real_name && !message.includes("")) { - message = `

    ${__('Dear')} ${this.real_name},

    -
    ${message}`; + + const SALUTATION_END_COMMENT = ""; + if (this.real_name && !message.includes(SALUTATION_END_COMMENT)) { + this.message = ` +

    ${__('Dear')} ${this.real_name},

    + ${SALUTATION_END_COMMENT}
    + ${message} + `; } if (this.is_a_reply) { From f14d9bd3dade7c09577b65c6b8a75495b53285c8 Mon Sep 17 00:00:00 2001 From: leela Date: Fri, 28 May 2021 07:50:31 +0530 Subject: [PATCH 211/868] fix: refresh form section while refreshing the field If all the fields with in a section has depends_on property and in such case section itself stays hidden as all fields with in it are hidden. Currently when any form field is updated, we are refreshing only the fields but not the sections. So, field refresh is not affecting the form because of section being hidden. Fix is to refresh the sections when ever form fields are refreshed. (cherry picked from commit 20c6e24a9f58a303b36da8cce247d273e6e3582f) --- frappe/public/js/frappe/form/form.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 88d7ceaa94..b7d375be8e 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -175,6 +175,7 @@ frappe.ui.form.Form = class FrappeForm { field && ["Link", "Dynamic Link"].includes(field.df.fieldtype) && field.validate && field.validate(value); me.layout.refresh_dependency(); + me.layout.refresh_sections(); let object = me.script_manager.trigger(fieldname, doc.doctype, doc.name); return object; } @@ -1078,6 +1079,7 @@ frappe.ui.form.Form = class FrappeForm { if (this.fields_dict[fname] && this.fields_dict[fname].refresh) { this.fields_dict[fname].refresh(); this.layout.refresh_dependency(); + this.layout.refresh_sections(); } } From 651a9ff42edf0ddf17aa66b9e851109ca83ac1c3 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 28 May 2021 21:43:07 +0530 Subject: [PATCH 212/868] fix: Return address 'name' instead of 'parent' field --- frappe/contacts/doctype/address/address.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index b3150aa75a..bfcf91427d 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -111,8 +111,8 @@ def get_default_address(doctype, name, sort_key='is_primary_address'): if out: for contact in out: if contact.get(sort_key): - return contact.parent - return out[0].parent + return contact.name + return out[0].name else: return None From 9b4c19192805499dcc870709351c78fedb3352d5 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Fri, 28 May 2021 23:10:59 +0530 Subject: [PATCH 213/868] chore: Update Jinja2 dependency Update from 2.11.3 to 3.0.1 Ref: https://jinja.palletsprojects.com/en/3.0.x/changes/ --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4f4614955b..8b1d9e649d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,7 +26,7 @@ html2text==2020.1.16 html5lib~=1.1 ipython~=7.16.1 jedi==0.17.2 # not directly required. Pinned to fix upstream IPython issue (https://github.com/ipython/ipython/issues/12740) -Jinja2~=2.11.3 +Jinja2~=3.0.1 ldap3~=2.9 markdown2~=2.4.0 maxminddb-geolite2==2018.703 From 165ff8e1bfe1a8e94b9995626ea5dd188b2e23f2 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Sat, 29 May 2021 17:22:30 +0530 Subject: [PATCH 214/868] chore: Update PyJWT dependency * Update pinned dep fromm 1.7.1 to 2.0.1 * Updated usages as per changelog ref: https://python.libhunt.com/pyjwt-changelog --- frappe/oauth.py | 3 ++- frappe/tests/test_oauth20.py | 2 +- frappe/utils/oauth.py | 2 +- requirements.txt | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frappe/oauth.py b/frappe/oauth.py index a4c66bf3f2..67d346ad8a 100644 --- a/frappe/oauth.py +++ b/frappe/oauth.py @@ -486,6 +486,7 @@ class OAuthWebRequestValidator(RequestValidator): user = None payload = jwt.decode( id_token_hint, + algorithms=["HS256"], options={ "verify_signature": False, "verify_aud": False, @@ -508,7 +509,7 @@ class OAuthWebRequestValidator(RequestValidator): id_token_hint, key=client_secret, audience=client_id, - algorithm="HS256", + algorithms=["HS256"], options={ "verify_exp": False, }, diff --git a/frappe/tests/test_oauth20.py b/frappe/tests/test_oauth20.py index cf3b2ea90d..2a5bed34b3 100644 --- a/frappe/tests/test_oauth20.py +++ b/frappe/tests/test_oauth20.py @@ -302,7 +302,7 @@ class TestOAuth20(unittest.TestCase): id_token, audience=client.client_id, key=client.client_secret, - algorithm="HS256", + algorithms=["HS256"], ) self.assertTrue(payload.get("nonce") == nonce) diff --git a/frappe/utils/oauth.py b/frappe/utils/oauth.py index 45cce737e1..9f5ff9d360 100644 --- a/frappe/utils/oauth.py +++ b/frappe/utils/oauth.py @@ -134,7 +134,7 @@ def get_info_via_oauth(provider, code, decoder=None, id_token=False): token = parsed_access['id_token'] - info = jwt.decode(token, flow.client_secret, verify=False) + info = jwt.decode(token, flow.client_secret, options={"verify_signature": False}) else: api_endpoint = oauth2_providers[provider].get("api_endpoint") api_endpoint_args = oauth2_providers[provider].get("api_endpoint_args") diff --git a/requirements.txt b/requirements.txt index 8b1d9e649d..0791f01b27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -43,7 +43,7 @@ psutil~=5.8.0 psycopg2-binary~=2.8.6 pyasn1~=0.4.8 pycryptodome~=3.10.1 -PyJWT~=1.7.1 +PyJWT~=2.0.1 PyMySQL~=1.0.2 pyngrok~=5.0.5 pyOpenSSL~=20.0.1 From 4ce8a600e8c607ba418b0dd79265f917518d57a6 Mon Sep 17 00:00:00 2001 From: leela Date: Mon, 31 May 2021 09:02:29 +0530 Subject: [PATCH 215/868] fix: Tests and sider issues --- .../doctype/email_account/email_account.py | 8 +++---- .../email_account/test_email_account.py | 22 +++++++++---------- frappe/email/receive.py | 2 -- frappe/tests/test_email.py | 5 ++--- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index eea2dfc73e..6ee106bb12 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -19,7 +19,7 @@ from frappe.utils import (validate_email_address, cint, cstr, get_datetime, from frappe.utils.user import is_system_user from frappe.utils.jinja import render_template from frappe.email.smtp import SMTPServer -from frappe.email.receive import EmailServer, Email, InboundMail, SentEmailInInboxError +from frappe.email.receive import EmailServer, InboundMail, SentEmailInInboxError from poplib import error_proto from dateutil.relativedelta import relativedelta from datetime import datetime, timedelta @@ -469,12 +469,12 @@ class EmailAccount(Document): """retrive and return inbound mails. """ - if not self.enable_incoming: - return [] - if frappe.local.flags.in_test: return [InboundMail(msg, self) for msg in test_mails or []] + if not self.enable_incoming: + return [] + email_sync_rule = self.build_email_sync_rule() try: email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 7bf49593f4..35cacac45a 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -1,23 +1,23 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -from __future__ import unicode_literals -from frappe.core.doctype import communication -from frappe.core.doctype.communication.communication import Communication +import os +import email +import unittest +from datetime import datetime, timedelta + from frappe.email.receive import InboundMail, SentEmailInInboxError, Email from frappe.email.email_body import get_message_id -import frappe, os -import unittest, email - +import frappe from frappe.test_runner import make_test_records +from frappe.core.doctype.communication.email import make +from frappe.desk.form.load import get_attachments +from frappe.email.doctype.email_account.email_account import notify_unreplied make_test_records("User") make_test_records("Email Account") -from frappe.core.doctype.communication.email import make -from frappe.desk.form.load import get_attachments -from frappe.email.doctype.email_account.email_account import notify_unreplied -from datetime import datetime, timedelta + class TestEmailAccount(unittest.TestCase): @classmethod @@ -240,7 +240,7 @@ class TestInboundMail(unittest.TestCase): email_account = frappe.get_doc("Email Account", "_Test Email Account 1") email_account.db_set("enable_incoming", 0) - def tearDown(self): + def setUp(self): cleanup() frappe.db.sql('delete from `tabEmail Queue`') frappe.db.sql('delete from `tabToDo`') diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 52b9110ddb..7b3623df21 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -821,7 +821,6 @@ class InboundMail(Email): @staticmethod def get_doc(doctype, docname, ignore_error=False): try: - print(doctype, docname) return frappe.get_doc(doctype, docname) except frappe.DoesNotExistError: if ignore_error: @@ -862,7 +861,6 @@ class InboundMail(Email): for field in email_fields: if hasattr(meta, field): fields[field] = getattr(meta, field) - print("FIELDS::::", fields) return fields @staticmethod diff --git a/frappe/tests/test_email.py b/frappe/tests/test_email.py index ff7e6d534c..a37d1a519c 100644 --- a/frappe/tests/test_email.py +++ b/frappe/tests/test_email.py @@ -1,8 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - import unittest, frappe, re, email from six import PY3 @@ -176,7 +174,8 @@ class TestEmail(unittest.TestCase): frappe.db.sql('''delete from `tabCommunication` where sender = 'sukh@yyy.com' ''') with open(frappe.get_app_path('frappe', 'tests', 'data', 'email_with_image.txt'), 'r') as raw: - communication = email_account.insert_communication(raw.read()) + mails = email_account.get_inbound_mails(test_mails=[raw.read()]) + communication = mails[0].process() self.assertTrue(re.search(''']*src=["']/private/files/rtco1.png[^>]*>''', communication.content)) self.assertTrue(re.search(''']*src=["']/private/files/rtco2.png[^>]*>''', communication.content)) From 799397abae5c594c47e9e7d8085156f8bb845a58 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 31 May 2021 10:23:22 +0530 Subject: [PATCH 216/868] refactor: Refactor code --- .../internal_wiki_page/internal_wiki_page.py | 11 +- frappe/public/js/frappe/utils/utils.js | 13 ++ frappe/public/js/frappe/views/wiki.js | 189 ++++++++--------- .../public/js/frappe/widgets/base_widget.js | 43 ++-- frappe/public/js/frappe/wiki_blocks/block.js | 150 +++++++++++++ frappe/public/js/frappe/wiki_blocks/card.js | 196 ++--------------- frappe/public/js/frappe/wiki_blocks/chart.js | 197 ++---------------- frappe/public/js/frappe/wiki_blocks/header.js | 96 ++------- .../public/js/frappe/wiki_blocks/paragraph.js | 98 ++------- .../public/js/frappe/wiki_blocks/shortcut.js | 196 ++--------------- frappe/public/js/frappe/wiki_blocks/spacer.js | 105 ++-------- 11 files changed, 355 insertions(+), 939 deletions(-) create mode 100644 frappe/public/js/frappe/wiki_blocks/block.js diff --git a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py index 6be92f835d..5d119e364d 100644 --- a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py +++ b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py @@ -52,13 +52,4 @@ def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, if json.loads(new_widgets): save_new_widget(title, new_widgets) - return doc.title - -@frappe.whitelist() -def get_page_content(page): - return frappe.db.get_value("Internal Wiki Page", page, "content") - -@frappe.whitelist() -def get_pages(): - return frappe.db.get_list('Internal Wiki Page', fields=['name', 'icon', 'private', 'parent_page', 'sequence_id'], - order_by="sequence_id asc") \ No newline at end of file + return doc.title \ No newline at end of file diff --git a/frappe/public/js/frappe/utils/utils.js b/frappe/public/js/frappe/utils/utils.js index 484d9c65f1..9e20e419be 100644 --- a/frappe/public/js/frappe/utils/utils.js +++ b/frappe/public/js/frappe/utils/utils.js @@ -1319,5 +1319,18 @@ Object.assign(frappe.utils, { let e = clipboard_paste_event; let clipboard_data = e.clipboardData || window.clipboardData || e.originalEvent.clipboardData; return clipboard_data.getData('Text'); + }, + + add_custom_button(html, action, class_name = "", title="", btn_type, wrapper, prepend) { + if (!btn_type) btn_type = 'btn-secondary'; + let button = $( + `` + ); + button.click(event => { + event.stopPropagation(); + action && action(event); + }); + !prepend && button.appendTo(wrapper); + prepend && wrapper.prepend(button); } }); diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index 83f80e8769..f247f34330 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -57,7 +57,8 @@ frappe.views.Wiki = class Wiki { } setup_wiki_pages() { - this.get_pages().then(() => { + this.get_pages().then(pages => { + this.all_pages = pages; if (this.all_pages) { frappe.wiki_pages = {}; let root_pages = this.all_pages.filter(page => page.parent_page == '' || page.parent_page == null); @@ -75,11 +76,29 @@ frappe.views.Wiki = class Wiki { } get_pages() { - return frappe.xcall("frappe.desk.doctype.internal_wiki_page.internal_wiki_page.get_pages").then(data => { - this.all_pages = data; + return frappe.db.get_list('Internal Wiki Page', { + fields: ['name', 'icon', 'private', 'parent_page', 'sequence_id'], + order_by: "sequence_id asc" }); } + sidebar_item_container(item) { + return $(` + + `); + } + make_sidebar(items) { if (this.sidebar.find('.standard-sidebar-section')[0]) { this.sidebar.find('.standard-sidebar-section')[0].remove(); @@ -136,60 +155,19 @@ frappe.views.Wiki = class Wiki { } } - sidebar_item_container(item) { - return $(` - - `); - } - show() { if (!this.all_pages) { // pages not yet loaded, call again after a bit setTimeout(() => { this.show(); - }, 500); + }, 100); return; } + let page = this.get_page_to_show(); this.page.set_title(`${__(page)}`); - this.show_page(page); - this.get_content(page).then(() => { - this.get_data(page).then(() => { - if (this.content) { - if (this.editor) { - this.editor.isReady.then(() => { - this.editor.configuration.tools.chart.config.page_data = this.page_data; - this.editor.configuration.tools.shortcut.config.page_data = this.page_data; - this.editor.configuration.tools.card.config.page_data = this.page_data; - this.editor.render({ - blocks: JSON.parse(this.content) || [] - }); - }); - } else { - this.initialize_editorjs(JSON.parse(this.content)); - } - } - }); - }); - } - get_content(page) { - return frappe.xcall("frappe.desk.doctype.internal_wiki_page.internal_wiki_page.get_page_content", { - page: page - }).then(data => { - this.content = data; - }); + this.show_page(page); } get_data(page) { @@ -233,6 +211,7 @@ frappe.views.Wiki = class Wiki { if (this.sidebar_items && this.sidebar_items[this.current_page_name]) { this.sidebar_items[this.current_page_name][0].firstElementChild.classList.remove("selected"); this.sidebar_items[page][0].firstElementChild.classList.add("selected"); + if (this.sidebar_items[page].parents('.sidebar-item-container')[0]) { this.sidebar_items[page] .parents('.sidebar-item-container') @@ -240,6 +219,7 @@ frappe.views.Wiki = class Wiki { .attr("href", "#icon-small-up"); } } + this.current_page_name = page; localStorage.current_wiki_page = page; @@ -252,6 +232,28 @@ frappe.views.Wiki = class Wiki { } this.setup_actions(); + this.prepare_editorjs(page); + } + + prepare_editorjs(page) { + frappe.db.get_value("Internal Wiki Page", page, "content") + .then(content => { + this.content = JSON.parse(content.message["content"]); + this.get_data(page).then(() => { + if (this.editor) { + this.editor.isReady.then(() => { + this.editor.configuration.tools.chart.config.page_data = this.page_data; + this.editor.configuration.tools.shortcut.config.page_data = this.page_data; + this.editor.configuration.tools.card.config.page_data = this.page_data; + this.editor.render({ + blocks: this.content || [] + }); + }); + } else { + this.initialize_editorjs(this.content); + } + }); + }); } setup_actions() { @@ -280,16 +282,49 @@ frappe.views.Wiki = class Wiki { initialize_editorjs_undo() { this.undo = new Undo({ editor: this.editor }); - this.undo.initialize({blocks: JSON.parse(this.content)}); + this.undo.initialize({blocks: this.content}); this.undo.readOnly = false; } + setup_customization_buttons() { + this.page.clear_primary_action(); + this.page.clear_secondary_action(); + this.page.clear_inner_toolbar(); + + this.page.set_primary_action( + __("Save Customizations"), + () => { + this.page.clear_primary_action(); + this.page.clear_secondary_action(); + this.undo.readOnly = true; + this.save_page(); + this.editor.readOnly.toggle(); + this.isReadOnly = true; + }, + null, + __("Saving") + ); + + this.page.set_secondary_action( + __("Discard"), + () => { + this.page.clear_primary_action(); + this.page.clear_secondary_action(); + this.editor.readOnly.toggle(); + this.isReadOnly = true; + this.deleted_sidebar_items = []; + this.reload(); + frappe.show_alert({ message: __("Customizations Discarded"), indicator: "info" }); + } + ); + } + show_sidebar_actions() { this.sidebar.find('.standard-sidebar-section').addClass('show-control'); } add_sidebar_actions(item, sidebar_control) { - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('drag', 'xs'), null, "drag-handle", @@ -297,7 +332,7 @@ frappe.views.Wiki = class Wiki { null, sidebar_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('delete', 'xs'), () => this.delete_page(item.name), "delete-page", @@ -307,18 +342,6 @@ frappe.views.Wiki = class Wiki { ); } - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(); - }); - button.appendTo(wrapper); - } - delete_page(name) { if (!this.deleted_sidebar_items.includes(name)) { this.deleted_sidebar_items.push(name); @@ -370,39 +393,6 @@ frappe.views.Wiki = class Wiki { }); } - setup_customization_buttons() { - this.page.clear_primary_action(); - this.page.clear_secondary_action(); - this.page.clear_inner_toolbar(); - - this.page.set_primary_action( - __("Save Customizations"), - () => { - this.page.clear_primary_action(); - this.page.clear_secondary_action(); - this.undo.readOnly = true; - this.save_page(); - this.editor.readOnly.toggle(); - this.isReadOnly = true; - }, - null, - __("Saving") - ); - - this.page.set_secondary_action( - __("Discard"), - () => { - this.page.clear_primary_action(); - this.page.clear_secondary_action(); - this.editor.readOnly.toggle(); - this.isReadOnly = true; - this.deleted_sidebar_items = []; - this.reload(); - frappe.show_alert({ message: __("Customizations Discarded"), indicator: "info" }); - } - ); - } - initialize_new_page() { const d = new frappe.ui.Dialog({ title: __('Set Title'), @@ -459,7 +449,7 @@ frappe.views.Wiki = class Wiki { }; let $sidebar_item = this.sidebar_item_container(item); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('drag', 'xs'), null, "drag-handle", @@ -486,13 +476,12 @@ frappe.views.Wiki = class Wiki { } initialize_editorjs(blocks) { - const data = { - blocks: blocks || [] - }; this.editor = new EditorJS({ + data: { + blocks: blocks || [] + }, tools: this.tools, autofocus: false, - data, tunes: ['spacingTune'], readOnly: true, logLevel: 'ERROR' diff --git a/frappe/public/js/frappe/widgets/base_widget.js b/frappe/public/js/frappe/widgets/base_widget.js index 821df609ef..90a2c1e641 100644 --- a/frappe/public/js/frappe/widgets/base_widget.js +++ b/frappe/public/js/frappe/widgets/base_widget.js @@ -25,18 +25,23 @@ export default class Widget { this.action_area.empty(); options.allow_sorting && - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('drag', 'xs'), null, "drag-handle", + `${__('Drag')}`, + null, + this.action_area ); options.allow_delete && - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('delete', 'xs'), () => this.delete(), "", - `${__('Delete')}` + `${__('Delete')}`, + null, + this.action_area ); if (options.allow_hiding) { @@ -48,11 +53,13 @@ export default class Widget { } const classname = this.hidden ? 'fa fa-eye' : 'fa fa-eye-slash'; const title = this.hidden ? `${__('Show')}` : `${__('Hide')}`; - this.add_custom_button( + frappe.utils.add_custom_button( ``, () => this.hide_or_show(), "show-or-hide-button", - title + title, + null, + this.action_area ); this.show_or_hide_button = this.action_area.find( @@ -61,18 +68,24 @@ export default class Widget { } options.allow_edit && - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon("edit", "xs"), - () => this.edit() + () => this.edit(), + null, + `${__('Edit')}`, + null, + this.action_area ); if (options.allow_resize) { const title = this.width == 'Full'? `${__('Collapse')}` : `${__('Expand')}`; - this.add_custom_button( + frappe.utils.add_custom_button( '', () => this.toggle_width(), "resize-button", - title + title, + null, + this.action_area ); this.resize_button = this.action_area.find( @@ -129,18 +142,6 @@ export default class Widget { this.subtitle && this.subtitle_field.html(this.subtitle); } - add_custom_button(html, action, class_name = "", title="", btn_type) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(); - }); - button.appendTo(this.action_area); - } - delete(animate=true) { let remove_widget = (setup_new) => { this.widget.remove(); diff --git a/frappe/public/js/frappe/wiki_blocks/block.js b/frappe/public/js/frappe/wiki_blocks/block.js new file mode 100644 index 0000000000..1f8cdf1f21 --- /dev/null +++ b/frappe/public/js/frappe/wiki_blocks/block.js @@ -0,0 +1,150 @@ +import get_dialog_constructor from "../widgets/widget_dialog.js"; + +export default class Block { + constructor(opts) { + Object.assign(this, opts); + } + + make(block, block_name, widget_type = block) { + let block_data = this.config.page_data[block+'s'].items.find(obj => { + return obj.label == block_name; + }); + if (!block_data) return; + this.wrapper.innerHTML = ''; + block_data.in_customize_mode = !this.readOnly; + this.block_widget = new frappe.widget.SingleWidgetGroup({ + container: this.wrapper, + type: widget_type, + class_name: block == 'chart' ? 'widget-charts' : '', + options: this.options, + widgets: block_data, + api: this.api, + block: this.block + }); + this.wrapper.setAttribute(block+'_name', block_name); + if (!this.readOnly) { + this.block_widget.customize(); + } + } + + rendered() { + var e = this.wrapper.closest('.ce-block'); + e.classList.add("col-" + this.col); + e.classList.add("pt-" + this.pt); + e.classList.add("pr-" + this.pr); + e.classList.add("pb-" + this.pb); + e.classList.add("pl-" + this.pl); + } + + new(block, widget_type = block) { + const dialog_class = get_dialog_constructor(widget_type); + let block_name = block+'_name'; + this.dialog = new dialog_class({ + label: this.label, + type: widget_type, + primary_action: (widget) => { + widget.in_customize_mode = 1; + this.block_widget = frappe.widget.make_widget({ + ...widget, + widget_type: widget_type, + container: this.wrapper, + options: { + ...this.options, + on_delete: () => this.api.blocks.delete(), + on_edit: () => this.on_edit(this.block_widget) + } + }); + this.block_widget.customize(this.options); + this.wrapper.setAttribute(block_name, this.block_widget.label); + this.new_block_widget = this.block_widget.get_config(); + this.add_tune_button(); + }, + }); + + if (!this.readOnly && this.data && !this.data[block_name]) { + this.dialog.make(); + } + } + + on_edit(block_obj) { + let block_name = block_obj.edit_dialog.type+'_name'; + if (block_obj.edit_dialog.type == 'links') { + block_name = 'card_name'; + } + let block = block_obj.get_config(); + this.block_widget.widgets = block; + this.wrapper.setAttribute(block_name, block.label); + this.new_block_widget = block_obj.get_config(); + } + + add_tune_button() { + let $widget_control = $(this.wrapper).find('.widget-control'); + frappe.utils.add_custom_button( + frappe.utils.icon('dot-horizontal', 'xs'), + (event) => { + let evn = event; + !$('.ce-settings.ce-settings--opened').length && + setTimeout(() => { + this.api.toolbar.toggleBlockSettings(); + var position = $(evn.target).offset(); + $('.ce-settings.ce-settings--opened').offset({ + top: position.top + 25, + left: position.left - 77 + }); + }, 50); + }, + "tune-btn", + `${__('Tune')}`, + null, + $widget_control, + true + ); + } + + get_col() { + let col = 12; + let class_name = "col-12"; + let wrapper = this.wrapper.closest('.ce-block'); + const col_class = new RegExp(/\bcol-.+?\b/, "g"); + if (wrapper.className.match(col_class)) { + wrapper.classList.forEach(function (cn) { + cn.match(col_class) && (class_name = cn); + }); + let parts = class_name.split("-"); + col = parseInt(parts[1]); + } + return col; + } + + get_padding() { + let direction = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; + let padding = 0; + let pad_name = "p" + direction + "-0"; + let wrapper = this.wrapper.closest('.ce-block'); + let pad_left = new RegExp(/\pl-.+?\b/, "g"); + let pad_right = new RegExp(/\pr-.+?\b/, "g"); + let pad_top = new RegExp(/\pt-.+?\b/, "g"); + let pad_bottom = new RegExp(/\pb-.+?\b/, "g"); + + const get_padding = (pad_direction) => { + if (wrapper.className.match(pad_direction)) { + wrapper.classList.forEach(function (cn) { + cn.match(pad_direction) && (pad_name = cn); + }); + let parts = pad_name.split("-"); + padding = parseInt(parts[1]); + } + } + + if ("l" == direction) { + get_padding(pad_left); + } else if ("r" == direction) { + get_padding(pad_right); + } else if ("t" == direction) { + get_padding(pad_top); + } else if ("b" == direction) { + get_padding(pad_bottom); + } + return padding; + } +} \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index ecde804be2..ed3704cc2d 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -1,5 +1,5 @@ -import get_dialog_constructor from "../widgets/widget_dialog.js"; -export default class Card { +import Block from "./block.js"; +export default class Card extends Block { static get toolbox() { return { title: 'Card', @@ -11,12 +11,8 @@ export default class Card { return true; } - constructor({data, api, config, readOnly, block}) { - this.data = data; - this.api = api; - this.block = block; - this.config = config; - this.readOnly = readOnly; + constructor(opts = {data, api, config, readOnly, block}) { + super(opts) this.sections = {}; this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; @@ -35,54 +31,19 @@ export default class Card { render() { this.wrapper = document.createElement('div'); - this._new_card(); + this.new('card', 'links'); if (this.data && this.data.card_name) { - this._make_cards(this.data.card_name); + this.make('card', this.data.card_name, 'links'); } if (!this.readOnly) { - this._add_tune_button(); + this.add_tune_button(); } return this.wrapper; } - _add_tune_button() { - let $widget_control = $(this.wrapper).find('.widget-control'); - this.add_custom_button( - frappe.utils.icon('dot-horizontal', 'xs'), - (event) => { - let evn = event; - !$('.ce-settings.ce-settings--opened').length && - setTimeout(() => { - this.api.toolbar.toggleBlockSettings(); - var position = $(evn.target).offset(); - $('.ce-settings.ce-settings--opened').offset({ - top: position.top + 25, - left: position.left - 77 - }); - }, 50); - }, - "tune-btn", - `${__('Tune')}`, - null, - $widget_control - ); - } - - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(event); - }); - wrapper.prepend(button); - } - validate(savedData) { if (!savedData.card_name) { return false; @@ -94,143 +55,12 @@ export default class Card { save(blockContent) { return { card_name: blockContent.getAttribute('card_name'), - col: this._getCol(), - pt: this._getPadding("t"), - pr: this._getPadding("r"), - pb: this._getPadding("b"), - pl: this._getPadding("l"), - new: this.new_card_widget + col: this.get_col(), + pt: this.get_padding("t"), + pr: this.get_padding("r"), + pb: this.get_padding("b"), + pl: this.get_padding("l"), + new: this.new_block_widget }; } - - rendered() { - var e = this.wrapper.closest('.ce-block'); - e.classList.add("col-" + this.col); - e.classList.add("pt-" + this.pt); - e.classList.add("pr-" + this.pr); - e.classList.add("pb-" + this.pb); - e.classList.add("pl-" + this.pl); - } - - _new_card() { - const dialog_class = get_dialog_constructor('links'); - this.dialog = new dialog_class({ - label: this.label, - type: 'card', - primary_action: (widget) => { - widget.in_customize_mode = 1; - this.card_widget = frappe.widget.make_widget({ - ...widget, - widget_type: 'links', - container: this.wrapper, - options: { - ...this.options, - on_delete: () => this.api.blocks.delete(), - on_edit: () => this.on_edit(this.card_widget) - } - }); - this.card_widget.customize(this.options); - this.wrapper.setAttribute("card_name", this.card_widget.label); - this.new_card_widget = this.card_widget.get_config(); - this._add_tune_button(); - }, - }); - - if (!this.readOnly && this.data && !this.data.card_name) { - this.dialog.make(); - } - } - - _getCol() { - var e = 12; - var t = "col-12"; - var n = this.wrapper.closest('.ce-block'); - var r = new RegExp(/\bcol-.+?\b/, "g"); - if (n.className.match(r)) { - n.classList.forEach(function (e) { - e.match(r) && (t = e); - }); - var a = t.split("-"); - e = parseInt(a[1]); - } - return e; - } - - _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - var t = 0; - var n = "p" + e + "-0"; - var r = this.wrapper.closest('.ce-block'); - var a = new RegExp(/\pl-.+?\b/, "g"); - var i = new RegExp(/\pr-.+?\b/, "g"); - var o = new RegExp(/\pt-.+?\b/, "g"); - var c = new RegExp(/\pb-.+?\b/, "g"); - if ("l" == e) { - if (r.className.match(a)) { - r.classList.forEach(function (e) { - e.match(a) && (n = e); - }); - var s = n.split("-"); - t = parseInt(s[1]); - } - } else if ("r" == e) { - if (r.className.match(i)) { - r.classList.forEach(function (e) { - e.match(i) && (n = e); - }); - var l = n.split("-"); - t = parseInt(l[1]); - } - } else if ("t" == e) { - if (r.className.match(o)) { - r.classList.forEach(function (e) { - e.match(o) && (n = e); - }); - var u = n.split("-"); - t = parseInt(u[1]); - } - } else if ("b" == e && r.className.match(c)) { - r.classList.forEach(function (e) { - e.match(c) && (n = e); - }); - var p = n.split("-"); - t = parseInt(p[1]); - } - return t; - } - - _make_fieldgroup(parent, ddf_list) { - this.card_field = new frappe.ui.FieldGroup({ - "fields": ddf_list, - "parent": parent - }); - this.card_field.make(); - } - - on_edit(card_obj) { - let card = card_obj.get_config(); - this.card_widget.widgets = card; - this.wrapper.setAttribute("card_name", card.label); - this.new_card_widget = card_obj.get_config(); - } - - _make_cards(card_name) { - let card = this.config.page_data.cards.items.find(obj => { - return obj.label == card_name; - }); - this.wrapper.innerHTML = ''; - card.in_customize_mode = !this.readOnly; - this.card_widget = new frappe.widget.SingleWidgetGroup({ - container: this.wrapper, - type: "links", - options: this.options, - widgets: card, - api: this.api, - block: this.block - }); - this.wrapper.setAttribute("card_name", card_name); - if (!this.readOnly) { - this.card_widget.customize(); - } - } } \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index c562b453ed..cf43cc5455 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -1,5 +1,5 @@ -import get_dialog_constructor from "../widgets/widget_dialog.js"; -export default class Chart { +import Block from "./block.js"; +export default class Chart extends Block { static get toolbox() { return { title: 'Chart', @@ -11,12 +11,8 @@ export default class Chart { return true; } - constructor({data, api, config, readOnly, block}) { - this.data = data; - this.api = api; - this.block = block; - this.config = config; - this.readOnly = readOnly; + constructor(opts = {data, api, config, readOnly, block}) { + super(opts) this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; @@ -35,54 +31,19 @@ export default class Chart { render() { this.wrapper = document.createElement('div'); - this._new_chart(); + this.new('chart'); if (this.data && this.data.chart_name) { - this._make_charts(this.data.chart_name); + this.make('chart', this.data.chart_name); } if (!this.readOnly) { - this._add_tune_button(); + this.add_tune_button(); } return this.wrapper; } - _add_tune_button() { - let $widget_control = $(this.wrapper).find('.widget-control'); - this.add_custom_button( - frappe.utils.icon('dot-horizontal', 'xs'), - (event) => { - let evn = event; - !$('.ce-settings.ce-settings--opened').length && - setTimeout(() => { - this.api.toolbar.toggleBlockSettings(); - var position = $(evn.target).offset(); - $('.ce-settings.ce-settings--opened').offset({ - top: position.top + 25, - left: position.left - 77 - }); - }, 50); - }, - "tune-btn", - `${__('Tune')}`, - null, - $widget_control - ); - } - - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(event); - }); - wrapper.prepend(button); - } - validate(savedData) { if (!savedData.chart_name) { return false; @@ -94,144 +55,12 @@ export default class Chart { save(blockContent) { return { chart_name: blockContent.getAttribute('chart_name'), - col: this._getCol(), - pt: this._getPadding("t"), - pr: this._getPadding("r"), - pb: this._getPadding("b"), - pl: this._getPadding("l"), - new: this.new_chart_widget + col: this.get_col(), + pt: this.get_padding("t"), + pr: this.get_padding("r"), + pb: this.get_padding("b"), + pl: this.get_padding("l"), + new: this.new_block_widget }; } - - rendered() { - var e = this.wrapper.closest('.ce-block'); - e.classList.add("col-" + this.col); - e.classList.add("pt-" + this.pt); - e.classList.add("pr-" + this.pr); - e.classList.add("pb-" + this.pb); - e.classList.add("pl-" + this.pl); - } - - _new_chart() { - const dialog_class = get_dialog_constructor('chart'); - this.dialog = new dialog_class({ - label: this.label, - type: 'chart', - primary_action: (widget) => { - widget.in_customize_mode = 1; - this.chart_widget = frappe.widget.make_widget({ - ...widget, - widget_type: 'chart', - container: this.wrapper, - options: { - ...this.options, - on_delete: () => this.api.blocks.delete(), - on_edit: () => this.on_edit(this.chart_widget) - } - }); - this.chart_widget.customize(this.options); - this.wrapper.setAttribute("chart_name", this.chart_widget.label); - this.new_chart_widget = this.chart_widget.get_config(); - this._add_tune_button(); - }, - }); - - if (!this.readOnly && this.data && !this.data.chart_name) { - this.dialog.make(); - } - } - - _getCol() { - var e = 12; - var t = "col-12"; - var n = this.wrapper.closest('.ce-block'); - var r = new RegExp(/\bcol-.+?\b/, "g"); - if (n.className.match(r)) { - n.classList.forEach(function (e) { - e.match(r) && (t = e); - }); - var a = t.split("-"); - e = parseInt(a[1]); - } - return e; - } - - _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - var t = 0; - var n = "p" + e + "-0"; - var r = this.wrapper.closest('.ce-block'); - var a = new RegExp(/\pl-.+?\b/, "g"); - var i = new RegExp(/\pr-.+?\b/, "g"); - var o = new RegExp(/\pt-.+?\b/, "g"); - var c = new RegExp(/\pb-.+?\b/, "g"); - if ("l" == e) { - if (r.className.match(a)) { - r.classList.forEach(function (e) { - e.match(a) && (n = e); - }); - var s = n.split("-"); - t = parseInt(s[1]); - } - } else if ("r" == e) { - if (r.className.match(i)) { - r.classList.forEach(function (e) { - e.match(i) && (n = e); - }); - var l = n.split("-"); - t = parseInt(l[1]); - } - } else if ("t" == e) { - if (r.className.match(o)) { - r.classList.forEach(function (e) { - e.match(o) && (n = e); - }); - var u = n.split("-"); - t = parseInt(u[1]); - } - } else if ("b" == e && r.className.match(c)) { - r.classList.forEach(function (e) { - e.match(c) && (n = e); - }); - var p = n.split("-"); - t = parseInt(p[1]); - } - return t; - } - - _make_fieldgroup(parent, ddf_list) { - this.chart_field = new frappe.ui.FieldGroup({ - "fields": ddf_list, - "parent": parent - }); - this.chart_field.make(); - } - - on_edit(chart_obj) { - let chart = chart_obj.get_config(); - this.chart_widget.widgets = chart; - this.wrapper.setAttribute("chart_name", chart.label); - this.new_chart_widget = chart_obj.get_config(); - } - - _make_charts(chart_name) { - let chart = this.config.page_data.charts.items.find(obj => { - return obj.label == chart_name; - }); - if (!chart) return; - this.wrapper.innerHTML = ''; - this.chart_widget = new frappe.widget.SingleWidgetGroup({ - container: this.wrapper, - type: "chart", - class_name: "widget-charts", - options: this.options, - widgets: chart, - api: this.api, - block: this.block - }); - this.wrapper.setAttribute("chart_name", chart_name); - if (!this.readOnly) { - this.chart_widget.customize(); - } - } } \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/header.js b/frappe/public/js/frappe/wiki_blocks/header.js index a3fcc39175..eeb6054e63 100644 --- a/frappe/public/js/frappe/wiki_blocks/header.js +++ b/frappe/public/js/frappe/wiki_blocks/header.js @@ -1,8 +1,9 @@ -export default class Header { +import Block from "./block.js"; +export default class Header extends Block { constructor({ data, config, api, readOnly }) { - this.api = api; - this.readOnly = readOnly; + let opts = { config, api, readOnly }; + super(opts); this._CSS = { block: this.api.styles.block, @@ -11,7 +12,7 @@ export default class Header { wrapper: 'ce-header', }; - this._settings = config; + this._settings = this.config; this._data = this.normalizeData(data); this.settingsButtons = []; this._element = this.getTag(); @@ -55,7 +56,7 @@ export default class Header { this.wrapper.classList.add('widget', 'header'); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; @@ -75,7 +76,7 @@ export default class Header { $widget_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('drag', 'xs'), null, "drag-handle", @@ -84,7 +85,7 @@ export default class Header { $widget_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('delete', 'xs'), () => this.api.blocks.delete(), "delete-header", @@ -98,18 +99,6 @@ export default class Header { return this._element; } - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(event); - }); - button.appendTo(wrapper); - } - renderSettings() { const holder = document.createElement('DIV'); @@ -167,14 +156,15 @@ export default class Header { } save(toolsContent) { + this.wrapper = this._element; return { text: toolsContent.innerText, level: this.currentLevel.number, - col: this._getCol(), - pt: this._getPadding("t"), - pr: this._getPadding("r"), - pb: this._getPadding("b"), - pl: this._getPadding("l") + col: this.get_col(), + pt: this.get_padding("t"), + pr: this.get_padding("r"), + pb: this.get_padding("b"), + pl: this.get_padding("l") }; } @@ -187,64 +177,6 @@ export default class Header { e.classList.add("pl-" + this.pl); } - _getCol() { - var e = 12; - var t = "col-12"; - var n = this._element.closest('.ce-block'); - var r = new RegExp(/\bcol-.+?\b/, "g"); - if (n.className.match(r)) { - n.classList.forEach(function (e) { - e.match(r) && (t = e); - }); - var a = t.split("-"); - e = parseInt(a[1]); - } - return e; - } - - _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - var t = 0; - var n = "p" + e + "-0"; - var r = this._element.closest('.ce-block'); - var a = new RegExp(/\pl-.+?\b/, "g"); - var i = new RegExp(/\pr-.+?\b/, "g"); - var o = new RegExp(/\pt-.+?\b/, "g"); - var c = new RegExp(/\pb-.+?\b/, "g"); - if ("l" == e) { - if (r.className.match(a)) { - r.classList.forEach(function (e) { - e.match(a) && (n = e); - }); - var s = n.split("-"); - t = parseInt(s[1]); - } - } else if ("r" == e) { - if (r.className.match(i)) { - r.classList.forEach(function (e) { - e.match(i) && (n = e); - }); - var l = n.split("-"); - t = parseInt(l[1]); - } - } else if ("t" == e) { - if (r.className.match(o)) { - r.classList.forEach(function (e) { - e.match(o) && (n = e); - }); - var u = n.split("-"); - t = parseInt(u[1]); - } - } else if ("b" == e && r.className.match(c)) { - r.classList.forEach(function (e) { - e.match(c) && (n = e); - }); - var p = n.split("-"); - t = parseInt(p[1]); - } - return t; - } - static get conversionConfig() { return { export: 'text', // use 'text' property for other blocks diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index cc05f3edbc..3a5f411954 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -1,12 +1,13 @@ -export default class Paragraph { +import Block from "./block.js"; +export default class Paragraph extends Block{ static get DEFAULT_PLACEHOLDER() { return ''; } constructor({data, config, api, readOnly}) { - this.api = api; - this.readOnly = readOnly; + let opts = {config, api, readOnly}; + super(opts); this._CSS = { block: this.api.styles.block, @@ -17,10 +18,10 @@ export default class Paragraph { this.onKeyUp = this.onKeyUp.bind(this); } - this._placeholder = config.placeholder ? config.placeholder : Paragraph.DEFAULT_PLACEHOLDER; + this._placeholder = this.config.placeholder ? this.config.placeholder : Paragraph.DEFAULT_PLACEHOLDER; this._data = {}; this._element = this.drawView(); - this._preserveBlank = config.preserveBlank !== undefined ? config.preserveBlank : false; + this._preserveBlank = this.config.preserveBlank !== undefined ? this.config.preserveBlank : false; this.data = data; this.col = this.data.col ? this.data.col : "12"; @@ -68,7 +69,7 @@ export default class Paragraph { this.wrapper.classList.add('widget'); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; @@ -88,7 +89,7 @@ export default class Paragraph { $para_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('drag', 'xs'), null, "drag-handle", @@ -97,7 +98,7 @@ export default class Paragraph { $para_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('delete', 'xs'), () => this.api.blocks.delete(), "delete-paragraph", @@ -111,18 +112,6 @@ export default class Paragraph { return this._element; } - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(event); - }); - button.appendTo(wrapper); - } - merge(data) { let newData = { text: this.data.text + data.text @@ -140,13 +129,14 @@ export default class Paragraph { } save(toolsContent) { + this.wrapper = this._element; return { text: toolsContent.innerText, - col: this._getCol(), - pt: this._getPadding("t"), - pr: this._getPadding("r"), - pb: this._getPadding("b"), - pl: this._getPadding("l") + col: this.get_col(), + pt: this.get_padding("t"), + pr: this.get_padding("r"), + pb: this.get_padding("b"), + pl: this.get_padding("l") }; } @@ -159,64 +149,6 @@ export default class Paragraph { e.classList.add("pl-" + this.pl); } - _getCol() { - var e = 12; - var t = "col-12"; - var n = this._element.closest('.ce-block'); - var r = new RegExp(/\bcol-.+?\b/, "g"); - if (n.className.match(r)) { - n.classList.forEach(function (e) { - e.match(r) && (t = e); - }); - var a = t.split("-"); - e = parseInt(a[1]); - } - return e; - } - - _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - var t = 0; - var n = "p" + e + "-0"; - var r = this._element.closest('.ce-block'); - var a = new RegExp(/\pl-.+?\b/, "g"); - var i = new RegExp(/\pr-.+?\b/, "g"); - var o = new RegExp(/\pt-.+?\b/, "g"); - var c = new RegExp(/\pb-.+?\b/, "g"); - if ("l" == e) { - if (r.className.match(a)) { - r.classList.forEach(function (e) { - e.match(a) && (n = e); - }); - var s = n.split("-"); - t = parseInt(s[1]); - } - } else if ("r" == e) { - if (r.className.match(i)) { - r.classList.forEach(function (e) { - e.match(i) && (n = e); - }); - var l = n.split("-"); - t = parseInt(l[1]); - } - } else if ("t" == e) { - if (r.className.match(o)) { - r.classList.forEach(function (e) { - e.match(o) && (n = e); - }); - var u = n.split("-"); - t = parseInt(u[1]); - } - } else if ("b" == e && r.className.match(c)) { - r.classList.forEach(function (e) { - e.match(c) && (n = e); - }); - var p = n.split("-"); - t = parseInt(p[1]); - } - return t; - } - onPaste(event) { const data = { text: event.detail.data.innerHTML diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index dc1cbb5b5a..d7b4a9b4f1 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -1,5 +1,5 @@ -import get_dialog_constructor from "../widgets/widget_dialog.js"; -export default class Shortcut { +import Block from "./block.js"; +export default class Shortcut extends Block { static get toolbox() { return { title: 'Shortcut', @@ -11,12 +11,8 @@ export default class Shortcut { return true; } - constructor({data, api, config, readOnly, block}) { - this.data = data; - this.api = api; - this.block = block; - this.config = config; - this.readOnly = readOnly; + constructor(opts = {data, api, config, readOnly, block}) { + super(opts); this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; @@ -34,53 +30,18 @@ export default class Shortcut { render() { this.wrapper = document.createElement('div'); - this._new_shortcut(); + this.new('shortcut'); if (this.data && this.data.shortcut_name) { - this._make_shortcuts(this.data.shortcut_name); + this.make('shortcut', this.data.shortcut_name); } if (!this.readOnly) { - this._add_tune_button(); + this.add_tune_button(); } return this.wrapper; } - _add_tune_button() { - let $widget_control = $(this.wrapper).find('.widget-control'); - this.add_custom_button( - frappe.utils.icon('dot-horizontal', 'xs'), - (event) => { - let evn = event; - !$('.ce-settings.ce-settings--opened').length && - setTimeout(() => { - this.api.toolbar.toggleBlockSettings(); - var position = $(evn.target).offset(); - $('.ce-settings.ce-settings--opened').offset({ - top: position.top + 25, - left: position.left - 77 - }); - }, 50); - }, - "tune-btn", - `${__('Tune')}`, - null, - $widget_control - ); - } - - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(event); - }); - wrapper.prepend(button); - } - validate(savedData) { if (!savedData.shortcut_name) { return false; @@ -92,143 +53,12 @@ export default class Shortcut { save(blockContent) { return { shortcut_name: blockContent.getAttribute('shortcut_name'), - col: this._getCol(), - pt: this._getPadding("t"), - pr: this._getPadding("r"), - pb: this._getPadding("b"), - pl: this._getPadding("l"), - new: this.new_shortcut_widget + col: this.get_col(), + pt: this.get_padding("t"), + pr: this.get_padding("r"), + pb: this.get_padding("b"), + pl: this.get_padding("l"), + new: this.new_block_widget }; } - - rendered() { - var e = this.wrapper.closest('.ce-block'); - e.classList.add("col-" + this.col); - e.classList.add("pt-" + this.pt); - e.classList.add("pr-" + this.pr); - e.classList.add("pb-" + this.pb); - e.classList.add("pl-" + this.pl); - } - - _new_shortcut() { - const dialog_class = get_dialog_constructor('shortcut'); - this.dialog = new dialog_class({ - label: this.label, - type: 'shortcut', - primary_action: (widget) => { - widget.in_customize_mode = 1; - this.shortcut_widget = frappe.widget.make_widget({ - ...widget, - widget_type: 'shortcut', - container: this.wrapper, - options: { - ...this.options, - on_delete: () => this.api.blocks.delete(), - on_edit: () => this.on_edit(this.shortcut_widget) - } - }); - this.shortcut_widget.customize(this.options); - this.wrapper.setAttribute("shortcut_name", this.shortcut_widget.label); - this.new_shortcut_widget = this.shortcut_widget.get_config(); - this._add_tune_button(); - }, - }); - - if (!this.readOnly && this.data && !this.data.shortcut_name) { - this.dialog.make(); - } - } - - _getCol() { - var e = 12; - var t = "col-12"; - var n = this.wrapper.closest('.ce-block'); - var r = new RegExp(/\bcol-.+?\b/, "g"); - if (n.className.match(r)) { - n.classList.forEach(function (e) { - e.match(r) && (t = e); - }); - var a = t.split("-"); - e = parseInt(a[1]); - } - return e; - } - - _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - var t = 0; - var n = "p" + e + "-0"; - var r = this.wrapper.closest('.ce-block'); - var a = new RegExp(/\pl-.+?\b/, "g"); - var i = new RegExp(/\pr-.+?\b/, "g"); - var o = new RegExp(/\pt-.+?\b/, "g"); - var c = new RegExp(/\pb-.+?\b/, "g"); - if ("l" == e) { - if (r.className.match(a)) { - r.classList.forEach(function (e) { - e.match(a) && (n = e); - }); - var s = n.split("-"); - t = parseInt(s[1]); - } - } else if ("r" == e) { - if (r.className.match(i)) { - r.classList.forEach(function (e) { - e.match(i) && (n = e); - }); - var l = n.split("-"); - t = parseInt(l[1]); - } - } else if ("t" == e) { - if (r.className.match(o)) { - r.classList.forEach(function (e) { - e.match(o) && (n = e); - }); - var u = n.split("-"); - t = parseInt(u[1]); - } - } else if ("b" == e && r.className.match(c)) { - r.classList.forEach(function (e) { - e.match(c) && (n = e); - }); - var p = n.split("-"); - t = parseInt(p[1]); - } - return t; - } - - _make_fieldgroup(parent, ddf_list) { - this.shortcut_field = new frappe.ui.FieldGroup({ - "fields": ddf_list, - "parent": parent - }); - this.shortcut_field.make(); - } - - on_edit(shortcut_obj) { - let shortcut = shortcut_obj.get_config(); - this.shortcut_widget.widgets = shortcut; - this.wrapper.setAttribute("shortcut_name", shortcut.label); - this.new_shortcut_widget = shortcut_obj.get_config(); - } - - _make_shortcuts(shortcut_name) { - let shortcut = this.config.page_data.shortcuts.items.find(obj => { - return obj.label == shortcut_name; - }); - this.wrapper.innerHTML = ''; - shortcut.in_customize_mode = !this.readOnly; - this.shortcut_widget = new frappe.widget.SingleWidgetGroup({ - container: this.wrapper, - type: "shortcut", - options: this.options, - widgets: shortcut, - api: this.api, - block: this.block - }); - this.wrapper.setAttribute("shortcut_name", shortcut_name); - if (!this.readOnly) { - this.shortcut_widget.customize(); - } - } } \ No newline at end of file diff --git a/frappe/public/js/frappe/wiki_blocks/spacer.js b/frappe/public/js/frappe/wiki_blocks/spacer.js index 5f26f06ca4..d2b7707ced 100644 --- a/frappe/public/js/frappe/wiki_blocks/spacer.js +++ b/frappe/public/js/frappe/wiki_blocks/spacer.js @@ -1,4 +1,5 @@ -export default class Spacer { +import Block from './block.js'; +export default class Spacer extends Block { static get toolbox() { return { title: 'Spacer', @@ -10,11 +11,8 @@ export default class Spacer { return true; } - constructor({data, api, config, readOnly}) { - this.data = data; - this.api = api; - this.config = config; - this.readOnly = readOnly; + constructor(opts = {data, api, config, readOnly}) { + super(opts); this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; @@ -39,7 +37,7 @@ export default class Spacer { let $widget_control = $spacer.find('.widget-control'); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('dot-horizontal', 'xs'), (event) => { let evn = event; @@ -59,7 +57,7 @@ export default class Spacer { $widget_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('drag', 'xs'), null, "drag-handle", @@ -68,7 +66,7 @@ export default class Spacer { $widget_control ); - this.add_custom_button( + frappe.utils.add_custom_button( frappe.utils.icon('delete', 'xs'), () => this.api.blocks.delete(), "delete-spacer", @@ -80,92 +78,13 @@ export default class Spacer { return this.wrapper; } - add_custom_button(html, action, class_name = "", title="", btn_type, wrapper) { - if (!btn_type) btn_type = 'btn-secondary'; - let button = $( - `` - ); - button.click(event => { - event.stopPropagation(); - action && action(event); - }); - button.appendTo(wrapper); - } - save() { return { - col: this._getCol(), - pt: this._getPadding("t"), - pr: this._getPadding("r"), - pb: this._getPadding("b"), - pl: this._getPadding("l") + col: this.get_col(), + pt: this.get_padding("t"), + pr: this.get_padding("r"), + pb: this.get_padding("b"), + pl: this.get_padding("l") }; } - - rendered() { - var e = this.wrapper.closest('.ce-block'); - e.classList.add("col-" + this.col); - e.classList.add("pt-" + this.pt); - e.classList.add("pr-" + this.pr); - e.classList.add("pb-" + this.pb); - e.classList.add("pl-" + this.pl); - } - - _getCol() { - var e = 12; - var t = "col-12"; - var n = this.wrapper.closest('.ce-block'); - var r = new RegExp(/\bcol-.+?\b/, "g"); - if (n.className.match(r)) { - n.classList.forEach(function (e) { - e.match(r) && (t = e); - }); - var a = t.split("-"); - e = parseInt(a[1]); - } - return e; - } - - _getPadding() { - var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "l"; - var t = 0; - var n = "p" + e + "-0"; - var r = this.wrapper.closest('.ce-block'); - var a = new RegExp(/\pl-.+?\b/, "g"); - var i = new RegExp(/\pr-.+?\b/, "g"); - var o = new RegExp(/\pt-.+?\b/, "g"); - var c = new RegExp(/\pb-.+?\b/, "g"); - if ("l" == e) { - if (r.className.match(a)) { - r.classList.forEach(function (e) { - e.match(a) && (n = e); - }); - var s = n.split("-"); - t = parseInt(s[1]); - } - } else if ("r" == e) { - if (r.className.match(i)) { - r.classList.forEach(function (e) { - e.match(i) && (n = e); - }); - var l = n.split("-"); - t = parseInt(l[1]); - } - } else if ("t" == e) { - if (r.className.match(o)) { - r.classList.forEach(function (e) { - e.match(o) && (n = e); - }); - var u = n.split("-"); - t = parseInt(u[1]); - } - } else if ("b" == e && r.className.match(c)) { - r.classList.forEach(function (e) { - e.match(c) && (n = e); - }); - var p = n.split("-"); - t = parseInt(p[1]); - } - return t; - } } \ No newline at end of file From 8aff94d514fe7cc898f407620764d07642d8a30e Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Mon, 31 May 2021 10:30:26 +0530 Subject: [PATCH 217/868] fix(jinja): Remove frappe.utils.jinja.get_jenv() from jinja globals --- frappe/utils/jinja_globals.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py index 347d52dc57..2881a21aff 100644 --- a/frappe/utils/jinja_globals.py +++ b/frappe/utils/jinja_globals.py @@ -2,7 +2,6 @@ # MIT License. See license.txt from __future__ import unicode_literals -from frappe.utils.jinja import get_jenv def resolve_class(classes): @@ -22,6 +21,8 @@ def resolve_class(classes): def inspect(var, render=True): + from frappe.utils.jinja import get_jenv + context = {"var": var} if render: html = "
    {{ var | pprint | e }}
    " From e73efaec04b86d41eb4a773288fd2ab73aa327a4 Mon Sep 17 00:00:00 2001 From: Saqib Date: Mon, 31 May 2021 10:42:50 +0530 Subject: [PATCH 218/868] fix: Return promise while reloading doc (#13219) --- frappe/public/js/frappe/form/form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index b7d375be8e..35ebf9274d 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -1069,7 +1069,7 @@ frappe.ui.form.Form = class FrappeForm { if(!this.doc.__islocal) { frappe.model.remove_from_locals(this.doctype, this.docname); - frappe.model.with_doc(this.doctype, this.docname, () => { + return frappe.model.with_doc(this.doctype, this.docname, () => { this.refresh(); }); } From 2cc90ceafe725f177f22f223d40c437c164b715c Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 31 May 2021 11:13:51 +0530 Subject: [PATCH 219/868] fix: sider fix --- frappe/public/js/frappe/views/wiki.js | 9 +++++---- frappe/public/js/frappe/wiki_blocks/block.js | 2 +- frappe/public/js/frappe/wiki_blocks/card.js | 4 ++-- frappe/public/js/frappe/wiki_blocks/chart.js | 4 ++-- frappe/public/js/frappe/wiki_blocks/paragraph.js | 2 +- frappe/public/js/frappe/wiki_blocks/shortcut.js | 4 ++-- frappe/public/js/frappe/wiki_blocks/spacer.js | 4 ++-- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index f247f34330..06964a9d38 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -140,8 +140,8 @@ frappe.views.Wiki = class Wiki { this.add_drop_icon(item, sidebar_control, $item_container); } - add_drop_icon(item, sidebar_control, $item_container) { - let $child_item_section = $item_container.find('.sidebar-child-item'); + add_drop_icon(item, sidebar_control, item_container) { + let $child_item_section = item_container.find('.sidebar-child-item'); let $drop_icon = $(``) .appendTo(sidebar_control); @@ -400,7 +400,8 @@ frappe.views.Wiki = class Wiki { { label: __('Title'), fieldtype: 'Data', - fieldname: 'title' + fieldname: 'title', + "reqd": 1 }, { label: __('Parent'), @@ -422,7 +423,7 @@ frappe.views.Wiki = class Wiki { type: "header", data: { text: this.title, - level: 2 + level: 4 } } ] diff --git a/frappe/public/js/frappe/wiki_blocks/block.js b/frappe/public/js/frappe/wiki_blocks/block.js index 1f8cdf1f21..a3f95890c7 100644 --- a/frappe/public/js/frappe/wiki_blocks/block.js +++ b/frappe/public/js/frappe/wiki_blocks/block.js @@ -134,7 +134,7 @@ export default class Block { let parts = pad_name.split("-"); padding = parseInt(parts[1]); } - } + }; if ("l" == direction) { get_padding(pad_left); diff --git a/frappe/public/js/frappe/wiki_blocks/card.js b/frappe/public/js/frappe/wiki_blocks/card.js index ed3704cc2d..0c8dc4ca82 100644 --- a/frappe/public/js/frappe/wiki_blocks/card.js +++ b/frappe/public/js/frappe/wiki_blocks/card.js @@ -11,8 +11,8 @@ export default class Card extends Block { return true; } - constructor(opts = {data, api, config, readOnly, block}) { - super(opts) + constructor({data, api, config, readOnly, block}) { + super(arguments[0]); this.sections = {}; this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; diff --git a/frappe/public/js/frappe/wiki_blocks/chart.js b/frappe/public/js/frappe/wiki_blocks/chart.js index cf43cc5455..505d03c732 100644 --- a/frappe/public/js/frappe/wiki_blocks/chart.js +++ b/frappe/public/js/frappe/wiki_blocks/chart.js @@ -11,8 +11,8 @@ export default class Chart extends Block { return true; } - constructor(opts = {data, api, config, readOnly, block}) { - super(opts) + constructor({data, api, config, readOnly, block}) { + super(arguments[0]); this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; diff --git a/frappe/public/js/frappe/wiki_blocks/paragraph.js b/frappe/public/js/frappe/wiki_blocks/paragraph.js index 3a5f411954..ebabcc98b6 100644 --- a/frappe/public/js/frappe/wiki_blocks/paragraph.js +++ b/frappe/public/js/frappe/wiki_blocks/paragraph.js @@ -1,5 +1,5 @@ import Block from "./block.js"; -export default class Paragraph extends Block{ +export default class Paragraph extends Block { static get DEFAULT_PLACEHOLDER() { return ''; diff --git a/frappe/public/js/frappe/wiki_blocks/shortcut.js b/frappe/public/js/frappe/wiki_blocks/shortcut.js index d7b4a9b4f1..7de8097715 100644 --- a/frappe/public/js/frappe/wiki_blocks/shortcut.js +++ b/frappe/public/js/frappe/wiki_blocks/shortcut.js @@ -11,8 +11,8 @@ export default class Shortcut extends Block { return true; } - constructor(opts = {data, api, config, readOnly, block}) { - super(opts); + constructor({data, api, config, readOnly, block}) { + super(arguments[0]); this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; diff --git a/frappe/public/js/frappe/wiki_blocks/spacer.js b/frappe/public/js/frappe/wiki_blocks/spacer.js index d2b7707ced..4a97dbcb02 100644 --- a/frappe/public/js/frappe/wiki_blocks/spacer.js +++ b/frappe/public/js/frappe/wiki_blocks/spacer.js @@ -11,8 +11,8 @@ export default class Spacer extends Block { return true; } - constructor(opts = {data, api, config, readOnly}) { - super(opts); + constructor({data, api, config, readOnly}) { + super(arguments[0]); this.col = this.data.col ? this.data.col : "12"; this.pt = this.data.pt ? this.data.pt : "0"; this.pr = this.data.pr ? this.data.pr : "0"; From 63a42f54b292d8592b7eb48ddf33686d17778547 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 31 May 2021 14:55:23 +0530 Subject: [PATCH 220/868] fix: Deprecation warning --- frappe/website/page_renderers/template_page.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index d1f0b47032..ea92c7103c 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -70,8 +70,8 @@ class TemplatePage(BaseTemplatePage): self.setup_template() self.update_context() self.post_process_context() - html = self.render_template() + html = self.render_template() html = self.update_toc(html) html = self.add_csrf_token(html) @@ -182,7 +182,8 @@ class TemplatePage(BaseTemplatePage): comment_tag = f"" if comment_tag in self.source: self.context[context_key] = value - click.echo(f'⚠️ DEPRECATION WARNING: {comment_tag} will be deprecated on 2021-12-31.') + click.echo(f'\n⚠️ DEPRECATION WARNING: {comment_tag} will be deprecated on 2021-12-31.') + click.echo(f'Please remove it from {self.template_path} in {self.app}') def run_pymodule_method(self, method): if hasattr(self.pymodule, method): From a42fc3c5dfe674a48c91cb29acb5e61cf03dd61c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 31 May 2021 14:56:09 +0530 Subject: [PATCH 221/868] feat: Option to add custom renderers --- frappe/website/path_resolver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index 9816900677..0519d82735 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -35,7 +35,8 @@ class PathResolver(): return frappe.flags.redirect_location, RedirectPage(self.path) endpoint = resolve_path(self.path) - renderers = (StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage) + custom_renderers = frappe.get_hooks('page_renderer') + renderers = custom_renderers + [StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage] for renderer in renderers: renderer_instance = renderer(endpoint, 200) From 384d875b6235573cef9ead8e9f0b2185167f78ff Mon Sep 17 00:00:00 2001 From: leela Date: Mon, 31 May 2021 15:42:45 +0530 Subject: [PATCH 222/868] refactor: smtp session creation cleanup --- frappe/email/smtp.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frappe/email/smtp.py b/frappe/email/smtp.py index 3acb76af23..2a1d6d297f 100644 --- a/frappe/email/smtp.py +++ b/frappe/email/smtp.py @@ -85,18 +85,19 @@ class SMTPServer: SMTP = smtplib.SMTP_SSL if self.use_ssl else smtplib.SMTP try: - self._session = SMTP(self.server, self.port) - if not self._session: + _session = SMTP(self.server, self.port) + if not _session: frappe.msgprint(CONNECTION_FAILED, raise_exception=frappe.OutgoingEmailError) - self.secure_session(self._session) + self.secure_session(_session) if self.login and self.password: - res = self._session.login(str(self.login or ""), str(self.password or "")) + res = _session.login(str(self.login or ""), str(self.password or "")) # check if logged correctly if res[0]!=235: frappe.msgprint(res[1], raise_exception=frappe.OutgoingEmailError) + self._session = _session return self._session except smtplib.SMTPAuthenticationError as e: From 77590184929bba29d08faf9823feaa0e32f55b46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 May 2021 16:26:38 +0530 Subject: [PATCH 223/868] chore(deps): bump ws from 7.4.2 to 7.4.6 (#13369) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86719d81f4..298c424b72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7608,9 +7608,9 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@~7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" - integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== xdg-basedir@^4.0.0: version "4.0.0" From 872299b3f3846be0c115c12bf74789b556cb2942 Mon Sep 17 00:00:00 2001 From: Fisher Yu <12823863+szufisher@users.noreply.github.com> Date: Mon, 31 May 2021 19:01:42 +0800 Subject: [PATCH 224/868] fix: Translate Strings (#13277) --- frappe/core/doctype/data_import/data_import.js | 2 +- frappe/core/doctype/doctype/doctype.js | 4 ++-- frappe/custom/doctype/customize_form/customize_form.js | 2 +- frappe/public/js/frappe/data_import/data_exporter.js | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frappe/core/doctype/data_import/data_import.js b/frappe/core/doctype/data_import/data_import.js index 079bdaa09c..216db53c72 100644 --- a/frappe/core/doctype/data_import/data_import.js +++ b/frappe/core/doctype/data_import/data_import.js @@ -91,7 +91,7 @@ frappe.ui.form.on('Data Import', { if (frm.doc.status.includes('Success')) { frm.add_custom_button( - __('Go to {0} List', [frm.doc.reference_doctype]), + __('Go to {0} List', [__(frm.doc.reference_doctype)]), () => frappe.set_route('List', frm.doc.reference_doctype) ); } diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js index 1a173f7252..b4d3fb9a89 100644 --- a/frappe/core/doctype/doctype/doctype.js +++ b/frappe/core/doctype/doctype/doctype.js @@ -33,11 +33,11 @@ frappe.ui.form.on('DocType', { if (!frm.is_new() && !frm.doc.istable) { if (frm.doc.issingle) { - frm.add_custom_button(__('Go to {0}', [frm.doc.name]), () => { + frm.add_custom_button(__('Go to {0}', [__(frm.doc.name)]), () => { window.open(`/app/${frappe.router.slug(frm.doc.name)}`); }); } else { - frm.add_custom_button(__('Go to {0} List', [frm.doc.name]), () => { + frm.add_custom_button(__('Go to {0} List', [__(frm.doc.name)]), () => { window.open(`/app/${frappe.router.slug(frm.doc.name)}`); }); } diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index d9d8ae196e..4e00456f0d 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -117,7 +117,7 @@ frappe.ui.form.on("Customize Form", { frappe.customize_form.set_primary_action(frm); frm.add_custom_button( - __("Go to {0} List", [frm.doc.doc_type]), + __("Go to {0} List", [__(frm.doc.doc_type)]), function() { frappe.set_route("List", frm.doc.doc_type); }, diff --git a/frappe/public/js/frappe/data_import/data_exporter.js b/frappe/public/js/frappe/data_import/data_exporter.js index dee4839b34..03e6288856 100644 --- a/frappe/public/js/frappe/data_import/data_exporter.js +++ b/frappe/public/js/frappe/data_import/data_exporter.js @@ -72,8 +72,8 @@ frappe.data_import.DataExporter = class DataExporter { let child_fieldname = df.fieldname; let label = df.reqd ? // prettier-ignore - __('{0} ({1}) (1 row mandatory)', [df.label || df.fieldname, doctype]) - : __('{0} ({1})', [df.label || df.fieldname, doctype]); + __('{0} ({1}) (1 row mandatory)', [__(df.label || df.fieldname), __(doctype)]) + : __('{0} ({1})', [__(df.label || df.fieldname), __(doctype)]); return { label, fieldname: child_fieldname, From 0afe774ddb1e8129a031ca136a3fff9d71dee5be Mon Sep 17 00:00:00 2001 From: getsali <30821137+getsali@users.noreply.github.com> Date: Mon, 31 May 2021 16:32:58 +0530 Subject: [PATCH 225/868] fix: Select appropriate email template response (#13051) * Update email_group.py Fix: Select appropriate email template response, Welcome email template can be either html or rich text * refactor: Simpify code Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> --- frappe/email/doctype/email_group/email_group.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/email/doctype/email_group/email_group.py b/frappe/email/doctype/email_group/email_group.py index b19a134713..b1c1295f75 100755 --- a/frappe/email/doctype/email_group/email_group.py +++ b/frappe/email/doctype/email_group/email_group.py @@ -105,6 +105,6 @@ def send_welcome_email(welcome_email, email, email_group): email=email, email_group=email_group ) - - message = frappe.render_template(welcome_email.response, args) + email_message = welcome_email.response or welcome_email.response_html + message = frappe.render_template(email_message, args) frappe.sendmail(email, subject=welcome_email.subject, message=message) From c033e0d34d9f257e8e8242e17bfbba43e24f1256 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Mon, 31 May 2021 19:24:36 +0530 Subject: [PATCH 226/868] fix(server scripts): Restrict access to python's internal attributes --- frappe/__init__.py | 17 +++++++++++++++++ frappe/utils/safe_exec.py | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/frappe/__init__.py b/frappe/__init__.py index 9b208f7c2d..5793b224a3 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1693,6 +1693,23 @@ def safe_eval(code, eval_globals=None, eval_locals=None): "round": round } + UNSAFE_ATTRIBUTES = { + # Generator Attributes + "gi_frame", "gi_code", + # Coroutine Attributes + "cr_frame", "cr_code", "cr_origin", + # Async Generator Attributes + "ag_code", "ag_frame", + # Traceback Attributes + "tb_frame", "tb_next", + # Format Attributes + "format", "format_map", + } + + for attribute in UNSAFE_ATTRIBUTES: + if attribute in code: + throw('Illegal rule {0}. Cannot use "{1}"'.format(bold(code), attribute)) + if '__' in code: throw('Illegal rule {0}. Cannot use "__"'.format(bold(code))) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index d1307a3a90..632fc5df23 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -150,6 +150,7 @@ def get_safe_globals(): # default writer allows write access out._write_ = _write out._getitem_ = _getitem + out._getattr_ = _getattr # allow iterators and list comprehension out._getiter_ = iter @@ -176,6 +177,27 @@ def _getitem(obj, key): raise SyntaxError('Key starts with _') return obj[key] +def _getattr(object, name, default=None): + # guard function for RestrictedPython + # allow any key to be accessed as long as + # 1. it does not start with an underscore (safer_getattr) + # 2. it is not an UNSAFE_ATTRIBUTES + + UNSAFE_ATTRIBUTES = { + # Generator Attributes + "gi_frame", "gi_code", + # Coroutine Attributes + "cr_frame", "cr_code", "cr_origin", + # Async Generator Attributes + "ag_code", "ag_frame", + # Traceback Attributes + "tb_frame", "tb_next", + } + + if isinstance(name, str) and (name in UNSAFE_ATTRIBUTES): + raise SyntaxError("{name} is an unsafe attribute".format(name=name)) + return RestrictedPython.Guards.safer_getattr(object, name, default=default) + def _write(obj): # guard function for RestrictedPython # allow writing to any object From 35590453dfa09f72c3f2cfd74a079cbb692535a9 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Mon, 31 May 2021 19:45:14 +0530 Subject: [PATCH 227/868] fix: minor fixes --- frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py index 5d119e364d..392169b502 100644 --- a/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py +++ b/frappe/desk/doctype/internal_wiki_page/internal_wiki_page.py @@ -12,7 +12,7 @@ class InternalWikiPage(Document): def before_insert(self): sequence_id_list = frappe.get_all('Internal Wiki Page', {'sequence_id'}) - self.sequence_id = max([page.sequence_id for page in sequence_id_list]) + 1 + self.sequence_id = max([page.sequence_id for page in sequence_id_list] or [0]) + 1 @frappe.whitelist() def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, save=True): From bcd6d2cb42a7e23ea274e0e3a64ff7a2f1499b4c Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 1 Jun 2021 11:25:15 +0530 Subject: [PATCH 228/868] fix: Added link count field in Workspace Link --- .../doctype/workspace_link/workspace_link.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/frappe/desk/doctype/workspace_link/workspace_link.json b/frappe/desk/doctype/workspace_link/workspace_link.json index 53dadad83d..a7b217be9e 100644 --- a/frappe/desk/doctype/workspace_link/workspace_link.json +++ b/frappe/desk/doctype/workspace_link/workspace_link.json @@ -8,15 +8,16 @@ "type", "label", "icon", - "only_for", "hidden", "link_details_section", "link_type", "link_to", "column_break_7", "dependencies", + "only_for", "onboard", - "is_query_report" + "is_query_report", + "link_count" ], "fields": [ { @@ -99,12 +100,19 @@ "fieldname": "is_query_report", "fieldtype": "Check", "label": "Is Query Report" + }, + { + "depends_on": "eval:doc.type == \"Card Break\"", + "fieldname": "link_count", + "fieldtype": "Int", + "hidden": 1, + "label": "Link Count" } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-05-13 13:10:18.128512", + "modified": "2021-06-01 11:23:28.990593", "modified_by": "Administrator", "module": "Desk", "name": "Workspace Link", From 55a49ce445aac635c09bfba14fbdadc621d59811 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 1 Jun 2021 17:39:25 +0530 Subject: [PATCH 229/868] fix: cannot set shortcut for actions menu item --- frappe/public/js/frappe/ui/page.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js index e740718ef9..a302c26892 100644 --- a/frappe/public/js/frappe/ui/page.js +++ b/frappe/public/js/frappe/ui/page.js @@ -377,11 +377,12 @@ frappe.ui.Page = class Page { }); } - add_actions_menu_item(label, click, standard) { + add_actions_menu_item(label, click, standard, shortcut) { return this.add_dropdown_item({ label, click, standard, + shortcut, parent: this.actions, show_parent: false }); From 39eee3e5c8fbd514ebedbd0526eb13508250336d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 1 Jun 2021 19:02:01 +0530 Subject: [PATCH 230/868] fix: Add min-width for awesomplete class --- frappe/public/scss/common/awesomeplete.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/public/scss/common/awesomeplete.scss b/frappe/public/scss/common/awesomeplete.scss index 096da1e2fd..619d6a9e3e 100644 --- a/frappe/public/scss/common/awesomeplete.scss +++ b/frappe/public/scss/common/awesomeplete.scss @@ -31,6 +31,7 @@ margin: 0; padding: var(--padding-xs); z-index: 1; + min-width: 250px; &> li { cursor: pointer; From f15edd21d1ca19d0353ca138a63d3d80d0848bd2 Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 1 Jun 2021 19:41:18 +0530 Subject: [PATCH 231/868] feat: enable use of custom encryption_key in encrypt()/decrypt() --- frappe/tests/test_password.py | 12 +++++++++++- frappe/utils/password.py | 14 +++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/frappe/tests/test_password.py b/frappe/tests/test_password.py index 98141072e2..9b68f3aace 100644 --- a/frappe/tests/test_password.py +++ b/frappe/tests/test_password.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils.password import update_password, check_password, passlibctx +from frappe.utils.password import update_password, check_password, passlibctx, encrypt, decrypt class TestPassword(unittest.TestCase): def setUp(self): @@ -105,6 +105,16 @@ class TestPassword(unittest.TestCase): doc.save() self.assertEqual(doc.get_password(raise_exception=False), None) + def test_custom_encryption_key(self): + text = 'Frappe Framework' + custom_encryption_key = 'DFTBA' + + encrypted_text = encrypt(text, encryption_key=custom_encryption_key) + decrypted_text = decrypt(encrypted_text, encryption_key=custom_encryption_key) + + self.assertEqual(text, decrypted_text) + + pass def get_password_list(doc): return frappe.db.sql("""SELECT `password` diff --git a/frappe/utils/password.py b/frappe/utils/password.py index fbed3cd8e7..d97c788568 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -157,20 +157,20 @@ def create_auth_table(): frappe.db.create_auth_table() -def encrypt(pwd): - cipher_suite = Fernet(encode(get_encryption_key())) - cipher_text = cstr(cipher_suite.encrypt(encode(pwd))) +def encrypt(txt, encryption_key=None): + cipher_suite = Fernet(encode(encryption_key or get_encryption_key())) + cipher_text = cstr(cipher_suite.encrypt(encode(txt))) return cipher_text -def decrypt(pwd): +def decrypt(txt, encryption_key=None): try: - cipher_suite = Fernet(encode(get_encryption_key())) - plain_text = cstr(cipher_suite.decrypt(encode(pwd))) + cipher_suite = Fernet(encode(encryption_key or get_encryption_key())) + plain_text = cstr(cipher_suite.decrypt(encode(txt))) return plain_text except InvalidToken: # encryption_key in site_config is changed and not valid - frappe.throw(_('Encryption key is invalid, Please check site_config.json')) + frappe.throw(_('Encryption key is invalid' + '!' if encryption_key else ', please check site_config.json.')) def get_encryption_key(): From 6596dd612f16225c065d3fbcbda3fad1248d0b08 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Tue, 1 Jun 2021 20:33:04 +0530 Subject: [PATCH 232/868] fix: User based Wiki Pages --- frappe/desk/desktop.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index ba4a44d7d7..f4d4796aef 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -543,20 +543,40 @@ def save_customization(page, config): def save_new_widget(page, new_widgets): original_page = frappe.get_doc("Workspace", page) + page_doc = get_custom_workspace_for_user(page) + + # Update field values + page_doc.update({ + "icon": original_page.icon, + "charts_label": original_page.charts_label, + "cards_label": original_page.cards_label, + "shortcuts_label": original_page.shortcuts_label, + "module": original_page.module, + "onboarding": original_page.onboarding, + "developer_mode_only": original_page.developer_mode_only, + "category": original_page.category, + "charts": original_page.charts, + "shortcuts": original_page.shortcuts, + "links": original_page.links, + }) + widgets = _dict(loads(new_widgets)) if widgets.chart: - original_page.charts.extend(new_widget(widgets.chart, "Workspace Chart", "charts")) + page_doc.charts.extend(new_widget(widgets.chart, "Workspace Chart", "charts")) if widgets.shortcut: - original_page.shortcuts.extend(new_widget(widgets.shortcut, "Workspace Shortcut", "shortcuts")) + page_doc.shortcuts.extend(new_widget(widgets.shortcut, "Workspace Shortcut", "shortcuts")) if widgets.card: - original_page.build_links_table_from_card(widgets.card) + page_doc.build_links_table_from_card(widgets.card) # remove duplicate and unwanted widgets - clean_up(original_page, page) + clean_up(page_doc, page) + + # Set label + page_doc.label = page + '-' + frappe.session.user try: - original_page.save(ignore_permissions=True) + page_doc.save(ignore_permissions=True) except (ValidationError, TypeError) as e: # Create a json string to log json_config = dumps(widgets, sort_keys=True, indent=4) From 464e93a405d831d6496d56956673068f3282436e Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 1 Jun 2021 21:32:32 +0530 Subject: [PATCH 233/868] fix: Allow only use of Fernet generated key for using custom encryption_key (#13399) * fix: only allow keys generated by fernet in encrypt()/decrypt() * fix: sider and semgrep fixes --- frappe/tests/test_password.py | 4 ++-- frappe/utils/password.py | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/frappe/tests/test_password.py b/frappe/tests/test_password.py index 9b68f3aace..6bc4bc7729 100644 --- a/frappe/tests/test_password.py +++ b/frappe/tests/test_password.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe import unittest from frappe.utils.password import update_password, check_password, passlibctx, encrypt, decrypt - +from cryptography.fernet import Fernet class TestPassword(unittest.TestCase): def setUp(self): frappe.delete_doc('Email Account', 'Test Email Account Password') @@ -107,7 +107,7 @@ class TestPassword(unittest.TestCase): def test_custom_encryption_key(self): text = 'Frappe Framework' - custom_encryption_key = 'DFTBA' + custom_encryption_key = Fernet.generate_key().decode() encrypted_text = encrypt(text, encryption_key=custom_encryption_key) decrypted_text = decrypt(encrypted_text, encryption_key=custom_encryption_key) diff --git a/frappe/utils/password.py b/frappe/utils/password.py index d97c788568..34719eb384 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -61,7 +61,7 @@ def set_encrypted_password(doctype, name, pwd, fieldname='password'): except frappe.db.DataError as e: if ((frappe.db.db_type == 'mariadb' and e.args[0] == DATA_TOO_LONG) or (frappe.db.db_type == 'postgres' and e.pgcode == STRING_DATA_RIGHT_TRUNCATION)): - frappe.throw("Most probably your password is too long.", exc=e) + frappe.throw(_("Most probably your password is too long.", exc=e)) raise e @@ -158,12 +158,21 @@ def create_auth_table(): def encrypt(txt, encryption_key=None): - cipher_suite = Fernet(encode(encryption_key or get_encryption_key())) + # Only use Fernet.generate_key().decode() to enter encyption_key value + + try: + cipher_suite = Fernet(encode(encryption_key or get_encryption_key())) + except Exception: + # encryption_key is not in 32 url-safe base64-encoded format + frappe.throw(_('Encryption key is in invalid format!')) + cipher_text = cstr(cipher_suite.encrypt(encode(txt))) return cipher_text def decrypt(txt, encryption_key=None): + # Only use encryption_key value generated with Fernet.generate_key().decode() + try: cipher_suite = Fernet(encode(encryption_key or get_encryption_key())) plain_text = cstr(cipher_suite.decrypt(encode(txt))) From 8e3b358b9fbeb18cdbf04aeff1359e3bbaf694cb Mon Sep 17 00:00:00 2001 From: leela Date: Mon, 31 May 2021 22:15:57 +0530 Subject: [PATCH 234/868] refactor: email queue builder is added replaced queue.send function with Queue builder. Queue builder builds a queue from sendmail request and sends the mail if requested to send mail immediately. --- frappe/__init__.py | 10 +- .../email/doctype/email_queue/email_queue.py | 307 +++++++++++++++++- frappe/email/doctype/newsletter/newsletter.py | 1 - frappe/email/queue.py | 252 +------------- frappe/email/test_email_body.py | 21 +- frappe/tests/test_email.py | 13 +- frappe/utils/error.py | 2 +- 7 files changed, 327 insertions(+), 279 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 9b208f7c2d..880e5d48a4 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -528,16 +528,20 @@ def sendmail(recipients=[], sender="", subject="No Subject", message="No Message if not delayed: now = True - from frappe.email import queue - queue.send(recipients=recipients, sender=sender, + from frappe.email.doctype.email_queue.email_queue import QueueBuilder + builder = QueueBuilder(recipients=recipients, sender=sender, subject=subject, message=message, text_content=text_content, reference_doctype = doctype or reference_doctype, reference_name = name or reference_name, add_unsubscribe_link=add_unsubscribe_link, unsubscribe_method=unsubscribe_method, unsubscribe_params=unsubscribe_params, unsubscribe_message=unsubscribe_message, attachments=attachments, reply_to=reply_to, cc=cc, bcc=bcc, message_id=message_id, in_reply_to=in_reply_to, send_after=send_after, expose_recipients=expose_recipients, send_priority=send_priority, queue_separately=queue_separately, - communication=communication, now=now, read_receipt=read_receipt, is_notification=is_notification, + communication=communication, read_receipt=read_receipt, is_notification=is_notification, inline_images=inline_images, header=header, print_letterhead=print_letterhead, with_container=with_container) + # build email queue and send the email if send_now is True. + builder.process(send_now=now) + + whitelisted = [] guest_methods = [] xss_safe_methods = [] diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index 394fe50468..dad473b8aa 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -9,14 +9,18 @@ from rq.timeouts import JobTimeoutException import smtplib import quopri from email.parser import Parser +from email.policy import SMTPUTF8 +from html2text import html2text +from six.moves import html_parser as HTMLParser import frappe from frappe import _, safe_encode, task from frappe.model.document import Document -from frappe.email.queue import get_unsubcribed_url -from frappe.email.email_body import add_attachment -from frappe.utils import cint -from email.policy import SMTPUTF8 +from frappe.email.queue import get_unsubcribed_url, get_unsubscribe_message +from frappe.email.email_body import add_attachment, get_formatted_html, get_email +from frappe.utils import cint, split_emails, add_days, nowdate, cstr +from frappe.email.doctype.email_account.email_account import EmailAccount + MAX_RETRY_COUNT = 3 class EmailQueue(Document): @@ -41,6 +45,19 @@ class EmailQueue(Document): duplicate.set_recipients(recipients) return duplicate + @classmethod + def new(cls, doc_data, ignore_permissions=False): + data = doc_data.copy() + if not data.get('recipients'): + return + + recipients = data.pop('recipients') + doc = frappe.new_doc(cls.DOCTYPE) + doc.update(data) + doc.set_recipients(recipients) + doc.insert(ignore_permissions=ignore_permissions) + return doc + @classmethod def find(cls, name): return frappe.get_doc(cls.DOCTYPE, name) @@ -74,8 +91,6 @@ class EmailQueue(Document): return json.loads(self.attachments) if self.attachments else [] def get_email_account(self): - from frappe.email.doctype.email_account.email_account import EmailAccount - if self.email_account: return frappe.get_doc('Email Account', self.email_account) @@ -300,3 +315,283 @@ def send_now(name): def on_doctype_update(): """Add index in `tabCommunication` for `(reference_doctype, reference_name)`""" frappe.db.add_index('Email Queue', ('status', 'send_after', 'priority', 'creation'), 'index_bulk_flush') + +class QueueBuilder: + """Builds Email Queue from the given data + """ + def __init__(self, recipients=None, sender=None, subject=None, message=None, + text_content=None, reference_doctype=None, reference_name=None, + unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, + attachments=None, reply_to=None, cc=None, bcc=None, message_id=None, in_reply_to=None, + send_after=None, expose_recipients=None, send_priority=1, communication=None, + read_receipt=None, queue_separately=False, is_notification=False, + add_unsubscribe_link=1, inline_images=None, header=None, + print_letterhead=False, with_container=False): + """Add email to sending queue (Email Queue) + + :param recipients: List of recipients. + :param sender: Email sender. + :param subject: Email subject. + :param message: Email message. + :param text_content: Text version of email message. + :param reference_doctype: Reference DocType of caller document. + :param reference_name: Reference name of caller document. + :param send_priority: Priority for Email Queue, default 1. + :param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`. + :param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email + :param attachments: Attachments to be sent. + :param reply_to: Reply to be captured here (default inbox) + :param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To. + :param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date. + :param communication: Communication link to be set in Email Queue record + :param queue_separately: Queue each email separately + :param is_notification: Marks email as notification so will not trigger notifications from system + :param add_unsubscribe_link: Send unsubscribe link in the footer of the Email, default 1. + :param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id + :param header: Append header in email (boolean) + :param with_container: Wraps email inside styled container + """ + + self._unsubscribe_method = unsubscribe_method + self._recipients = recipients + self._cc = cc + self._bcc = bcc + self._send_after = send_after + self._sender = sender + self._text_content = text_content + self._message = message + self._add_unsubscribe_link = add_unsubscribe_link + self._unsubscribe_message = unsubscribe_message + self._attachments = attachments + + self._unsubscribed_user_emails = None + self._email_account = None + + self.unsubscribe_params = unsubscribe_params + self.subject = subject + self.reference_doctype = reference_doctype + self.reference_name = reference_name + self.expose_recipients = expose_recipients + self.with_container = with_container + self.header = header + self.reply_to = reply_to + self.message_id = message_id + self.in_reply_to = in_reply_to + self.send_priority = send_priority + self.communication = communication + self.read_receipt = read_receipt + self.queue_separately = queue_separately + self.is_notification = is_notification + self.inline_images = inline_images + self.print_letterhead = print_letterhead + + @property + def unsubscribe_method(self): + return self._unsubscribe_method or '/api/method/frappe.email.queue.unsubscribe' + + def _get_emails_list(self, emails=None): + emails = split_emails(emails) if isinstance(emails, str) else (emails or []) + return [each for each in set(emails) if each] + + @property + def recipients(self): + return self._get_emails_list(self._recipients) + + @property + def cc(self): + return self._get_emails_list(self._cc) + + @property + def bcc(self): + return self._get_emails_list(self._bcc) + + @property + def send_after(self): + if isinstance(self._send_after, int): + return add_days(nowdate(), self._send_after) + return self._send_after + + @property + def sender(self): + if not self._sender or self._sender == "Administrator": + email_account = self.get_outgoing_email_account() + return email_account.default_sender + return self._sender + + def email_text_content(self): + unsubscribe_msg = self.unsubscribe_message() + unsubscribe_text_message = (unsubscribe_msg and unsubscribe_msg.text) or '' + + if self._text_content: + return self._text_content + unsubscribe_text_message + + try: + text_content = html2text(self._message) + except HTMLParser.HTMLParseError: + text_content = "See html attachment" + return text_content + unsubscribe_text_message + + def email_html_content(self): + email_account = self.get_outgoing_email_account() + return get_formatted_html(self.subject, self._message, header=self.header, + email_account=email_account, unsubscribe_link=self.unsubscribe_message(), + with_container=self.with_container) + + def should_include_unsubscribe_link(self): + return (self._add_unsubscribe_link == 1 + and self.reference_doctype + and (self._unsubscribe_message or self.reference_doctype=="Newsletter")) + + def unsubscribe_message(self): + if self.should_include_unsubscribe_link(): + return get_unsubscribe_message(self._unsubscribe_message, self.expose_recipients) + + def get_outgoing_email_account(self): + if self._email_account: + return self._email_account + + self._email_account = EmailAccount.find_outgoing( + match_by_doctype=self.reference_doctype, match_by_email=self._sender, _raise_error=True) + return self._email_account + + def get_unsubscribed_user_emails(self): + if self._unsubscribed_user_emails is not None: + return self._unsubscribed_user_emails + + all_ids = tuple(set(self.recipients + self.cc)) + + unsubscribed = frappe.db.sql_list(''' + SELECT + distinct email + from + `tabEmail Unsubscribe` + where + email in %(all_ids)s + and ( + ( + reference_doctype = %(reference_doctype)s + and reference_name = %(reference_name)s + ) + or global_unsubscribe = 1 + ) + ''', { + 'all_ids': all_ids, + 'reference_doctype': self.reference_doctype, + 'reference_name': self.reference_name, + }) + + self._unsubscribed_user_emails = unsubscribed or [] + return self._unsubscribed_user_emails + + def final_recipients(self): + unsubscribed_emails = self.get_unsubscribed_user_emails() + return [mail_id for mail_id in self.recipients if mail_id not in unsubscribed_emails] + + def final_cc(self): + unsubscribed_emails = self.get_unsubscribed_user_emails() + return [mail_id for mail_id in self.cc if mail_id not in unsubscribed_emails] + + def get_attachments(self): + attachments = [] + if self._attachments: + # store attachments with fid or print format details, to be attached on-demand later + for att in self._attachments: + if att.get('fid'): + attachments.append(att) + elif att.get("print_format_attachment") == 1: + if not att.get('lang', None): + att['lang'] = frappe.local.lang + att['print_letterhead'] = self.print_letterhead + attachments.append(att) + return attachments + + def prepare_email_content(self): + mail = get_email(recipients=self.final_recipients(), + sender=self.sender, + subject=self.subject, + formatted=self.email_html_content(), + text_content=self.email_text_content(), + attachments=self._attachments, + reply_to=self.reply_to, + cc=self.final_cc(), + bcc=self.bcc, + email_account=self.get_outgoing_email_account(), + expose_recipients=self.expose_recipients, + inline_images=self.inline_images, + header=self.header) + + mail.set_message_id(self.message_id, self.is_notification) + if self.read_receipt: + mail.msg_root["Disposition-Notification-To"] = self.sender + if self.in_reply_to: + mail.set_in_reply_to(self.in_reply_to) + return mail + + def process(self, send_now=False): + """Build and return the email queues those are created. + + Sends email incase if it is requested to send now. + """ + final_recipients = self.final_recipients() + queue_separately = (final_recipients and self.queue_separately) or len(final_recipients) > 20 + if not (final_recipients + self.final_cc()): + return [] + + email_queues = [] + queue_data = self.as_dict(include_recipients=False) + if not queue_data: + return [] + + if not queue_separately: + recipients = list(set(final_recipients + self.final_cc() + self.bcc)) + q = EmailQueue.new({**queue_data, **{'recipients': recipients}}, ignore_permissions=True) + email_queues.append(q) + else: + for r in final_recipients: + recipients = [r] if email_queues else list(set([r] + self.final_cc() + self.bcc)) + q = EmailQueue.new({**queue_data, **{'recipients': recipients}}, ignore_permissions=True) + email_queues.append(q) + + if send_now: + for doc in email_queues: + doc.send() + return email_queues + + def as_dict(self, include_recipients=True): + email_account = self.get_outgoing_email_account() + email_account_name = email_account and email_account.is_exists_in_db() and email_account.name + + mail = self.prepare_email_content() + try: + mail_to_string = cstr(mail.as_string()) + except frappe.InvalidEmailAddressError: + # bad Email Address - don't add to queue + frappe.log_error('Invalid Email ID Sender: {0}, Recipients: {1}, \nTraceback: {2} ' + .format(self.sender, ', '.join(self.final_recipients()), traceback.format_exc()), + 'Email Not Sent' + ) + return + + d = { + 'priority': self.send_priority, + 'attachments': json.dumps(self.get_attachments()), + 'message_id': mail.msg_root["Message-Id"].strip(" <>"), + 'message': mail_to_string, + 'sender': self.sender, + 'reference_doctype': self.reference_doctype, + 'reference_name': self.reference_name, + 'add_unsubscribe_link': self._add_unsubscribe_link, + 'unsubscribe_method': self.unsubscribe_method, + 'unsubscribe_params': self.unsubscribe_params, + 'expose_recipients': self.expose_recipients, + 'communication': self.communication, + 'send_after': self.send_after, + 'show_as_cc': ",".join(self.final_cc()), + 'show_as_bcc': ','.join(self.bcc), + 'email_account': email_account_name or None + } + + if include_recipients: + d['recipients'] = self.final_recipients() + + return d diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 6412338e96..469390322c 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -8,7 +8,6 @@ import frappe.utils from frappe import throw, _ from frappe.website.website_generator import WebsiteGenerator from frappe.utils.verified_command import get_signed_params, verify_request -from frappe.email.queue import send from frappe.email.doctype.email_group.email_group import add_subscribers from frappe.utils import parse_addr, now_datetime, markdown, validate_email_address diff --git a/frappe/email/queue.py b/frappe/email/queue.py index 52c91baf1c..451d1c970e 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -3,257 +3,9 @@ from __future__ import unicode_literals import frappe -import sys -from six.moves import html_parser as HTMLParser -import smtplib, quopri, json -from frappe import msgprint, _, safe_decode, safe_encode, enqueue -from frappe.email.smtp import SMTPServer -from frappe.email.doctype.email_account.email_account import EmailAccount -from frappe.email.email_body import get_email, get_formatted_html, add_attachment +from frappe import msgprint, _ from frappe.utils.verified_command import get_signed_params, verify_request -from html2text import html2text -from frappe.utils import get_url, nowdate, now_datetime, add_days, split_emails, cstr, cint -from rq.timeouts import JobTimeoutException -from six import text_type, string_types, PY3 -from email.parser import Parser - - -class EmailLimitCrossedError(frappe.ValidationError): pass - -def send(recipients=None, sender=None, subject=None, message=None, text_content=None, reference_doctype=None, - reference_name=None, unsubscribe_method=None, unsubscribe_params=None, unsubscribe_message=None, - attachments=None, reply_to=None, cc=None, bcc=None, message_id=None, in_reply_to=None, send_after=None, - expose_recipients=None, send_priority=1, communication=None, now=False, read_receipt=None, - queue_separately=False, is_notification=False, add_unsubscribe_link=1, inline_images=None, - header=None, print_letterhead=False, with_container=False): - """Add email to sending queue (Email Queue) - - :param recipients: List of recipients. - :param sender: Email sender. - :param subject: Email subject. - :param message: Email message. - :param text_content: Text version of email message. - :param reference_doctype: Reference DocType of caller document. - :param reference_name: Reference name of caller document. - :param send_priority: Priority for Email Queue, default 1. - :param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`. - :param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email - :param attachments: Attachments to be sent. - :param reply_to: Reply to be captured here (default inbox) - :param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To. - :param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date. - :param communication: Communication link to be set in Email Queue record - :param now: Send immediately (don't send in the background) - :param queue_separately: Queue each email separately - :param is_notification: Marks email as notification so will not trigger notifications from system - :param add_unsubscribe_link: Send unsubscribe link in the footer of the Email, default 1. - :param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id - :param header: Append header in email (boolean) - :param with_container: Wraps email inside styled container - """ - if not unsubscribe_method: - unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe" - - if not recipients and not cc: - return - - if not cc: - cc = [] - if not bcc: - bcc = [] - - if isinstance(recipients, string_types): - recipients = split_emails(recipients) - - if isinstance(cc, string_types): - cc = split_emails(cc) - - if isinstance(bcc, string_types): - bcc = split_emails(bcc) - - if isinstance(send_after, int): - send_after = add_days(nowdate(), send_after) - - email_account = EmailAccount.find_outgoing( - match_by_doctype=reference_doctype, match_by_email=sender, _raise_error=True) - - if not sender or sender == "Administrator": - sender = email_account.default_sender - - if not text_content: - try: - text_content = html2text(message) - except HTMLParser.HTMLParseError: - text_content = "See html attachment" - - recipients = list(set(recipients)) - cc = list(set(cc)) - - all_ids = tuple(recipients + cc) - - unsubscribed = frappe.db.sql_list(''' - SELECT - distinct email - from - `tabEmail Unsubscribe` - where - email in %(all_ids)s - and ( - ( - reference_doctype = %(reference_doctype)s - and reference_name = %(reference_name)s - ) - or global_unsubscribe = 1 - ) - ''', { - 'all_ids': all_ids, - 'reference_doctype': reference_doctype, - 'reference_name': reference_name, - }) - - recipients = [r for r in recipients if r and r not in unsubscribed] - - if cc: - cc = [r for r in cc if r and r not in unsubscribed] - - if not recipients and not cc: - # Recipients may have been unsubscribed, exit quietly - return - - email_text_context = text_content - - should_append_unsubscribe = (add_unsubscribe_link - and reference_doctype - and (unsubscribe_message or reference_doctype=="Newsletter") - and add_unsubscribe_link==1) - - unsubscribe_link = None - if should_append_unsubscribe: - unsubscribe_link = get_unsubscribe_message(unsubscribe_message, expose_recipients) - email_text_context += unsubscribe_link.text - - email_content = get_formatted_html(subject, message, - email_account=email_account, header=header, - unsubscribe_link=unsubscribe_link, with_container=with_container) - - # add to queue - add(recipients, sender, subject, - formatted=email_content, - text_content=email_text_context, - reference_doctype=reference_doctype, - reference_name=reference_name, - attachments=attachments, - reply_to=reply_to, - cc=cc, - bcc=bcc, - message_id=message_id, - in_reply_to=in_reply_to, - send_after=send_after, - send_priority=send_priority, - email_account=email_account, - communication=communication, - add_unsubscribe_link=add_unsubscribe_link, - unsubscribe_method=unsubscribe_method, - unsubscribe_params=unsubscribe_params, - expose_recipients=expose_recipients, - read_receipt=read_receipt, - queue_separately=queue_separately, - is_notification = is_notification, - inline_images = inline_images, - header=header, - now=now, - print_letterhead=print_letterhead) - - -def add(recipients, sender, subject, **kwargs): - """Add to Email Queue""" - if kwargs.get('queue_separately') or len(recipients) > 20: - email_queue = None - for r in recipients: - if not email_queue: - email_queue = get_email_queue([r], sender, subject, **kwargs) - if kwargs.get('now'): - email_queue.send() - else: - duplicate = email_queue.get_duplicate([r]) - duplicate.insert(ignore_permissions=True) - - if kwargs.get('now'): - duplicate.send() - - frappe.db.commit() - else: - email_queue = get_email_queue(recipients, sender, subject, **kwargs) - if kwargs.get('now'): - email_queue.send() - -def get_email_queue(recipients, sender, subject, **kwargs): - '''Make Email Queue object''' - e = frappe.new_doc('Email Queue') - e.priority = kwargs.get('send_priority') - attachments = kwargs.get('attachments') - if attachments: - # store attachments with fid or print format details, to be attached on-demand later - _attachments = [] - for att in attachments: - if att.get('fid'): - _attachments.append(att) - elif att.get("print_format_attachment") == 1: - if not att.get('lang', None): - att['lang'] = frappe.local.lang - att['print_letterhead'] = kwargs.get('print_letterhead') - _attachments.append(att) - e.attachments = json.dumps(_attachments) - - try: - mail = get_email(recipients, - sender=sender, - subject=subject, - formatted=kwargs.get('formatted'), - text_content=kwargs.get('text_content'), - attachments=kwargs.get('attachments'), - reply_to=kwargs.get('reply_to'), - cc=kwargs.get('cc'), - bcc=kwargs.get('bcc'), - email_account=kwargs.get('email_account'), - expose_recipients=kwargs.get('expose_recipients'), - inline_images=kwargs.get('inline_images'), - header=kwargs.get('header')) - - mail.set_message_id(kwargs.get('message_id'),kwargs.get('is_notification')) - if kwargs.get('read_receipt'): - mail.msg_root["Disposition-Notification-To"] = sender - if kwargs.get('in_reply_to'): - mail.set_in_reply_to(kwargs.get('in_reply_to')) - - e.message_id = mail.msg_root["Message-Id"].strip(" <>") - e.message = cstr(mail.as_string()) - e.sender = mail.sender - - except frappe.InvalidEmailAddressError: - # bad Email Address - don't add to queue - import traceback - frappe.log_error('Invalid Email ID Sender: {0}, Recipients: {1}, \nTraceback: {2} '.format(mail.sender, - ', '.join(mail.recipients), traceback.format_exc()), 'Email Not Sent') - - recipients = list(set(recipients + kwargs.get('cc', []) + kwargs.get('bcc', []))) - email_account = kwargs.get('email_account') - email_account_name = email_account and email_account.is_exists_in_db() and email_account.name - - e.set_recipients(recipients) - e.reference_doctype = kwargs.get('reference_doctype') - e.reference_name = kwargs.get('reference_name') - e.add_unsubscribe_link = kwargs.get("add_unsubscribe_link") - e.unsubscribe_method = kwargs.get('unsubscribe_method') - e.unsubscribe_params = kwargs.get('unsubscribe_params') - e.expose_recipients = kwargs.get('expose_recipients') - e.communication = kwargs.get('communication') - e.send_after = kwargs.get('send_after') - e.show_as_cc = ",".join(kwargs.get('cc', [])) - e.show_as_bcc = ",".join(kwargs.get('bcc', [])) - e.email_account = email_account_name or None - e.insert(ignore_permissions=True) - return e +from frappe.utils import get_url, now_datetime, cint def get_emails_sent_this_month(): return frappe.db.sql(""" diff --git a/frappe/email/test_email_body.py b/frappe/email/test_email_body.py index 33668cddba..5b37102a17 100644 --- a/frappe/email/test_email_body.py +++ b/frappe/email/test_email_body.py @@ -7,8 +7,7 @@ from frappe import safe_decode from frappe.email.receive import Email from frappe.email.email_body import (replace_filename_with_cid, get_email, inline_style_in_html, get_header) -from frappe.email.queue import get_email_queue -from frappe.email.doctype.email_queue.email_queue import SendMailContext +from frappe.email.doctype.email_queue.email_queue import SendMailContext, QueueBuilder from six import PY3 class TestEmailBody(unittest.TestCase): @@ -50,27 +49,25 @@ This is the text version of this email uni_chr1 = unichr(40960) uni_chr2 = unichr(1972) - email = get_email_queue( + queue_doc = QueueBuilder( recipients=['test@example.com'], sender='me@example.com', subject='Test Subject', - content='

    ' + uni_chr1 + 'abcd' + uni_chr2 + '

    ', - formatted='

    ' + uni_chr1 + 'abcd' + uni_chr2 + '

    ', - text_content='whatever') - mail_ctx = SendMailContext(queue_doc = email) + message='

    ' + uni_chr1 + 'abcd' + uni_chr2 + '

    ', + text_content='whatever').process()[0] + mail_ctx = SendMailContext(queue_doc = queue_doc) result = mail_ctx.build_message(recipient_email = 'test@test.com') self.assertTrue(b"

    =EA=80=80abcd=DE=B4

    " in result) def test_prepare_message_returns_cr_lf(self): - email = get_email_queue( + queue_doc = QueueBuilder( recipients=['test@example.com'], sender='me@example.com', subject='Test Subject', - content='

    \n this is a test of newlines\n' + '

    ', - formatted='

    \n this is a test of newlines\n' + '

    ', - text_content='whatever') + message='

    \n this is a test of newlines\n' + '

    ', + text_content='whatever').process()[0] - mail_ctx = SendMailContext(queue_doc = email) + mail_ctx = SendMailContext(queue_doc = queue_doc) result = safe_decode(mail_ctx.build_message(recipient_email='test@test.com')) if PY3: diff --git a/frappe/tests/test_email.py b/frappe/tests/test_email.py index 74962dd84c..58ffe7531d 100644 --- a/frappe/tests/test_email.py +++ b/frappe/tests/test_email.py @@ -143,7 +143,8 @@ class TestEmail(unittest.TestCase): self.assertEqual(len(queue_recipients), 2) def test_unsubscribe(self): - from frappe.email.queue import unsubscribe, send + from frappe.email.queue import unsubscribe + from frappe.email.doctype.email_queue.email_queue import QueueBuilder unsubscribe(doctype="User", name="Administrator", email="test@example.com") self.assertTrue(frappe.db.get_value("Email Unsubscribe", @@ -152,11 +153,11 @@ class TestEmail(unittest.TestCase): before = frappe.db.sql("""select count(name) from `tabEmail Queue` where status='Not Sent'""")[0][0] - send(recipients=['test@example.com', 'test1@example.com'], - sender="admin@example.com", - reference_doctype='User', reference_name="Administrator", - subject='Testing Email Queue', message='This is mail is queued!', unsubscribe_message="Unsubscribe") - + builder = QueueBuilder(recipients=['test@example.com', 'test1@example.com'], + sender="admin@example.com", + reference_doctype='User', reference_name="Administrator", + subject='Testing Email Queue', message='This is mail is queued!', unsubscribe_message="Unsubscribe") + builder.process() # this is sent async (?) email_queue = frappe.db.sql("""select name from `tabEmail Queue` where status='Not Sent'""", diff --git a/frappe/utils/error.py b/frappe/utils/error.py index 2d8d6491a5..68577e47e5 100644 --- a/frappe/utils/error.py +++ b/frappe/utils/error.py @@ -215,7 +215,7 @@ def raise_error_on_no_output(error_message, error_type=None, keep_quiet=None): >>> @raise_error_on_no_output("Ingradients missing") ... def get_indradients(_raise_error=1): return ... - >>> get_indradients() + >>> get_ingradients() `Exception Name`: Ingradients missing """ def decorator_raise_error_on_no_output(func): From 43972e28a73b9d08cd073065fc94d0175cf872ed Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 1 Jun 2021 22:17:24 +0530 Subject: [PATCH 235/868] feat: group by tags in report view --- frappe/public/js/frappe/form/formatters.js | 11 ++++++++--- frappe/public/js/frappe/ui/group_by/group_by.js | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/form/formatters.js b/frappe/public/js/frappe/form/formatters.js index 89c34ed80c..83fe9ffa9c 100644 --- a/frappe/public/js/frappe/form/formatters.js +++ b/frappe/public/js/frappe/form/formatters.js @@ -221,9 +221,13 @@ frappe.form.formatters = { Tag: function(value) { var html = ""; $.each((value || "").split(","), function(i, v) { - if(v) html+= ''+v +''; + if (v) html += ` + + ${v} + `; }); return html; }, @@ -310,6 +314,7 @@ frappe.form.get_formatter = function(fieldtype) { frappe.format = function(value, df, options, doc) { if(!df) df = {"fieldtype":"Data"}; + if (df.fieldname == '_user_tags') df.fieldtype = 'Tag' var fieldtype = df.fieldtype || "Data"; // format Dynamic Link as a Link diff --git a/frappe/public/js/frappe/ui/group_by/group_by.js b/frappe/public/js/frappe/ui/group_by/group_by.js index 3ebf9c9d3d..a113396643 100644 --- a/frappe/public/js/frappe/ui/group_by/group_by.js +++ b/frappe/public/js/frappe/ui/group_by/group_by.js @@ -381,10 +381,11 @@ frappe.ui.GroupBy = class { this.group_by_fields = {}; this.all_fields = {}; - let fields = this.report_view.meta.fields.filter((f) => + const fields = this.report_view.meta.fields.filter((f) => ['Select', 'Link', 'Data', 'Int', 'Check'].includes(f.fieldtype) ); - this.group_by_fields[this.doctype] = fields; + const tag_field = {fieldname:'_user_tags', fieldtype:'Data', label:__('Tags')}; + this.group_by_fields[this.doctype] = fields.concat(tag_field); this.all_fields[this.doctype] = this.report_view.meta.fields; const standard_fields_filter = (df) => From 0e3d8626c49d464aaa4e4a541c273678887352d8 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 2 Jun 2021 12:15:58 +0530 Subject: [PATCH 236/868] fix: Remove ellipsis to avoid cliping of useful content --- frappe/public/js/frappe/form/controls/link.js | 2 +- frappe/public/scss/common/awesomeplete.scss | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index af92f3b7a9..83f3f8dd70 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -141,7 +141,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat return $('
  • ') .data('item.autocomplete', d) .prop('aria-selected', 'false') - .html(`

    ${html}

    `) + .html(`

    ${html}

    `) .get(0); }, sort: function() { diff --git a/frappe/public/scss/common/awesomeplete.scss b/frappe/public/scss/common/awesomeplete.scss index 096da1e2fd..b9e8035d68 100644 --- a/frappe/public/scss/common/awesomeplete.scss +++ b/frappe/public/scss/common/awesomeplete.scss @@ -31,6 +31,7 @@ margin: 0; padding: var(--padding-xs); z-index: 1; + min-width: 250px; &> li { cursor: pointer; @@ -44,6 +45,8 @@ } p { margin-bottom: 0; + overflow-y: clip; + text-overflow: ellipsis; } } From e489c1b594697931972cf819c44a41b25311a75c Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 2 Jun 2021 13:05:16 +0530 Subject: [PATCH 237/868] fix: Added select permission for Module Def doctype to All role --- frappe/core/doctype/module_def/module_def.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/module_def/module_def.json b/frappe/core/doctype/module_def/module_def.json index 7a8bfd76a7..4de046bbb6 100644 --- a/frappe/core/doctype/module_def/module_def.json +++ b/frappe/core/doctype/module_def/module_def.json @@ -55,7 +55,7 @@ "link_fieldname": "module" } ], - "modified": "2020-08-06 12:39:30.740379", + "modified": "2021-06-02 13:04:53.118716", "modified_by": "Administrator", "module": "Core", "name": "Module Def", @@ -69,6 +69,7 @@ "read": 1, "report": 1, "role": "Administrator", + "select": 1, "share": 1, "write": 1 }, @@ -78,7 +79,14 @@ "read": 1, "report": 1, "role": "System Manager", + "select": 1, "write": 1 + }, + { + "read": 1, + "report": 1, + "role": "All", + "select": 1 } ], "show_name_in_global_search": 1, From 915f778538ee2bc711bfa9c47cdeb874fa0af235 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 2 Jun 2021 15:15:54 +0530 Subject: [PATCH 238/868] fix: minor fix --- frappe/desk/desktop.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index f4d4796aef..9df46cc7df 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -555,10 +555,13 @@ def save_new_widget(page, new_widgets): "onboarding": original_page.onboarding, "developer_mode_only": original_page.developer_mode_only, "category": original_page.category, - "charts": original_page.charts, - "shortcuts": original_page.shortcuts, - "links": original_page.links, }) + if page_doc.is_new(): + page_doc.update({ + "charts": original_page.charts, + "shortcuts": original_page.shortcuts, + "links": original_page.links, + }) widgets = _dict(loads(new_widgets)) From a457501422e06b22293ab2bfd19d8c2a8f509ace Mon Sep 17 00:00:00 2001 From: walstanb Date: Wed, 2 Jun 2021 16:20:51 +0530 Subject: [PATCH 239/868] fix: removed duplicate fields from Customize Form --- .../doctype/customize_form/customize_form.json | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index 1807678673..b9dde88126 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -288,16 +288,6 @@ "fieldname": "autoname", "fieldtype": "Data", "label": "Auto Name" - }, - { - "fieldname": "default_email_template", - "fieldtype": "Link", - "label": "Default Email Template", - "options": "Email Template" - }, - { - "fieldname": "column_break_26", - "fieldtype": "Column Break" } ], "hide_toolbar": 1, @@ -306,7 +296,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-04-29 21:21:06.476372", + "modified": "2021-06-02 06:49:16.782806", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", From c36f0631ee1e1bece691039b904c7ece9dc452c9 Mon Sep 17 00:00:00 2001 From: shariquerik Date: Wed, 2 Jun 2021 16:52:00 +0530 Subject: [PATCH 240/868] fix: User based Wiki Pages fix --- frappe/desk/desktop.py | 22 ++++++++++------- frappe/desk/doctype/workspace/workspace.json | 25 +++++++++++++------- frappe/public/js/frappe/views/wiki.js | 3 ++- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index 9df46cc7df..8ea5738caf 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe import json +from typing import Dict, List from json import loads, dumps from frappe import _, DoesNotExistError, ValidationError, _dict from frappe.boot import get_allowed_pages, get_allowed_reports @@ -30,7 +31,9 @@ def handle_not_exist(fn): class Workspace: - def __init__(self, page_name, minimal=False): + def __init__(self, page_name, minimal=False, wiki=False) -> List[Dict]: + if isinstance(wiki, str): + wiki = json.loads(wiki) self.page_name = page_name self.extended_links = [] self.extended_charts = [] @@ -39,7 +42,7 @@ class Workspace: self.user = frappe.get_user() self.allowed_modules = self.get_cached('user_allowed_modules', self.get_allowed_modules) - self.doc = self.get_page_for_user() + self.doc = self.get_page_for_user(wiki) if self.doc.module and self.doc.module not in self.allowed_modules: raise frappe.PermissionError @@ -104,11 +107,12 @@ class Workspace: return self.user.allow_modules - def get_page_for_user(self): + def get_page_for_user(self, wiki=False): filters = { 'extends': self.page_name, 'for_user': frappe.session.user } + filters['for_wiki'] = wiki user_pages = frappe.get_all("Workspace", filters=filters, limit=1) if user_pages: return frappe.get_cached_doc("Workspace", user_pages[0]) @@ -350,7 +354,7 @@ class Workspace: @frappe.whitelist() @frappe.read_only() -def get_desktop_page(page): +def get_desktop_page(page, wiki=False): """Applies permissions, customizations and returns the configruration for a page on desk. @@ -361,7 +365,7 @@ def get_desktop_page(page): dict: dictionary of cards, charts and shortcuts to be displayed on website """ try: - wspace = Workspace(page) + wspace = Workspace(page, wiki=wiki) wspace.build_workspace() return { 'charts': wspace.charts, @@ -461,7 +465,7 @@ def get_custom_report_list(module): return out -def get_custom_workspace_for_user(page): +def get_custom_workspace_for_user(page, wiki=False): """Get custom page from workspace if exists or create one Args: @@ -474,12 +478,14 @@ def get_custom_workspace_for_user(page): 'extends': page, 'for_user': frappe.session.user } + filters['for_wiki'] = wiki pages = frappe.get_list("Workspace", filters=filters) if pages: return frappe.get_doc("Workspace", pages[0]) doc = frappe.new_doc("Workspace") doc.extends = page doc.for_user = frappe.session.user + doc.for_wiki = wiki return doc @@ -543,7 +549,7 @@ def save_customization(page, config): def save_new_widget(page, new_widgets): original_page = frappe.get_doc("Workspace", page) - page_doc = get_custom_workspace_for_user(page) + page_doc = get_custom_workspace_for_user(page, True) # Update field values page_doc.update({ @@ -576,7 +582,7 @@ def save_new_widget(page, new_widgets): clean_up(page_doc, page) # Set label - page_doc.label = page + '-' + frappe.session.user + page_doc.label = page + '-Wiki-' + frappe.session.user try: page_doc.save(ignore_permissions=True) diff --git a/frappe/desk/doctype/workspace/workspace.json b/frappe/desk/doctype/workspace/workspace.json index 386267b699..2de8eeef62 100644 --- a/frappe/desk/doctype/workspace/workspace.json +++ b/frappe/desk/doctype/workspace/workspace.json @@ -24,6 +24,7 @@ "pin_to_top", "pin_to_bottom", "hide_custom", + "for_wiki", "section_break_2", "charts_label", "charts", @@ -209,16 +210,22 @@ "options": "Workspace Link" }, { - "default": "0", - "depends_on": "extends_another_page", - "description": "Sets the current page as default for all users", - "fieldname": "is_default", - "fieldtype": "Check", - "label": "Is Default" - } + "default": "0", + "depends_on": "extends_another_page", + "description": "Sets the current page as default for all users", + "fieldname": "is_default", + "fieldtype": "Check", + "label": "Is Default" + }, + { + "default": "0", + "fieldname": "for_wiki", + "fieldtype": "Check", + "label": "For Wiki" + } ], "links": [], - "modified": "2021-01-21 12:09:36.156614", + "modified": "2021-06-02 15:35:08.963507", "modified_by": "Administrator", "module": "Desk", "name": "Workspace", @@ -248,4 +255,4 @@ ], "sort_field": "modified", "sort_order": "DESC" -} +} \ No newline at end of file diff --git a/frappe/public/js/frappe/views/wiki.js b/frappe/public/js/frappe/views/wiki.js index 06964a9d38..9acf3b72c7 100644 --- a/frappe/public/js/frappe/views/wiki.js +++ b/frappe/public/js/frappe/views/wiki.js @@ -172,7 +172,8 @@ frappe.views.Wiki = class Wiki { get_data(page) { return frappe.xcall("frappe.desk.desktop.get_desktop_page", { - page: page + page: page, + wiki: true }).then(data => { this.page_data = data; if (!this.page_data) return; From 879ecaacabad73ea13f583e61d85f5a086a36f6c Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 3 Jun 2021 10:40:36 +0530 Subject: [PATCH 241/868] fix: Custom page renderer logic --- frappe/website/path_resolver.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/frappe/website/path_resolver.py b/frappe/website/path_resolver.py index 0519d82735..bedd9f19ae 100644 --- a/frappe/website/path_resolver.py +++ b/frappe/website/path_resolver.py @@ -1,4 +1,5 @@ import re +import click from werkzeug.routing import Rule @@ -35,7 +36,7 @@ class PathResolver(): return frappe.flags.redirect_location, RedirectPage(self.path) endpoint = resolve_path(self.path) - custom_renderers = frappe.get_hooks('page_renderer') + custom_renderers = self.get_custom_page_renderers() renderers = custom_renderers + [StaticPage, WebFormPage, TemplatePage, ListPage, DocumentPage, PrintPage, NotFoundPage] for renderer in renderers: @@ -49,6 +50,27 @@ class PathResolver(): _endpoint, renderer_instance = self.resolve() return not isinstance(renderer_instance, NotFoundPage) + @staticmethod + def get_custom_page_renderers(): + custom_renderers = [] + for renderer_path in frappe.get_hooks('page_renderer') or []: + try: + renderer = frappe.get_attr(renderer_path) + if not hasattr(renderer, 'can_render'): + click.echo(f'{renderer.__name__} does not have can_render method') + continue + if not hasattr(renderer, 'render'): + click.echo(f'{renderer.__name__} does not have render method') + continue + + custom_renderers.append(renderer) + + except Exception: + click.echo(f'Failed to load page renderer. Import path: {renderer_path}') + + return custom_renderers + + def resolve_redirect(path, query_string=None): ''' From 254496450163cc308db0c9a23224b041daceb07d Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 3 Jun 2021 10:41:22 +0530 Subject: [PATCH 242/868] test: Add test case to validate custom page renderer --- frappe/tests/test_website.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 69425cdc45..84bf3ef8f1 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -3,9 +3,10 @@ from __future__ import unicode_literals import unittest import frappe -from frappe.website.serve import get_response -from frappe.website.utils import get_home_page, clear_website_cache from frappe.utils import set_request +from frappe.website.serve import get_response, get_response_content +from frappe.website.utils import (build_response, clear_website_cache, get_home_page) + class TestWebsite(unittest.TestCase): def setUp(self): @@ -178,6 +179,25 @@ class TestWebsite(unittest.TestCase): delattr(frappe.hooks, 'website_redirects') frappe.cache().delete_key('app_hooks') + def test_custom_page_renderer(self): + import frappe.hooks + frappe.hooks.page_renderer = ['frappe.tests.test_website.CustomPageRenderer'] + frappe.cache().delete_key('app_hooks') + set_request(method='GET', path='/custom') + response = get_response() + self.assertEqual(response.status_code, 3984) + + set_request(method='GET', path='/new') + content = get_response_content() + self.assertIn("
    Custom Page Response
    ", content) + + set_request(method='GET', path='/random') + response = get_response() + self.assertEqual(response.status_code, 404) + + delattr(frappe.hooks, 'page_renderer') + frappe.cache().delete_key('app_hooks') + def set_home_page_hook(key, value): from frappe import hooks @@ -189,3 +209,15 @@ def set_home_page_hook(key, value): setattr(hooks, key, value) frappe.cache().delete_key('app_hooks') +class CustomPageRenderer(): + def __init__(self, path, status_code=None): + self.path = path + # custom status code + self.status_code = 3984 + + def can_render(self): + if self.path in ('new', 'custom'): + return True + + def render(self): + return build_response(self.path, """
    Custom Page Response
    """, self.status_code) From 468b8fbd996142193107ecfc8f93a975646911d3 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 3 Jun 2021 11:48:49 +0530 Subject: [PATCH 243/868] fix: Remove unnecessary import --- frappe/website/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/website/utils.py b/frappe/website/utils.py index df3cdefa1f..0f5f182ea2 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -7,7 +7,6 @@ import re from functools import wraps import yaml -from past.builtins import cmp from six import iteritems from werkzeug.wrappers import Response From 73f320ee3974fe7bec4decb8e34cce403b6ecf03 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 13:21:04 +0530 Subject: [PATCH 244/868] chore: Drop patches before added before v10 * This change will not allow direct upgrade from frappe versions older than v10 to v13 and newer * Removed patch records and execute commands that could've been guessed aren't needed by sleuthing and guessing. since 2017 had 3 major releases: v8, v9 and v10 unsure which execute lines are required so kept all that were last updated in that year --- frappe/patches.txt | 157 --------------------------------------------- 1 file changed, 157 deletions(-) diff --git a/frappe/patches.txt b/frappe/patches.txt index e70be0a37b..7605d8ea2b 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -1,11 +1,5 @@ frappe.patches.v12_0.remove_deprecated_fields_from_doctype #3 -execute:frappe.db.sql("""update `tabPatch Log` set patch=replace(patch, '.4_0.', '.v4_0.')""") #2014-05-12 -frappe.patches.v5_0.convert_to_barracuda_and_utf8mb4 execute:frappe.utils.global_search.setup_global_search_table() -frappe.patches.v8_0.update_global_search_table -frappe.patches.v7_0.update_auth -frappe.patches.v8_0.drop_in_dialog #2017-09-22 -frappe.patches.v7_2.remove_in_filter execute:frappe.reload_doc('core', 'doctype', 'doctype_action', force=True) #2019-09-23 execute:frappe.reload_doc('core', 'doctype', 'doctype_link', force=True) #2020-10-17 execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2017-09-22 @@ -14,7 +8,6 @@ frappe.patches.v11_0.drop_column_apply_user_permissions execute:frappe.reload_doc('core', 'doctype', 'custom_docperm') execute:frappe.reload_doc('core', 'doctype', 'docperm') #2018-05-29 execute:frappe.reload_doc('core', 'doctype', 'comment') -frappe.patches.v8_0.drop_is_custom_from_docperm execute:frappe.reload_doc('core', 'doctype', 'document_naming_rule', force=True) execute:frappe.reload_doc('core', 'doctype', 'module_def') #2020-08-28 execute:frappe.reload_doc('core', 'doctype', 'version') #2017-04-01 @@ -25,190 +18,40 @@ execute:frappe.reload_doc('core', 'doctype', 'communication') #2019-10-02 execute:frappe.reload_doc('core', 'doctype', 'server_script') frappe.patches.v11_0.replicate_old_user_permissions frappe.patches.v11_0.reload_and_rename_view_log #2019-01-03 -frappe.patches.v7_1.rename_scheduler_log_to_error_log -frappe.patches.v6_1.rename_file_data -frappe.patches.v7_0.re_route #2016-06-27 -frappe.patches.v8_0.update_records_in_global_search #11-05-2017 -frappe.patches.v8_0.update_published_in_global_search frappe.patches.v11_0.copy_fetch_data_from_options frappe.patches.v11_0.change_email_signature_fieldtype execute:frappe.reload_doc('core', 'doctype', 'activity_log') execute:frappe.reload_doc('core', 'doctype', 'deleted_document') execute:frappe.reload_doc('core', 'doctype', 'domain_settings') frappe.patches.v13_0.rename_custom_client_script -frappe.patches.v8_0.rename_page_role_to_has_role #2017-03-16 -frappe.patches.v7_2.setup_custom_perms #2017-01-19 -frappe.patches.v8_0.set_user_permission_for_page_and_report #2017-03-20 execute:frappe.reload_doc('core', 'doctype', 'role') #2017-05-23 execute:frappe.reload_doc('core', 'doctype', 'user') #2017-10-27 -execute:frappe.reload_doc('custom', 'doctype', 'custom_field') #2015-10-19 -execute:frappe.reload_doc('core', 'doctype', 'page') #2013-13-26 execute:frappe.reload_doc('core', 'doctype', 'report_column') execute:frappe.reload_doc('core', 'doctype', 'report_filter') execute:frappe.reload_doc('core', 'doctype', 'report') #2020-08-25 -execute:frappe.reload_doc('core', 'doctype', 'translation') #2016-03-03 -execute:frappe.reload_doc('email', 'doctype', 'email_alert') #2014-07-15 -execute:frappe.reload_doc('desk', 'doctype', 'todo') #2014-12-31-1 -execute:frappe.reload_doc('custom', 'doctype', 'property_setter') #2014-12-31-1 -execute:frappe.reload_doc('core', 'doctype', 'patch_log') #2016-10-31 -execute:frappe.reload_doctype("File") # 2015-10-19 execute:frappe.reload_doc('core', 'doctype', 'error_snapshot') -execute:frappe.clear_cache() -frappe.patches.v7_1.rename_scheduler_log_to_error_log -frappe.patches.v7_1.sync_language_doctype -frappe.patches.v7_0.rename_bulk_email_to_email_queue -frappe.patches.v7_1.rename_chinese_language_codes - -execute:frappe.db.sql("alter table `tabSessions` modify `user` varchar(255), engine=InnoDB") -execute:frappe.db.sql("delete from `tabDocField` where parent='0'") -frappe.patches.v4_0.change_varchar_length -frappe.patches.v6_4.reduce_varchar_length -frappe.patches.v5_2.change_checks_to_not_null -frappe.patches.v6_9.int_float_not_null #2015-11-25 -frappe.patches.v5_0.v4_to_v5 - -frappe.patches.v5_0.remove_shopping_cart_app -frappe.patches.v4_0.webnotes_to_frappe -execute:frappe.permissions.reset_perms("Module Def") -execute:import frappe.installer;frappe.installer.make_site_dirs() #2014-02-19 -frappe.patches.v4_0.rename_profile_to_user -frappe.patches.v4_0.deprecate_control_panel -frappe.patches.v4_0.remove_old_parent -frappe.patches.v4_0.rename_sitemap_to_route -frappe.patches.v4_0.website_sitemap_hierarchy -frappe.patches.v4_0.remove_index_sitemap -frappe.patches.v4_0.set_website_route_idx -frappe.patches.v4_0.add_delete_permission -frappe.patches.v4_0.set_todo_checked_as_closed -frappe.patches.v4_0.private_backups -frappe.patches.v4_0.set_module_in_report -frappe.patches.v4_0.update_datetime -frappe.patches.v4_0.file_manager_hooks execute:frappe.get_doc("User", "Guest").save() -frappe.patches.v4_0.update_custom_field_insert_after -frappe.patches.v4_0.deprecate_link_selects -frappe.patches.v4_0.set_user_gravatar -frappe.patches.v4_0.set_user_permissions -frappe.patches.v4_0.create_custom_field_for_owner_match -frappe.patches.v4_0.enable_scheduler_in_system_settings -execute:frappe.db.sql("update tabReport set apply_user_permissions=1") #2014-06-03 -frappe.patches.v4_0.replace_deprecated_timezones -execute:import frappe.website.render; frappe.website.render.clear_cache("login"); #2014-06-10 -frappe.patches.v4_0.fix_attach_field_file_url -execute:frappe.permissions.reset_perms("User") #2015-03-24 -execute:frappe.db.sql("""delete from `tabUserRole` where ifnull(parentfield, '')='' or ifnull(`role`, '')=''""") #2014-08-18 -frappe.patches.v4_0.remove_user_owner_custom_field -execute:frappe.delete_doc("DocType", "Website Template") -execute:frappe.db.sql("""update `tabProperty Setter` set property_type='Text' where property in ('options', 'default')""") #2014-06-20 -frappe.patches.v4_1.enable_outgoing_email_settings -execute:frappe.db.sql("""update `tabSingles` set `value`=`doctype` where `field`='name'""") #2014-07-04 -frappe.patches.v4_1.enable_print_as_pdf #2014-06-17 -execute:frappe.db.sql("""update `tabDocPerm` set email=1 where parent='User' and permlevel=0 and `role`='All' and `read`=1 and apply_user_permissions=1""") #2014-07-15 -execute:frappe.db.sql("""update `tabPrint Format` set print_format_type='Client' where ifnull(print_format_type, '')=''""") #2014-07-28 -frappe.patches.v4_1.file_manager_fix -frappe.patches.v4_2.print_with_letterhead execute:frappe.delete_doc("DocType", "Control Panel", force=1) -execute:frappe.reload_doc('website', 'doctype', 'web_form') #2014-09-04 -execute:frappe.reload_doc('website', 'doctype', 'web_form_field') #2014-09-04 -frappe.patches.v4_2.refactor_website_routing -frappe.patches.v4_2.set_assign_in_doc -frappe.patches.v4_3.remove_allow_on_submit_customization -frappe.patches.v5_0.rename_table_fieldnames -frappe.patches.v5_0.communication_parent -frappe.patches.v5_0.clear_website_group_and_notifications -frappe.patches.v5_0.update_shared -execute:frappe.reload_doc("core", "doctype", "docshare") #2015-07-21 -frappe.patches.v6_19.comment_feed_communication -frappe.patches.v6_16.star_to_like -frappe.patches.v5_0.bookmarks_to_stars -frappe.patches.v5_0.style_settings_to_website_theme -frappe.patches.v5_0.rename_ref_type_fieldnames -frappe.patches.v5_0.fix_email_alert -frappe.patches.v5_0.fix_null_date_datetime -frappe.patches.v5_0.force_sync_website execute:frappe.delete_doc("DocType", "Tag") execute:frappe.db.sql("delete from `tabProperty Setter` where `property` in ('idx', '_idx')") -frappe.patches.v5_0.move_scheduler_last_event_to_system_settings execute:frappe.db.sql("update tabUser set new_password='' where ifnull(new_password, '')!=''") -frappe.patches.v5_0.fix_text_editor_file_urls -frappe.patches.v5_0.modify_session -frappe.patches.v5_0.expire_old_scheduler_logs execute:frappe.permissions.reset_perms("DocType") execute:frappe.db.sql("delete from `tabProperty Setter` where `property` = 'idx'") -frappe.patches.v6_0.communication_status_and_permission -frappe.patches.v6_0.make_task_log_folder -frappe.patches.v6_0.document_type_rename -frappe.patches.v6_0.fix_ghana_currency -frappe.patches.v6_2.ignore_user_permissions_if_missing execute:frappe.db.sql("delete from tabSessions where user is null") -frappe.patches.v6_2.rename_backup_manager execute:frappe.delete_doc("DocType", "Backup Manager") -execute:frappe.db.sql("""update `tabCommunication` set parenttype=null, parent=null, parentfield=null""") #2015-10-22 execute:frappe.permissions.reset_perms("Web Page") -frappe.patches.v6_6.user_last_active -frappe.patches.v6_6.fix_file_url -frappe.patches.v6_11.rename_field_in_email_account -frappe.patches.v7_0.create_private_file_folder -frappe.patches.v6_15.remove_property_setter_for_previous_field #2015-12-29 -frappe.patches.v6_15.set_username execute:frappe.permissions.reset_perms("Error Snapshot") -frappe.patches.v6_16.feed_doc_owner -frappe.patches.v6_21.print_settings_repeat_header_footer -frappe.patches.v6_24.set_language_as_code -frappe.patches.v6_20x.update_insert_after -frappe.patches.v6_20x.set_allow_draft_for_print -frappe.patches.v6_20x.remove_roles_from_website_user -frappe.patches.v7_0.set_user_fullname -frappe.patches.v7_0.add_communication_in_doc -frappe.patches.v7_0.update_send_after_in_bulk_email -execute:frappe.db.sql('''delete from `tabSingles` where doctype="Email Settings"''') # 2016-06-13 execute:frappe.db.sql("delete from `tabWeb Page` where ifnull(template_path, '')!=''") -frappe.patches.v7_0.rename_newsletter_list_to_email_group -frappe.patches.v7_0.set_email_group -frappe.patches.v7_1.setup_integration_services #2016-10-27 -frappe.patches.v7_1.rename_chinese_language_codes execute:frappe.core.doctype.language.language.update_language_names() # 2017-04-12 execute:frappe.db.set_value("Print Settings", "Print Settings", "add_draft_heading", 1) -frappe.patches.v7_0.cleanup_list_settings execute:frappe.db.set_default('language', '') -frappe.patches.v7_1.refactor_integration_broker -frappe.patches.v7_1.set_backup_limit -frappe.patches.v7_2.set_doctype_engine -frappe.patches.v7_2.merge_knowledge_base -frappe.patches.v7_0.update_report_builder_json -frappe.patches.v7_2.set_in_standard_filter_property #1 -frappe.patches.v8_0.drop_unwanted_indexes execute:frappe.db.sql("update tabCommunication set communication_date = creation where time(communication_date) = 0") -frappe.patches.v7_2.fix_email_queue_recipient -frappe.patches.v7_2.update_feedback_request # 2017-02-27 execute:frappe.rename_doc('Country', 'Macedonia, Republic of', 'Macedonia', ignore_if_exists=True) execute:frappe.rename_doc('Country', 'Iran, Islamic Republic of', 'Iran', ignore_if_exists=True) execute:frappe.rename_doc('Country', 'Tanzania, United Republic of', 'Tanzania', ignore_if_exists=True) execute:frappe.rename_doc('Country', 'Syrian Arab Republic', 'Syria', ignore_if_exists=True) -frappe.patches.v8_0.rename_listsettings_to_usersettings -frappe.patches.v7_2.update_communications -frappe.patches.v8_0.deprecate_integration_broker -frappe.patches.v8_0.update_gender_and_salutation -frappe.patches.v8_0.setup_email_inbox #2017-03-29 -frappe.patches.v8_0.newsletter_childtable_migrate -frappe.patches.v8_0.set_doctype_values_in_custom_role -frappe.patches.v8_0.install_new_build_system_requirements -frappe.patches.v8_0.set_currency_field_precision # 2017-05-09 execute:frappe.reload_doc('desk', 'doctype', 'notification_log') -frappe.patches.v8_0.rename_print_to_printing -frappe.patches.v7_1.disabled_print_settings_for_custom_print_format execute:frappe.db.sql('update tabReport set module="Desk" where name="ToDo"') -frappe.patches.v8_1.enable_allow_error_traceback_in_system_settings -frappe.patches.v8_1.update_format_options_in_auto_email_report -frappe.patches.v8_1.delete_custom_docperm_if_doctype_not_exists -frappe.patches.v8_5.delete_email_group_member_with_invalid_emails -frappe.patches.v8_x.update_user_permission -frappe.patches.v8_5.patch_event_colors -frappe.patches.v8_10.delete_static_web_page_from_global_search -frappe.patches.v9_1.add_sms_sender_name_as_parameters -frappe.patches.v9_1.resave_domain_settings -frappe.patches.v9_1.revert_domain_settings -frappe.patches.v9_1.move_feed_to_activity_log execute:frappe.delete_doc('Page', 'data-import-tool', ignore_missing=True) frappe.patches.v10_0.reload_countries_and_currencies # 2021-02-03 frappe.patches.v10_0.refactor_social_login_keys From 0e811e0193e6773f73b41a6112f189a38888bbb0 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 13:24:29 +0530 Subject: [PATCH 245/868] chore: Drop unlinked patches (pre v10) --- frappe/patches/v4_0/__init__.py | 0 frappe/patches/v4_0/add_delete_permission.py | 13 - frappe/patches/v4_0/change_varchar_length.py | 25 -- .../create_custom_field_for_owner_match.py | 39 --- .../patches/v4_0/deprecate_control_panel.py | 9 - frappe/patches/v4_0/deprecate_link_selects.py | 12 - .../enable_scheduler_in_system_settings.py | 13 - frappe/patches/v4_0/file_manager_hooks.py | 33 -- .../patches/v4_0/fix_attach_field_file_url.py | 12 - frappe/patches/v4_0/private_backups.py | 10 - frappe/patches/v4_0/remove_index_sitemap.py | 5 - frappe/patches/v4_0/remove_old_parent.py | 9 - .../v4_0/remove_user_owner_custom_field.py | 9 - frappe/patches/v4_0/rename_profile_to_user.py | 15 - .../patches/v4_0/rename_sitemap_to_route.py | 25 -- .../v4_0/replace_deprecated_timezones.py | 20 -- frappe/patches/v4_0/set_module_in_report.py | 9 - .../v4_0/set_todo_checked_as_closed.py | 9 - frappe/patches/v4_0/set_user_gravatar.py | 10 - frappe/patches/v4_0/set_user_permissions.py | 23 -- frappe/patches/v4_0/set_website_route_idx.py | 25 -- .../v4_0/update_custom_field_insert_after.py | 17 - frappe/patches/v4_0/update_datetime.py | 12 - frappe/patches/v4_0/webnotes_to_frappe.py | 12 - .../patches/v4_0/website_sitemap_hierarchy.py | 19 -- frappe/patches/v4_1/__init__.py | 0 .../v4_1/enable_outgoing_email_settings.py | 9 - frappe/patches/v4_1/enable_print_as_pdf.py | 25 -- frappe/patches/v4_1/file_manager_fix.py | 97 ------ frappe/patches/v4_2/__init__.py | 0 frappe/patches/v4_2/print_with_letterhead.py | 10 - .../patches/v4_2/refactor_website_routing.py | 8 - frappe/patches/v4_2/set_assign_in_doc.py | 11 - frappe/patches/v4_3/__init__.py | 0 .../remove_allow_on_submit_customization.py | 10 - frappe/patches/v5_0/__init__.py | 0 frappe/patches/v5_0/bookmarks_to_stars.py | 32 -- .../clear_website_group_and_notifications.py | 9 - frappe/patches/v5_0/communication_parent.py | 6 - .../v5_0/convert_to_barracuda_and_utf8mb4.py | 16 - .../patches/v5_0/expire_old_scheduler_logs.py | 8 - frappe/patches/v5_0/fix_email_alert.py | 14 - frappe/patches/v5_0/fix_null_date_datetime.py | 20 -- .../patches/v5_0/fix_text_editor_file_urls.py | 43 --- frappe/patches/v5_0/force_sync_website.py | 5 - frappe/patches/v5_0/modify_session.py | 6 - ...scheduler_last_event_to_system_settings.py | 8 - .../patches/v5_0/remove_shopping_cart_app.py | 5 - .../v5_0/rename_ref_type_fieldnames.py | 18 - .../patches/v5_0/rename_table_fieldnames.py | 29 -- .../v5_0/style_settings_to_website_theme.py | 59 ---- frappe/patches/v5_0/update_shared.py | 37 --- frappe/patches/v5_0/v4_to_v5.py | 17 - frappe/patches/v5_2/__init__.py | 0 .../patches/v5_2/change_checks_to_not_null.py | 34 -- frappe/patches/v5_3/__init__.py | 0 .../patches/v5_3/rename_chinese_languages.py | 12 - frappe/patches/v6_0/__init__.py | 0 .../communication_status_and_permission.py | 19 -- frappe/patches/v6_0/document_type_rename.py | 8 - frappe/patches/v6_0/fix_ghana_currency.py | 6 - frappe/patches/v6_0/make_task_log_folder.py | 7 - frappe/patches/v6_1/__init__.py | 0 frappe/patches/v6_1/rename_file_data.py | 37 --- frappe/patches/v6_11/__init__.py | 0 .../v6_11/rename_field_in_email_account.py | 7 - frappe/patches/v6_15/__init__.py | 0 ...move_property_setter_for_previous_field.py | 86 ----- frappe/patches/v6_15/set_username.py | 16 - frappe/patches/v6_16/__init__.py | 0 frappe/patches/v6_16/feed_doc_owner.py | 31 -- frappe/patches/v6_16/star_to_like.py | 15 - frappe/patches/v6_19/__init__.py | 0 .../v6_19/comment_feed_communication.py | 307 ------------------ frappe/patches/v6_2/__init__.py | 0 .../ignore_user_permissions_if_missing.py | 8 - frappe/patches/v6_2/rename_backup_manager.py | 20 -- frappe/patches/v6_20x/__init__.py | 0 .../v6_20x/remove_roles_from_website_user.py | 11 - .../v6_20x/set_allow_draft_for_print.py | 5 - frappe/patches/v6_20x/update_insert_after.py | 27 -- frappe/patches/v6_21/__init__.py | 0 .../print_settings_repeat_header_footer.py | 6 - frappe/patches/v6_24/__init__.py | 0 frappe/patches/v6_24/set_language_as_code.py | 8 - frappe/patches/v6_4/__init__.py | 0 frappe/patches/v6_4/reduce_varchar_length.py | 36 -- .../patches/v6_4/rename_bengali_language.py | 6 - frappe/patches/v6_6/__init__.py | 0 frappe/patches/v6_6/fix_file_url.py | 36 -- frappe/patches/v6_6/rename_slovak_language.py | 6 - frappe/patches/v6_6/user_last_active.py | 6 - frappe/patches/v6_9/__init__.py | 0 frappe/patches/v6_9/int_float_not_null.py | 30 -- .../patches/v6_9/rename_burmese_language.py | 6 - frappe/patches/v7_0/__init__.py | 0 .../patches/v7_0/add_communication_in_doc.py | 14 - frappe/patches/v7_0/cleanup_list_settings.py | 20 -- .../v7_0/create_private_file_folder.py | 6 - frappe/patches/v7_0/re_route.py | 23 -- .../v7_0/rename_bulk_email_to_email_queue.py | 5 - .../rename_newsletter_list_to_email_group.py | 6 - frappe/patches/v7_0/set_email_group.py | 10 - frappe/patches/v7_0/set_user_fullname.py | 10 - frappe/patches/v7_0/update_auth.py | 42 --- .../v7_0/update_report_builder_json.py | 11 - .../v7_0/update_send_after_in_bulk_email.py | 6 - frappe/patches/v7_1/__init__.py | 0 ..._print_settings_for_custom_print_format.py | 16 - .../v7_1/refactor_integration_broker.py | 51 --- .../v7_1/rename_chinese_language_codes.py | 11 - .../v7_1/rename_scheduler_log_to_error_log.py | 11 - frappe/patches/v7_1/set_backup_limit.py | 10 - .../v7_1/setup_integration_services.py | 118 ------- frappe/patches/v7_1/sync_language_doctype.py | 22 -- frappe/patches/v7_2/__init__.py | 0 .../patches/v7_2/fix_email_queue_recipient.py | 6 - frappe/patches/v7_2/merge_knowledge_base.py | 24 -- frappe/patches/v7_2/remove_in_filter.py | 7 - frappe/patches/v7_2/set_doctype_engine.py | 7 - .../v7_2/set_in_standard_filter_property.py | 20 -- frappe/patches/v7_2/setup_custom_perms.py | 13 - frappe/patches/v7_2/setup_ldap_config.py | 22 -- frappe/patches/v7_2/update_communications.py | 10 - .../patches/v7_2/update_feedback_request.py | 10 - frappe/patches/v8_0/__init__.py | 0 .../v8_0/deprecate_integration_broker.py | 51 --- frappe/patches/v8_0/drop_in_dialog.py | 7 - .../v8_0/drop_is_custom_from_docperm.py | 8 - frappe/patches/v8_0/drop_unwanted_indexes.py | 16 - .../install_new_build_system_requirements.py | 21 -- .../v8_0/newsletter_childtable_migrate.py | 23 -- .../rename_listsettings_to_usersettings.py | 45 --- .../v8_0/rename_page_role_to_has_role.py | 47 --- .../patches/v8_0/rename_print_to_printing.py | 13 - frappe/patches/v8_0/set_allow_traceback.py | 6 - .../v8_0/set_currency_field_precision.py | 21 -- .../v8_0/set_doctype_values_in_custom_role.py | 12 - ...set_user_permission_for_page_and_report.py | 54 --- frappe/patches/v8_0/setup_email_inbox.py | 26 -- .../v8_0/update_gender_and_salutation.py | 14 - .../v8_0/update_global_search_table.py | 13 - .../v8_0/update_published_in_global_search.py | 12 - .../v8_0/update_records_in_global_search.py | 12 - frappe/patches/v8_1/__init__.py | 0 ...te_custom_docperm_if_doctype_not_exists.py | 7 - ...llow_error_traceback_in_system_settings.py | 14 - ...ate_format_options_in_auto_email_report.py | 13 - frappe/patches/v8_10/__init__.py | 0 ...lete_static_web_page_from_global_search.py | 5 - frappe/patches/v8_5/__init__.py | 0 ..._email_group_member_with_invalid_emails.py | 19 -- frappe/patches/v8_5/patch_event_colors.py | 25 -- frappe/patches/v8_7/__init__.py | 0 frappe/patches/v8_x/__init__.py | 0 frappe/patches/v8_x/update_user_permission.py | 28 -- frappe/patches/v9_1/__init__.py | 1 - .../v9_1/add_sms_sender_name_as_parameters.py | 18 - .../patches/v9_1/move_feed_to_activity_log.py | 24 -- frappe/patches/v9_1/resave_domain_settings.py | 13 - frappe/patches/v9_1/revert_domain_settings.py | 11 - 161 files changed, 2773 deletions(-) delete mode 100644 frappe/patches/v4_0/__init__.py delete mode 100644 frappe/patches/v4_0/add_delete_permission.py delete mode 100644 frappe/patches/v4_0/change_varchar_length.py delete mode 100644 frappe/patches/v4_0/create_custom_field_for_owner_match.py delete mode 100644 frappe/patches/v4_0/deprecate_control_panel.py delete mode 100644 frappe/patches/v4_0/deprecate_link_selects.py delete mode 100644 frappe/patches/v4_0/enable_scheduler_in_system_settings.py delete mode 100644 frappe/patches/v4_0/file_manager_hooks.py delete mode 100644 frappe/patches/v4_0/fix_attach_field_file_url.py delete mode 100644 frappe/patches/v4_0/private_backups.py delete mode 100644 frappe/patches/v4_0/remove_index_sitemap.py delete mode 100644 frappe/patches/v4_0/remove_old_parent.py delete mode 100644 frappe/patches/v4_0/remove_user_owner_custom_field.py delete mode 100644 frappe/patches/v4_0/rename_profile_to_user.py delete mode 100644 frappe/patches/v4_0/rename_sitemap_to_route.py delete mode 100644 frappe/patches/v4_0/replace_deprecated_timezones.py delete mode 100644 frappe/patches/v4_0/set_module_in_report.py delete mode 100644 frappe/patches/v4_0/set_todo_checked_as_closed.py delete mode 100644 frappe/patches/v4_0/set_user_gravatar.py delete mode 100644 frappe/patches/v4_0/set_user_permissions.py delete mode 100644 frappe/patches/v4_0/set_website_route_idx.py delete mode 100644 frappe/patches/v4_0/update_custom_field_insert_after.py delete mode 100644 frappe/patches/v4_0/update_datetime.py delete mode 100644 frappe/patches/v4_0/webnotes_to_frappe.py delete mode 100644 frappe/patches/v4_0/website_sitemap_hierarchy.py delete mode 100644 frappe/patches/v4_1/__init__.py delete mode 100644 frappe/patches/v4_1/enable_outgoing_email_settings.py delete mode 100644 frappe/patches/v4_1/enable_print_as_pdf.py delete mode 100644 frappe/patches/v4_1/file_manager_fix.py delete mode 100644 frappe/patches/v4_2/__init__.py delete mode 100644 frappe/patches/v4_2/print_with_letterhead.py delete mode 100644 frappe/patches/v4_2/refactor_website_routing.py delete mode 100644 frappe/patches/v4_2/set_assign_in_doc.py delete mode 100644 frappe/patches/v4_3/__init__.py delete mode 100644 frappe/patches/v4_3/remove_allow_on_submit_customization.py delete mode 100644 frappe/patches/v5_0/__init__.py delete mode 100644 frappe/patches/v5_0/bookmarks_to_stars.py delete mode 100644 frappe/patches/v5_0/clear_website_group_and_notifications.py delete mode 100644 frappe/patches/v5_0/communication_parent.py delete mode 100644 frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py delete mode 100644 frappe/patches/v5_0/expire_old_scheduler_logs.py delete mode 100644 frappe/patches/v5_0/fix_email_alert.py delete mode 100644 frappe/patches/v5_0/fix_null_date_datetime.py delete mode 100644 frappe/patches/v5_0/fix_text_editor_file_urls.py delete mode 100644 frappe/patches/v5_0/force_sync_website.py delete mode 100644 frappe/patches/v5_0/modify_session.py delete mode 100644 frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py delete mode 100644 frappe/patches/v5_0/remove_shopping_cart_app.py delete mode 100644 frappe/patches/v5_0/rename_ref_type_fieldnames.py delete mode 100644 frappe/patches/v5_0/rename_table_fieldnames.py delete mode 100644 frappe/patches/v5_0/style_settings_to_website_theme.py delete mode 100644 frappe/patches/v5_0/update_shared.py delete mode 100644 frappe/patches/v5_0/v4_to_v5.py delete mode 100644 frappe/patches/v5_2/__init__.py delete mode 100644 frappe/patches/v5_2/change_checks_to_not_null.py delete mode 100644 frappe/patches/v5_3/__init__.py delete mode 100644 frappe/patches/v5_3/rename_chinese_languages.py delete mode 100644 frappe/patches/v6_0/__init__.py delete mode 100644 frappe/patches/v6_0/communication_status_and_permission.py delete mode 100644 frappe/patches/v6_0/document_type_rename.py delete mode 100644 frappe/patches/v6_0/fix_ghana_currency.py delete mode 100644 frappe/patches/v6_0/make_task_log_folder.py delete mode 100644 frappe/patches/v6_1/__init__.py delete mode 100644 frappe/patches/v6_1/rename_file_data.py delete mode 100644 frappe/patches/v6_11/__init__.py delete mode 100644 frappe/patches/v6_11/rename_field_in_email_account.py delete mode 100644 frappe/patches/v6_15/__init__.py delete mode 100644 frappe/patches/v6_15/remove_property_setter_for_previous_field.py delete mode 100644 frappe/patches/v6_15/set_username.py delete mode 100644 frappe/patches/v6_16/__init__.py delete mode 100644 frappe/patches/v6_16/feed_doc_owner.py delete mode 100644 frappe/patches/v6_16/star_to_like.py delete mode 100644 frappe/patches/v6_19/__init__.py delete mode 100644 frappe/patches/v6_19/comment_feed_communication.py delete mode 100644 frappe/patches/v6_2/__init__.py delete mode 100644 frappe/patches/v6_2/ignore_user_permissions_if_missing.py delete mode 100644 frappe/patches/v6_2/rename_backup_manager.py delete mode 100644 frappe/patches/v6_20x/__init__.py delete mode 100644 frappe/patches/v6_20x/remove_roles_from_website_user.py delete mode 100644 frappe/patches/v6_20x/set_allow_draft_for_print.py delete mode 100644 frappe/patches/v6_20x/update_insert_after.py delete mode 100644 frappe/patches/v6_21/__init__.py delete mode 100644 frappe/patches/v6_21/print_settings_repeat_header_footer.py delete mode 100644 frappe/patches/v6_24/__init__.py delete mode 100644 frappe/patches/v6_24/set_language_as_code.py delete mode 100644 frappe/patches/v6_4/__init__.py delete mode 100644 frappe/patches/v6_4/reduce_varchar_length.py delete mode 100644 frappe/patches/v6_4/rename_bengali_language.py delete mode 100644 frappe/patches/v6_6/__init__.py delete mode 100644 frappe/patches/v6_6/fix_file_url.py delete mode 100644 frappe/patches/v6_6/rename_slovak_language.py delete mode 100644 frappe/patches/v6_6/user_last_active.py delete mode 100644 frappe/patches/v6_9/__init__.py delete mode 100644 frappe/patches/v6_9/int_float_not_null.py delete mode 100644 frappe/patches/v6_9/rename_burmese_language.py delete mode 100644 frappe/patches/v7_0/__init__.py delete mode 100644 frappe/patches/v7_0/add_communication_in_doc.py delete mode 100644 frappe/patches/v7_0/cleanup_list_settings.py delete mode 100644 frappe/patches/v7_0/create_private_file_folder.py delete mode 100644 frappe/patches/v7_0/re_route.py delete mode 100644 frappe/patches/v7_0/rename_bulk_email_to_email_queue.py delete mode 100644 frappe/patches/v7_0/rename_newsletter_list_to_email_group.py delete mode 100644 frappe/patches/v7_0/set_email_group.py delete mode 100644 frappe/patches/v7_0/set_user_fullname.py delete mode 100644 frappe/patches/v7_0/update_auth.py delete mode 100644 frappe/patches/v7_0/update_report_builder_json.py delete mode 100644 frappe/patches/v7_0/update_send_after_in_bulk_email.py delete mode 100644 frappe/patches/v7_1/__init__.py delete mode 100644 frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py delete mode 100644 frappe/patches/v7_1/refactor_integration_broker.py delete mode 100644 frappe/patches/v7_1/rename_chinese_language_codes.py delete mode 100644 frappe/patches/v7_1/rename_scheduler_log_to_error_log.py delete mode 100644 frappe/patches/v7_1/set_backup_limit.py delete mode 100644 frappe/patches/v7_1/setup_integration_services.py delete mode 100644 frappe/patches/v7_1/sync_language_doctype.py delete mode 100644 frappe/patches/v7_2/__init__.py delete mode 100644 frappe/patches/v7_2/fix_email_queue_recipient.py delete mode 100644 frappe/patches/v7_2/merge_knowledge_base.py delete mode 100644 frappe/patches/v7_2/remove_in_filter.py delete mode 100644 frappe/patches/v7_2/set_doctype_engine.py delete mode 100644 frappe/patches/v7_2/set_in_standard_filter_property.py delete mode 100644 frappe/patches/v7_2/setup_custom_perms.py delete mode 100644 frappe/patches/v7_2/setup_ldap_config.py delete mode 100644 frappe/patches/v7_2/update_communications.py delete mode 100644 frappe/patches/v7_2/update_feedback_request.py delete mode 100644 frappe/patches/v8_0/__init__.py delete mode 100644 frappe/patches/v8_0/deprecate_integration_broker.py delete mode 100644 frappe/patches/v8_0/drop_in_dialog.py delete mode 100644 frappe/patches/v8_0/drop_is_custom_from_docperm.py delete mode 100644 frappe/patches/v8_0/drop_unwanted_indexes.py delete mode 100644 frappe/patches/v8_0/install_new_build_system_requirements.py delete mode 100644 frappe/patches/v8_0/newsletter_childtable_migrate.py delete mode 100644 frappe/patches/v8_0/rename_listsettings_to_usersettings.py delete mode 100644 frappe/patches/v8_0/rename_page_role_to_has_role.py delete mode 100644 frappe/patches/v8_0/rename_print_to_printing.py delete mode 100644 frappe/patches/v8_0/set_allow_traceback.py delete mode 100644 frappe/patches/v8_0/set_currency_field_precision.py delete mode 100644 frappe/patches/v8_0/set_doctype_values_in_custom_role.py delete mode 100644 frappe/patches/v8_0/set_user_permission_for_page_and_report.py delete mode 100644 frappe/patches/v8_0/setup_email_inbox.py delete mode 100644 frappe/patches/v8_0/update_gender_and_salutation.py delete mode 100644 frappe/patches/v8_0/update_global_search_table.py delete mode 100644 frappe/patches/v8_0/update_published_in_global_search.py delete mode 100644 frappe/patches/v8_0/update_records_in_global_search.py delete mode 100644 frappe/patches/v8_1/__init__.py delete mode 100644 frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py delete mode 100644 frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py delete mode 100644 frappe/patches/v8_1/update_format_options_in_auto_email_report.py delete mode 100644 frappe/patches/v8_10/__init__.py delete mode 100644 frappe/patches/v8_10/delete_static_web_page_from_global_search.py delete mode 100644 frappe/patches/v8_5/__init__.py delete mode 100644 frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py delete mode 100644 frappe/patches/v8_5/patch_event_colors.py delete mode 100644 frappe/patches/v8_7/__init__.py delete mode 100644 frappe/patches/v8_x/__init__.py delete mode 100644 frappe/patches/v8_x/update_user_permission.py delete mode 100644 frappe/patches/v9_1/__init__.py delete mode 100644 frappe/patches/v9_1/add_sms_sender_name_as_parameters.py delete mode 100644 frappe/patches/v9_1/move_feed_to_activity_log.py delete mode 100644 frappe/patches/v9_1/resave_domain_settings.py delete mode 100644 frappe/patches/v9_1/revert_domain_settings.py diff --git a/frappe/patches/v4_0/__init__.py b/frappe/patches/v4_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v4_0/add_delete_permission.py b/frappe/patches/v4_0/add_delete_permission.py deleted file mode 100644 index 9e375a431d..0000000000 --- a/frappe/patches/v4_0/add_delete_permission.py +++ /dev/null @@ -1,13 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "docperm") - - # delete same as cancel (map old permissions) - frappe.db.sql("""update tabDocPerm set `delete`=ifnull(`cancel`,0)""") - - # can't cancel if can't submit - frappe.db.sql("""update tabDocPerm set `cancel`=0 where ifnull(`submit`,0)=0""") - - frappe.clear_cache() \ No newline at end of file diff --git a/frappe/patches/v4_0/change_varchar_length.py b/frappe/patches/v4_0/change_varchar_length.py deleted file mode 100644 index 914034ccba..0000000000 --- a/frappe/patches/v4_0/change_varchar_length.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - frappe.db.sql('update tabDocField set search_index=0 where fieldtype="Small Text"') - frappe.db.sql('update tabDocField set in_list_view=0 where fieldtype="Image"') - - for dt in frappe.db.sql_list("""select name from `tabDocType` where issingle=0"""): - desc = dict((d["Field"], d) for d in frappe.db.sql("desc `tab{}`".format(dt), as_dict=True)) - alter_table = [] - - if desc["name"]["Type"] != "varchar(255)": - alter_table.append("change `name` `name` varchar(255) not null") - - for fieldname in ("modified_by", "owner", "parent", "parentfield", "parenttype"): - if desc[fieldname]["Type"] != "varchar(255)": - alter_table.append("change `{fieldname}` `{fieldname}` varchar(255)".format(fieldname=fieldname)) - - if alter_table: - alter_table_query = "alter table `tab{doctype}` {alter_table}".format(doctype=dt, alter_table=",\n".join(alter_table)) - # print alter_table_query - frappe.db.sql_ddl(alter_table_query) - diff --git a/frappe/patches/v4_0/create_custom_field_for_owner_match.py b/frappe/patches/v4_0/create_custom_field_for_owner_match.py deleted file mode 100644 index 438e280669..0000000000 --- a/frappe/patches/v4_0/create_custom_field_for_owner_match.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt -import frappe -from frappe.custom.doctype.custom_field.custom_field import create_custom_field - -def execute(): - if "match" in frappe.db.get_table_columns("DocPerm"): - create_custom_field_for_owner_match() - -def create_custom_field_for_owner_match(): - docperm_meta = frappe.get_meta('DocPerm') - if docperm_meta.get_field('apply_user_permissions'): - frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=1 where `match`='owner'""") - - for dt in frappe.db.sql_list("""select distinct parent from `tabDocPerm` - where `match`='owner' and permlevel=0 and parent != 'User'"""): - - # a link field pointing to User already exists - if (frappe.db.get_value("DocField", {"parent": dt, "fieldtype": "Link", "options": "User", "default": "__user"}) - or frappe.db.get_value("Custom Field", {"dt": dt, "fieldtype": "Link", "options": "User", "default": "__user"})): - print("User link field already exists for", dt) - continue - - fieldname = "{}_owner".format(frappe.scrub(dt)) - - create_custom_field(dt, frappe._dict({ - "permlevel": 0, - "label": "{} Owner".format(dt), - "fieldname": fieldname, - "fieldtype": "Link", - "options": "User", - "default": "__user" - })) - - frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=owner""".format(doctype=dt, - fieldname=fieldname)) - - # commit is required so that we don't lose these changes because of an error in next loop's ddl - frappe.db.commit() diff --git a/frappe/patches/v4_0/deprecate_control_panel.py b/frappe/patches/v4_0/deprecate_control_panel.py deleted file mode 100644 index 29ec8d35f6..0000000000 --- a/frappe/patches/v4_0/deprecate_control_panel.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - frappe.db.sql("update `tabDefaultValue` set parenttype='__default' where parenttype='Control Panel'") - frappe.db.sql("update `tabDefaultValue` set parent='__default' where parent='Control Panel'") - frappe.clear_cache() diff --git a/frappe/patches/v4_0/deprecate_link_selects.py b/frappe/patches/v4_0/deprecate_link_selects.py deleted file mode 100644 index 837144a6ba..0000000000 --- a/frappe/patches/v4_0/deprecate_link_selects.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - for name in frappe.db.sql_list("""select name from `tabCustom Field` - where fieldtype="Select" and options like "link:%" """): - custom_field = frappe.get_doc("Custom Field", name) - custom_field.fieldtype = "Link" - custom_field.options = custom_field.options[5:] - custom_field.save() diff --git a/frappe/patches/v4_0/enable_scheduler_in_system_settings.py b/frappe/patches/v4_0/enable_scheduler_in_system_settings.py deleted file mode 100644 index 68c74edb4f..0000000000 --- a/frappe/patches/v4_0/enable_scheduler_in_system_settings.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe -from frappe.utils.scheduler import disable_scheduler, enable_scheduler -from frappe.utils import cint - -def execute(): - frappe.reload_doc("core", "doctype", "system_settings") - if cint(frappe.db.get_global("disable_scheduler")): - disable_scheduler() - else: - enable_scheduler() diff --git a/frappe/patches/v4_0/file_manager_hooks.py b/frappe/patches/v4_0/file_manager_hooks.py deleted file mode 100644 index ccf95d1d31..0000000000 --- a/frappe/patches/v4_0/file_manager_hooks.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt -import frappe -import os -from frappe.core.doctype.file.file import get_content_hash - - -def execute(): - frappe.reload_doc('core', 'doctype', 'file_data') - for name, file_name, file_url in frappe.db.sql( - """select name, file_name, file_url from `tabFile` - where file_name is not null"""): - b = frappe.get_doc('File', name) - old_file_name = b.file_name - b.file_name = os.path.basename(old_file_name) - if old_file_name.startswith('files/') or old_file_name.startswith('/files/'): - b.file_url = os.path.normpath('/' + old_file_name) - else: - b.file_url = os.path.normpath('/files/' + old_file_name) - try: - _file = frappe.get_doc("File", {"file_name": name}) - content = _file.get_content() - b.content_hash = get_content_hash(content) - except IOError: - print('Warning: Error processing ', name) - _file_name = old_file_name - b.content_hash = None - - try: - b.save() - except frappe.DuplicateEntryError: - frappe.delete_doc(b.doctype, b.name) - diff --git a/frappe/patches/v4_0/fix_attach_field_file_url.py b/frappe/patches/v4_0/fix_attach_field_file_url.py deleted file mode 100644 index 61c35b120d..0000000000 --- a/frappe/patches/v4_0/fix_attach_field_file_url.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - attach_fields = (frappe.db.sql("""select parent, fieldname from `tabDocField` where fieldtype in ('Attach', 'Attach Image')""") + - frappe.db.sql("""select dt, fieldname from `tabCustom Field` where fieldtype in ('Attach', 'Attach Image')""")) - - for doctype, fieldname in attach_fields: - frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=concat("/", `{fieldname}`) - where `{fieldname}` like 'files/%'""".format(doctype=doctype, fieldname=fieldname)) diff --git a/frappe/patches/v4_0/private_backups.py b/frappe/patches/v4_0/private_backups.py deleted file mode 100644 index 7920564677..0000000000 --- a/frappe/patches/v4_0/private_backups.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe -from frappe.installer import make_site_dirs - -def execute(): - make_site_dirs() - if frappe.local.conf.backup_path and frappe.local.conf.backup_path.startswith("public"): - raise Exception("Backups path in conf set to public directory") diff --git a/frappe/patches/v4_0/remove_index_sitemap.py b/frappe/patches/v4_0/remove_index_sitemap.py deleted file mode 100644 index 8f48729276..0000000000 --- a/frappe/patches/v4_0/remove_index_sitemap.py +++ /dev/null @@ -1,5 +0,0 @@ - -import frappe - -def execute(): - pass diff --git a/frappe/patches/v4_0/remove_old_parent.py b/frappe/patches/v4_0/remove_old_parent.py deleted file mode 100644 index f2d125953a..0000000000 --- a/frappe/patches/v4_0/remove_old_parent.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - for doctype in frappe.db.sql_list("""select name from `tabDocType` where istable=1"""): - frappe.db.sql("""delete from `tab{0}` where parent like "old_par%:%" """.format(doctype)) - frappe.db.sql("""delete from `tabDocField` where parent="0" """) diff --git a/frappe/patches/v4_0/remove_user_owner_custom_field.py b/frappe/patches/v4_0/remove_user_owner_custom_field.py deleted file mode 100644 index 4620f055d9..0000000000 --- a/frappe/patches/v4_0/remove_user_owner_custom_field.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - user_owner = frappe.db.get_value("Custom Field", {"fieldname": "user_owner"}) - if user_owner: - frappe.delete_doc("Custom Field", user_owner) diff --git a/frappe/patches/v4_0/rename_profile_to_user.py b/frappe/patches/v4_0/rename_profile_to_user.py deleted file mode 100644 index 3e6f269329..0000000000 --- a/frappe/patches/v4_0/rename_profile_to_user.py +++ /dev/null @@ -1,15 +0,0 @@ - -import frappe - -from frappe.model.utils.rename_field import rename_field -from frappe.model.meta import get_table_columns - -def execute(): - tables = frappe.db.sql_list("show tables") - if "tabUser" not in tables: - frappe.rename_doc("DocType", "Profile", "User", force=True) - - frappe.reload_doc("website", "doctype", "blogger") - - if "profile" in get_table_columns("Blogger"): - rename_field("Blogger", "profile", "user") diff --git a/frappe/patches/v4_0/rename_sitemap_to_route.py b/frappe/patches/v4_0/rename_sitemap_to_route.py deleted file mode 100644 index b4606672bc..0000000000 --- a/frappe/patches/v4_0/rename_sitemap_to_route.py +++ /dev/null @@ -1,25 +0,0 @@ - -import frappe - -from frappe.model.utils.rename_field import rename_field - -def execute(): - tables = frappe.db.sql_list("show tables") - for doctype in ("Website Sitemap", "Website Sitemap Config"): - if "tab{}".format(doctype) in tables: - frappe.delete_doc("DocType", doctype, force=1) - frappe.db.sql("drop table `tab{}`".format(doctype)) - - for d in ("Blog Category", "Blog Post", "Web Page"): - frappe.reload_doc("website", "doctype", frappe.scrub(d)) - rename_field_if_exists(d, "parent_website_sitemap", "parent_website_route") - - for d in ("blog_category", "blog_post", "web_page", "post", "user_vote"): - frappe.reload_doc("website", "doctype", d) - -def rename_field_if_exists(doctype, old_fieldname, new_fieldname): - try: - rename_field(doctype, old_fieldname, new_fieldname) - except frappe.db.ProgrammingError as e: - if not frappe.db.is_column_missing(e): - raise diff --git a/frappe/patches/v4_0/replace_deprecated_timezones.py b/frappe/patches/v4_0/replace_deprecated_timezones.py deleted file mode 100644 index a3d8ecbf2b..0000000000 --- a/frappe/patches/v4_0/replace_deprecated_timezones.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe -from frappe.utils.momentjs import data as momentjs_data - -def execute(): - frappe.reload_doc("core", "doctype", "user") - - ss = frappe.get_doc("System Settings", "System Settings") - if ss.time_zone in momentjs_data.get("links"): - ss.time_zone = momentjs_data["links"][ss.time_zone] - ss.flags.ignore_mandatory = True - ss.save() - - for user, time_zone in frappe.db.sql("select name, time_zone from `tabUser` where ifnull(time_zone, '')!=''"): - if time_zone in momentjs_data.get("links"): - user = frappe.get_doc("User", user) - user.time_zone = momentjs_data["links"][user.time_zone] - user.save() diff --git a/frappe/patches/v4_0/set_module_in_report.py b/frappe/patches/v4_0/set_module_in_report.py deleted file mode 100644 index 6c670f4c8e..0000000000 --- a/frappe/patches/v4_0/set_module_in_report.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "report") - frappe.db.sql("""update `tabReport` r set r.module=(select d.module from `tabDocType` d - where d.name=r.ref_doctype) where ifnull(r.module, '')=''""") \ No newline at end of file diff --git a/frappe/patches/v4_0/set_todo_checked_as_closed.py b/frappe/patches/v4_0/set_todo_checked_as_closed.py deleted file mode 100644 index 5f02e1447b..0000000000 --- a/frappe/patches/v4_0/set_todo_checked_as_closed.py +++ /dev/null @@ -1,9 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "todo") - try: - frappe.db.sql("""update tabToDo set status = if(ifnull(checked,0)=0, 'Open', 'Closed')""") - except: - pass diff --git a/frappe/patches/v4_0/set_user_gravatar.py b/frappe/patches/v4_0/set_user_gravatar.py deleted file mode 100644 index 348991c320..0000000000 --- a/frappe/patches/v4_0/set_user_gravatar.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - for name in frappe.db.sql_list("select name from `tabUser` where ifnull(user_image, '')=''"): - user = frappe.get_doc("User", name) - user.update_gravatar() - user.db_set("user_image", user.user_image) diff --git a/frappe/patches/v4_0/set_user_permissions.py b/frappe/patches/v4_0/set_user_permissions.py deleted file mode 100644 index ef6f3a27e5..0000000000 --- a/frappe/patches/v4_0/set_user_permissions.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe -import frappe.permissions - -def execute(): - frappe.reload_doc("core", "doctype", "docperm") - table_columns = frappe.db.get_table_columns("DocPerm") - - if "restricted" in table_columns: - frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=1 where apply_user_permissions=0 - and restricted=1""") - - if "match" in table_columns: - frappe.db.sql("""update `tabDocPerm` set apply_user_permissions=1 - where apply_user_permissions=0 and ifnull(`match`, '')!=''""") - - # change Restriction to User Permission in tabDefaultValue - frappe.db.sql("""update `tabDefaultValue` set parenttype='User Permission' where parenttype='Restriction'""") - - frappe.clear_cache() - diff --git a/frappe/patches/v4_0/set_website_route_idx.py b/frappe/patches/v4_0/set_website_route_idx.py deleted file mode 100644 index c3dba712d8..0000000000 --- a/frappe/patches/v4_0/set_website_route_idx.py +++ /dev/null @@ -1,25 +0,0 @@ - -import frappe - -def execute(): - pass - # from frappe.website.doctype.website_template.website_template import \ - # get_pages_and_generators, get_template_controller - # - # frappe.reload_doc("website", "doctype", "website_template") - # frappe.reload_doc("website", "doctype", "website_route") - # - # for app in frappe.get_installed_apps(): - # pages, generators = get_pages_and_generators(app) - # for g in generators: - # doctype = frappe.get_attr(get_template_controller(app, g["path"], g["fname"]) + ".doctype") - # module = frappe.db.get_value("DocType", doctype, "module") - # frappe.reload_doc(frappe.scrub(module), "doctype", frappe.scrub(doctype)) - # - # frappe.db.sql("""update `tabBlog Category` set `title`=`name` where ifnull(`title`, '')=''""") - # frappe.db.sql("""update `tabWebsite Route` set idx=null""") - # for doctype in ["Blog Category", "Blog Post", "Web Page", "Website Group"]: - # frappe.db.sql("""update `tab{}` set idx=null""".format(doctype)) - # - # from frappe.website.doctype.website_template.website_template import rebuild_website_template - # rebuild_website_template() diff --git a/frappe/patches/v4_0/update_custom_field_insert_after.py b/frappe/patches/v4_0/update_custom_field_insert_after.py deleted file mode 100644 index 4cb50956d6..0000000000 --- a/frappe/patches/v4_0/update_custom_field_insert_after.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - for d in frappe.db.sql("""select name, dt, insert_after from `tabCustom Field` - where docstatus < 2""", as_dict=1): - dt_meta = frappe.get_meta(d.dt) - if not dt_meta.get_field(d.insert_after): - cf = frappe.get_doc("Custom Field", d.name) - df = dt_meta.get("fields", {"label": d.insert_after}) - if df: - cf.insert_after = df[0].fieldname - else: - cf.insert_after = None - cf.save() diff --git a/frappe/patches/v4_0/update_datetime.py b/frappe/patches/v4_0/update_datetime.py deleted file mode 100644 index 4034d8f665..0000000000 --- a/frappe/patches/v4_0/update_datetime.py +++ /dev/null @@ -1,12 +0,0 @@ - -import frappe - -def execute(): - for table in frappe.db.sql_list("show tables"): - for field in frappe.db.sql("desc `%s`" % table): - if field[1]=="datetime": - frappe.db.sql("alter table `%s` change `%s` `%s` datetime(6)" % \ - (table, field[0], field[0])) - elif field[1]=="time": - frappe.db.sql("alter table `%s` change `%s` `%s` time(6)" % \ - (table, field[0], field[0])) diff --git a/frappe/patches/v4_0/webnotes_to_frappe.py b/frappe/patches/v4_0/webnotes_to_frappe.py deleted file mode 100644 index c29f6f603e..0000000000 --- a/frappe/patches/v4_0/webnotes_to_frappe.py +++ /dev/null @@ -1,12 +0,0 @@ - -import frappe, json - -def execute(): - frappe.clear_cache() - installed = frappe.get_installed_apps() - if "webnotes" in installed: - installed.remove("webnotes") - if "frappe" not in installed: - installed = ["frappe"] + installed - frappe.db.set_global("installed_apps", json.dumps(installed)) - frappe.clear_cache() diff --git a/frappe/patches/v4_0/website_sitemap_hierarchy.py b/frappe/patches/v4_0/website_sitemap_hierarchy.py deleted file mode 100644 index 6404986245..0000000000 --- a/frappe/patches/v4_0/website_sitemap_hierarchy.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - # frappe.db.sql("""update `tabWebsite Route` ws set ref_doctype=(select wsc.ref_doctype - # from `tabWebsite Template` wsc where wsc.name=ws.website_template) - # where ifnull(page_or_generator, '')!='Page'""") - - frappe.reload_doc("website", "doctype", "website_settings") - - # original_home_page = frappe.db.get_value("Website Settings", "Website Settings", "home_page") - # - # home_page = frappe.db.sql("""select name from `tabWebsite Route` - # where (name=%s or docname=%s) and name!='index'""", (original_home_page, original_home_page)) - # home_page = home_page[0][0] if home_page else original_home_page - # - # frappe.db.set_value("Website Settings", "Website Settings", "home_page", home_page) diff --git a/frappe/patches/v4_1/__init__.py b/frappe/patches/v4_1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v4_1/enable_outgoing_email_settings.py b/frappe/patches/v4_1/enable_outgoing_email_settings.py deleted file mode 100644 index ffa891ae7c..0000000000 --- a/frappe/patches/v4_1/enable_outgoing_email_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "outgoing_email_settings") - if (frappe.db.get_value("Outgoing Email Settings", "Outgoing Email Settings", "mail_server") or "").strip(): - frappe.db.set_value("Outgoing Email Settings", "Outgoing Email Settings", "enabled", 1) diff --git a/frappe/patches/v4_1/enable_print_as_pdf.py b/frappe/patches/v4_1/enable_print_as_pdf.py deleted file mode 100644 index e5a8f830f6..0000000000 --- a/frappe/patches/v4_1/enable_print_as_pdf.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "print_settings") - print_settings = frappe.get_doc("Print Settings") - print_settings.print_style = "Modern" - - try: - import pdfkit - except ImportError: - pass - else: - # if someone has already configured in Outgoing Email Settings - outgoing_email_settings = frappe.db.get_singles_dict("Outgoing Email Settings") - if "send_print_as_pdf" in outgoing_email_settings: - print_settings.send_print_as_pdf = outgoing_email_settings.send_print_as_pdf - print_settings.pdf_page_size = outgoing_email_settings.pdf_page_size - - else: - print_settings.send_print_as_pdf = 1 - - print_settings.save() diff --git a/frappe/patches/v4_1/file_manager_fix.py b/frappe/patches/v4_1/file_manager_fix.py deleted file mode 100644 index 18f44203f2..0000000000 --- a/frappe/patches/v4_1/file_manager_fix.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt -import frappe -import os -from frappe.core.doctype.file.file import get_content_hash, get_file_name -from frappe.utils import get_files_path, get_site_path - -# The files missed by the previous patch might have been replaced with new files -# with the same filename -# -# This patch does the following, -# * Detect which files were replaced and rename them with name{hash:5}.extn and -# update filedata record for the new file -# -# * make missing_files.txt in site dir with files that should be recovered from -# a backup from a time before version 3 migration -# -# * Patch remaining unpatched File records. - - -def execute(): - frappe.db.auto_commit_on_many_writes = True - rename_replacing_files() - for name, file_name, file_url in frappe.db.sql( - """select name, file_name, file_url from `tabFile` - where ifnull(file_name, '')!='' and ifnull(content_hash, '')=''"""): - b = frappe.get_doc('File', name) - old_file_name = b.file_name - b.file_name = os.path.basename(old_file_name) - if old_file_name.startswith('files/') or old_file_name.startswith('/files/'): - b.file_url = os.path.normpath('/' + old_file_name) - else: - b.file_url = os.path.normpath('/files/' + old_file_name) - try: - _file = frappe.get_doc("File", {"file_name": name}) - content = _file.get_content() - b.content_hash = get_content_hash(content) - except IOError: - print('Warning: Error processing ', name) - b.content_hash = None - b.flags.ignore_duplicate_entry_error = True - b.save() - frappe.db.auto_commit_on_many_writes = False - -def get_replaced_files(): - ret = [] - new_files = dict(frappe.db.sql("select name, file_name from `tabFile` where file_name not like 'files/%'")) - old_files = dict(frappe.db.sql("select name, file_name from `tabFile` where ifnull(content_hash, '')=''")) - invfiles = invert_dict(new_files) - - for nname, nfilename in new_files.items(): - if 'files/' + nfilename in old_files.values(): - ret.append((nfilename, invfiles[nfilename])) - return ret - -def rename_replacing_files(): - replaced_files = get_replaced_files() - if len(replaced_files): - missing_files = [v[0] for v in replaced_files] - with open(get_site_path('missing_files.txt'), 'w') as f: - f.write(('\n'.join(missing_files) + '\n').encode('utf-8')) - - for file_name, file_datas in replaced_files: - print ('processing ' + file_name) - content_hash = frappe.db.get_value('File', file_datas[0], 'content_hash') - if not content_hash: - continue - new_file_name = get_file_name(file_name, content_hash) - if os.path.exists(get_files_path(new_file_name)): - continue - print('skipping ' + file_name) - try: - os.rename(get_files_path(file_name), get_files_path(new_file_name)) - except OSError: - print('Error renaming ', file_name) - for name in file_datas: - f = frappe.get_doc('File', name) - f.file_name = new_file_name - f.file_url = '/files/' + new_file_name - f.save() - -def invert_dict(ddict): - ret = {} - for k,v in ddict.items(): - if not ret.get(v): - ret[v] = [k] - else: - ret[v].append(k) - return ret - -def get_file_name(fname, hash): - if '.' in fname: - partial, extn = fname.rsplit('.', 1) - else: - partial = fname - extn = '' - return '{partial}{suffix}.{extn}'.format(partial=partial, extn=extn, suffix=hash[:5]) diff --git a/frappe/patches/v4_2/__init__.py b/frappe/patches/v4_2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v4_2/print_with_letterhead.py b/frappe/patches/v4_2/print_with_letterhead.py deleted file mode 100644 index 111f6c762e..0000000000 --- a/frappe/patches/v4_2/print_with_letterhead.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "print_settings") - print_settings = frappe.get_doc("Print Settings") - print_settings.with_letterhead = 1 - print_settings.save() diff --git a/frappe/patches/v4_2/refactor_website_routing.py b/frappe/patches/v4_2/refactor_website_routing.py deleted file mode 100644 index 77eea3d429..0000000000 --- a/frappe/patches/v4_2/refactor_website_routing.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -def execute(): - # clear all static web pages - frappe.delete_doc("DocType", "Website Route", force=1) - frappe.delete_doc("Page", "sitemap-browser", force=1) - frappe.db.sql("drop table if exists `tabWebsite Route`") diff --git a/frappe/patches/v4_2/set_assign_in_doc.py b/frappe/patches/v4_2/set_assign_in_doc.py deleted file mode 100644 index 8fbd37c5c5..0000000000 --- a/frappe/patches/v4_2/set_assign_in_doc.py +++ /dev/null @@ -1,11 +0,0 @@ - -import frappe - -def execute(): - for name in frappe.db.sql_list("""select name from `tabToDo` - where ifnull(reference_type, '')!='' and ifnull(reference_name, '')!=''"""): - try: - frappe.get_doc("ToDo", name).on_update() - except Exception as e: - if not frappe.db.is_table_missing(e): - raise diff --git a/frappe/patches/v4_3/__init__.py b/frappe/patches/v4_3/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v4_3/remove_allow_on_submit_customization.py b/frappe/patches/v4_3/remove_allow_on_submit_customization.py deleted file mode 100644 index a762fd10ab..0000000000 --- a/frappe/patches/v4_3/remove_allow_on_submit_customization.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - for d in frappe.get_all("Property Setter", fields=["name", "doc_type"], - filters={"doctype_or_field": "DocField", "property": "allow_on_submit", "value": "1"}): - frappe.delete_doc("Property Setter", d.name) - frappe.clear_cache(doctype=d.doc_type) diff --git a/frappe/patches/v5_0/__init__.py b/frappe/patches/v5_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v5_0/bookmarks_to_stars.py b/frappe/patches/v5_0/bookmarks_to_stars.py deleted file mode 100644 index 0d2c13525e..0000000000 --- a/frappe/patches/v5_0/bookmarks_to_stars.py +++ /dev/null @@ -1,32 +0,0 @@ - -import json -import frappe -import frappe.defaults -from frappe.desk.like import _toggle_like - -def execute(): - for user in frappe.get_all("User"): - username = user["name"] - bookmarks = frappe.db.get_default("_bookmarks", username) - - if not bookmarks: - continue - - if isinstance(bookmarks, str): - bookmarks = json.loads(bookmarks) - - for opts in bookmarks: - route = (opts.get("route") or "").strip("#/ ") - - if route and route.startswith("Form"): - try: - view, doctype, docname = opts["route"].split("/") - except ValueError: - continue - - if frappe.db.exists(doctype, docname): - if (doctype=="DocType" - or int(frappe.db.get_value("DocType", doctype, "issingle") or 0) - or not frappe.db.table_exists(doctype)): - continue - _toggle_like(doctype, docname, add="Yes", user=username) diff --git a/frappe/patches/v5_0/clear_website_group_and_notifications.py b/frappe/patches/v5_0/clear_website_group_and_notifications.py deleted file mode 100644 index 3d3d0c0d16..0000000000 --- a/frappe/patches/v5_0/clear_website_group_and_notifications.py +++ /dev/null @@ -1,9 +0,0 @@ - -import frappe - -def execute(): - frappe.delete_doc("DocType", "Post") - frappe.delete_doc("DocType", "Website Group") - frappe.delete_doc("DocType", "Website Route Permission") - frappe.delete_doc("DocType", "User Vote") - frappe.delete_doc("DocType", "Notification Count") diff --git a/frappe/patches/v5_0/communication_parent.py b/frappe/patches/v5_0/communication_parent.py deleted file mode 100644 index 3c73d91972..0000000000 --- a/frappe/patches/v5_0/communication_parent.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "communication") - frappe.db.sql("""update tabCommunication set reference_doctype = parenttype, reference_name = parent""") diff --git a/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py b/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py deleted file mode 100644 index 6fa6434f98..0000000000 --- a/frappe/patches/v5_0/convert_to_barracuda_and_utf8mb4.py +++ /dev/null @@ -1,16 +0,0 @@ - -import frappe -from frappe.database.mariadb.setup_db import check_database_settings -from frappe.model.meta import trim_tables - -def execute(): - check_database_settings() - - for table in frappe.db.get_tables(): - frappe.db.sql_ddl("""alter table `{0}` ENGINE=InnoDB ROW_FORMAT=COMPRESSED""".format(table)) - try: - frappe.db.sql_ddl("""alter table `{0}` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci""".format(table)) - except: - # if row size gets too large, let it be old charset! - pass - diff --git a/frappe/patches/v5_0/expire_old_scheduler_logs.py b/frappe/patches/v5_0/expire_old_scheduler_logs.py deleted file mode 100644 index 0262acd346..0000000000 --- a/frappe/patches/v5_0/expire_old_scheduler_logs.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype("Error Log") - - from frappe.core.doctype.error_log.error_log import set_old_logs_as_seen - set_old_logs_as_seen() diff --git a/frappe/patches/v5_0/fix_email_alert.py b/frappe/patches/v5_0/fix_email_alert.py deleted file mode 100644 index e7366e8b66..0000000000 --- a/frappe/patches/v5_0/fix_email_alert.py +++ /dev/null @@ -1,14 +0,0 @@ -import frappe - -def execute(): - frappe.reload_doctype("Notification") - for e in frappe.get_all("Notification"): - notification = frappe.get_doc("Notification", e.name) - if notification.event == "Date Change": - if notification.days_in_advance < 0: - notification.event = "Days After" - notification.days_in_advance = -email_alert.days_in_advance - else: - notification.event = "Days Before" - - notification.save() diff --git a/frappe/patches/v5_0/fix_null_date_datetime.py b/frappe/patches/v5_0/fix_null_date_datetime.py deleted file mode 100644 index 078cba079a..0000000000 --- a/frappe/patches/v5_0/fix_null_date_datetime.py +++ /dev/null @@ -1,20 +0,0 @@ - -import frappe - -def execute(): - for table in frappe.db.get_tables(): - changed = False - desc = frappe.db.sql("desc `{table}`".format(table=table), as_dict=True) - for field in desc: - if field["Type"] == "date": - frappe.db.sql("""update `{table}` set `{fieldname}`=null where `{fieldname}`='0000-00-00'""".format( - table=table, fieldname=field["Field"])) - changed = True - - elif field["Type"] == "datetime(6)": - frappe.db.sql("""update `{table}` set `{fieldname}`=null where `{fieldname}`='0000-00-00 00:00:00.000000'""".format( - table=table, fieldname=field["Field"])) - changed = True - - if changed: - frappe.db.commit() diff --git a/frappe/patches/v5_0/fix_text_editor_file_urls.py b/frappe/patches/v5_0/fix_text_editor_file_urls.py deleted file mode 100644 index 43f0c9d8a5..0000000000 --- a/frappe/patches/v5_0/fix_text_editor_file_urls.py +++ /dev/null @@ -1,43 +0,0 @@ -import frappe -import re - -def execute(): - """Fix relative urls for image src="files/" to src="/files/" in DocTypes with text editor fields""" - doctypes_with_text_fields = frappe.get_all("DocField", fields=["parent", "fieldname"], - filters={"fieldtype": "Text Editor"}) - - done = [] - for opts in doctypes_with_text_fields: - if opts in done: - continue - - try: - result = frappe.get_all(opts.parent, fields=["name", opts.fieldname]) - except frappe.db.SQLError: - # bypass single tables - continue - - for data in result: - old_value = data[opts.fieldname] - if not old_value: - continue - - html = scrub_relative_urls(old_value) - if html != old_value: - # print_diff(html, old_value) - frappe.db.set_value(opts.parent, data.name, opts.fieldname, html, update_modified=False) - - done.append(opts) - -def scrub_relative_urls(html): - """prepend a slash before a relative url""" - try: - return re.sub(r'src[\s]*=[\s]*[\'"]files/([^\'"]*)[\'"]', r'src="/files/\g<1>"', html) - except: - print("Error", html) - raise - -def print_diff(html, old_value): - import difflib - diff = difflib.unified_diff(old_value.splitlines(1), html.splitlines(1), lineterm='') - print('\n'.join(list(diff))) diff --git a/frappe/patches/v5_0/force_sync_website.py b/frappe/patches/v5_0/force_sync_website.py deleted file mode 100644 index 8f48729276..0000000000 --- a/frappe/patches/v5_0/force_sync_website.py +++ /dev/null @@ -1,5 +0,0 @@ - -import frappe - -def execute(): - pass diff --git a/frappe/patches/v5_0/modify_session.py b/frappe/patches/v5_0/modify_session.py deleted file mode 100644 index 1c2ff0d6e6..0000000000 --- a/frappe/patches/v5_0/modify_session.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - if "device" not in frappe.db.get_table_columns("Sessions"): - frappe.db.sql("alter table tabSessions add column `device` varchar(255) default 'desktop'") diff --git a/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py b/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py deleted file mode 100644 index bdc52e6152..0000000000 --- a/frappe/patches/v5_0/move_scheduler_last_event_to_system_settings.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype('System Settings') - last = frappe.db.get_global('scheduler_last_event') - frappe.db.set_value('System Settings', 'System Settings', 'scheduler_last_event', last) - diff --git a/frappe/patches/v5_0/remove_shopping_cart_app.py b/frappe/patches/v5_0/remove_shopping_cart_app.py deleted file mode 100644 index ed9414159e..0000000000 --- a/frappe/patches/v5_0/remove_shopping_cart_app.py +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt -def execute(): - from frappe.installer import remove_from_installed_apps - remove_from_installed_apps("shopping_cart") diff --git a/frappe/patches/v5_0/rename_ref_type_fieldnames.py b/frappe/patches/v5_0/rename_ref_type_fieldnames.py deleted file mode 100644 index 01e36af8a9..0000000000 --- a/frappe/patches/v5_0/rename_ref_type_fieldnames.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import frappe - -def execute(): - try: - frappe.db.sql("alter table `tabEmail Queue` change `ref_docname` `reference_name` varchar(255)") - except Exception as e: - if not frappe.db.is_table_or_column_missing(e): - raise - - try: - frappe.db.sql("alter table `tabEmail Queue` change `ref_doctype` `reference_doctype` varchar(255)") - except Exception as e: - if not frappe.db.is_table_or_column_missing(e): - raise - frappe.reload_doctype("Email Queue") diff --git a/frappe/patches/v5_0/rename_table_fieldnames.py b/frappe/patches/v5_0/rename_table_fieldnames.py deleted file mode 100644 index 79703bbba2..0000000000 --- a/frappe/patches/v5_0/rename_table_fieldnames.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe -from frappe.model.utils.rename_field import rename_field -from frappe.modules import scrub, get_doctype_module - -rename_map = { - "Customize Form": [ - ["customize_form_fields", "fields"] - ], - "Email Alert": [ - ["email_alert_recipients", "recipients"] - ], - "Workflow": [ - ["workflow_document_states", "states"], - ["workflow_transitions", "transitions"] - ] -} - -def execute(): - frappe.reload_doc("custom", "doctype", "customize_form") - frappe.reload_doc("email", "doctype", "notification") - frappe.reload_doc("desk", "doctype", "event") - frappe.reload_doc("workflow", "doctype", "workflow") - - for dt, field_list in rename_map.items(): - for field in field_list: - rename_field(dt, field[0], field[1]) diff --git a/frappe/patches/v5_0/style_settings_to_website_theme.py b/frappe/patches/v5_0/style_settings_to_website_theme.py deleted file mode 100644 index 73ee28c1fc..0000000000 --- a/frappe/patches/v5_0/style_settings_to_website_theme.py +++ /dev/null @@ -1,59 +0,0 @@ - -import frappe -from frappe import _ -from frappe.utils import cint - -def execute(): - frappe.reload_doc("website", "doctype", "website_theme") - frappe.reload_doc("website", "website_theme", "standard") - frappe.reload_doctype("Website Settings") - migrate_style_settings() - frappe.delete_doc("website", "doctype", "style_settings") - -def migrate_style_settings(): - style_settings = frappe.db.get_singles_dict("Style Settings") - standard_website_theme = frappe.get_doc("Website Theme", "Standard") - - website_theme = frappe.copy_doc(standard_website_theme) - website_theme.custom = 1 - website_theme.theme = _("Custom") - - if style_settings: - map_color_fields(style_settings, website_theme) - map_other_fields(style_settings, website_theme) - - website_theme.no_sidebar = cint(frappe.db.get_single_value("Website Settings", "no_sidebar")) - - website_theme.save() - website_theme.set_as_default() - -def map_color_fields(style_settings, website_theme): - color_fields_map = { - "page_text": "text_color", - "page_links": "link_color", - "top_bar_background": "top_bar_color", - "top_bar_foreground": "top_bar_text_color", - "footer_background": "footer_color", - "footer_color": "footer_text_color", - } - - for from_fieldname, to_fieldname in color_fields_map.items(): - from_value = style_settings.get(from_fieldname) - - if from_value: - website_theme.set(to_fieldname, "#{0}".format(from_value)) - -def map_other_fields(style_settings, website_theme): - other_fields_map = { - "heading_text_as": "heading_style", - "google_web_font_for_heading": "heading_webfont", - "google_web_font_for_text": "text_webfont", - "add_css": "css" - } - - for from_fieldname, to_fieldname in other_fields_map.items(): - website_theme.set(to_fieldname, style_settings.get(from_fieldname)) - - for fieldname in ("apply_style", "background_image", "background_color", - "font_size"): - website_theme.set(fieldname, style_settings.get(fieldname)) diff --git a/frappe/patches/v5_0/update_shared.py b/frappe/patches/v5_0/update_shared.py deleted file mode 100644 index e549d7271d..0000000000 --- a/frappe/patches/v5_0/update_shared.py +++ /dev/null @@ -1,37 +0,0 @@ - -import frappe -import frappe.share - -def execute(): - frappe.reload_doc("core", "doctype", "docperm") - frappe.reload_doc("core", "doctype", "docshare") - frappe.reload_doc('email', 'doctype', 'email_account') - - # default share to all writes - frappe.db.sql("""update tabDocPerm set `share`=1 where ifnull(`write`,0)=1 and ifnull(`permlevel`,0)=0""") - - # every user must have access to his / her own detail - users = frappe.get_all("User", filters={"user_type": "System User"}) - usernames = [user.name for user in users] - for user in usernames: - frappe.share.add("User", user, user, write=1, share=1) - - # move event user to shared - if frappe.db.exists("DocType", "Event User"): - for event in frappe.get_all("Event User", fields=["parent", "person"]): - if event.person in usernames: - if not frappe.db.exists("Event", event.parent): - frappe.db.sql("delete from `tabEvent User` where parent = %s",event.parent) - else: - frappe.share.add("Event", event.parent, event.person, write=1) - - frappe.delete_doc("DocType", "Event User") - - # move note user to shared - if frappe.db.exists("DocType", "Note User"): - for note in frappe.get_all("Note User", fields=["parent", "user", "permission"]): - perm = {"read": 1} if note.permission=="Read" else {"write": 1} - if note.user in usernames: - frappe.share.add("Note", note.parent, note.user, **perm) - - frappe.delete_doc("DocType", "Note User") diff --git a/frappe/patches/v5_0/v4_to_v5.py b/frappe/patches/v5_0/v4_to_v5.py deleted file mode 100644 index 479acc6d63..0000000000 --- a/frappe/patches/v5_0/v4_to_v5.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe - -def execute(): - changed = ( - ("desk", ("feed", "event", "todo", "note")), - ("custom", ("custom_field", "custom_script", "customize_form", - "customize_form_field", "property_setter")), - ("email", ("email_queue", "notification", "notification_recipient", "standard_reply")), - ("geo", ("country", "currency")), - ("print", ("letter_head", "print_format", "print_settings")) - ) - for module in changed: - for doctype in module[1]: - frappe.reload_doc(module[0], "doctype", doctype) diff --git a/frappe/patches/v5_2/__init__.py b/frappe/patches/v5_2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v5_2/change_checks_to_not_null.py b/frappe/patches/v5_2/change_checks_to_not_null.py deleted file mode 100644 index 32be3aa752..0000000000 --- a/frappe/patches/v5_2/change_checks_to_not_null.py +++ /dev/null @@ -1,34 +0,0 @@ - -import frappe -from frappe.utils import cint -from frappe.model import default_fields - -def execute(): - for table in frappe.db.get_tables(): - doctype = table[3:] - if frappe.db.exists("DocType", doctype): - fieldnames = [df["fieldname"] for df in - frappe.get_all("DocField", fields=["fieldname"], filters={"parent": doctype})] - custom_fieldnames = [df["fieldname"] for df in - frappe.get_all("Custom Field", fields=["fieldname"], filters={"dt": doctype})] - - else: - fieldnames = custom_fieldnames = [] - - for column in frappe.db.sql("""desc `{0}`""".format(table), as_dict=True): - if column["Type"]=="int(1)": - fieldname = column["Field"] - - # only change for defined fields, ignore old fields that don't exist in meta - if not (fieldname in default_fields or fieldname in fieldnames or fieldname in custom_fieldnames): - continue - - # set 0 - frappe.db.sql("""update `{table}` set `{column}`=0 where `{column}` is null"""\ - .format(table=table, column=fieldname)) - frappe.db.commit() - - # change definition - frappe.db.sql_ddl("""alter table `{table}` - modify `{column}` int(1) not null default {default}"""\ - .format(table=table, column=fieldname, default=cint(column["Default"]))) diff --git a/frappe/patches/v5_3/__init__.py b/frappe/patches/v5_3/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v5_3/rename_chinese_languages.py b/frappe/patches/v5_3/rename_chinese_languages.py deleted file mode 100644 index f720fb7538..0000000000 --- a/frappe/patches/v5_3/rename_chinese_languages.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -import frappe -from frappe.translate import rename_language - -def execute(): - language_map = { - "中国(简体)": "簡體中文", - "中國(繁體)": "正體中文" - } - - for old_name, new_name in language_map.items(): - rename_language(old_name, new_name) diff --git a/frappe/patches/v6_0/__init__.py b/frappe/patches/v6_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_0/communication_status_and_permission.py b/frappe/patches/v6_0/communication_status_and_permission.py deleted file mode 100644 index 435dcc21a5..0000000000 --- a/frappe/patches/v6_0/communication_status_and_permission.py +++ /dev/null @@ -1,19 +0,0 @@ - -import frappe -from frappe.permissions import reset_perms - -def execute(): - frappe.reload_doctype("Communication") - - # set status = "Linked" - frappe.db.sql("""update `tabCommunication` set status='Linked' - where ifnull(reference_doctype, '')!='' and ifnull(reference_name, '')!=''""") - - frappe.db.sql("""update `tabCommunication` set status='Closed' - where status='Archived'""") - - # reset permissions if owner of all DocPerms is Administrator - if not frappe.db.sql("""select name from `tabDocPerm` - where parent='Communication' and ifnull(owner, '')!='Administrator'"""): - - reset_perms("Communication") diff --git a/frappe/patches/v6_0/document_type_rename.py b/frappe/patches/v6_0/document_type_rename.py deleted file mode 100644 index 53eec5d85c..0000000000 --- a/frappe/patches/v6_0/document_type_rename.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -def execute(): - frappe.db.sql("""update tabDocType set document_type='Document' - where document_type='Transaction'""") - frappe.db.sql("""update tabDocType set document_type='Setup' - where document_type='Master'""") diff --git a/frappe/patches/v6_0/fix_ghana_currency.py b/frappe/patches/v6_0/fix_ghana_currency.py deleted file mode 100644 index 50feb3ca3f..0000000000 --- a/frappe/patches/v6_0/fix_ghana_currency.py +++ /dev/null @@ -1,6 +0,0 @@ -def execute(): - from frappe.geo.country_info import get_all - import frappe.utils.install - - countries = get_all() - frappe.utils.install.add_country_and_currency("Ghana", frappe._dict(countries["Ghana"])) diff --git a/frappe/patches/v6_0/make_task_log_folder.py b/frappe/patches/v6_0/make_task_log_folder.py deleted file mode 100644 index b5ed547d71..0000000000 --- a/frappe/patches/v6_0/make_task_log_folder.py +++ /dev/null @@ -1,7 +0,0 @@ - -import frappe.utils, os - -def execute(): - path = frappe.utils.get_site_path('task-logs') - if not os.path.exists(path): - os.makedirs(path) diff --git a/frappe/patches/v6_1/__init__.py b/frappe/patches/v6_1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_1/rename_file_data.py b/frappe/patches/v6_1/rename_file_data.py deleted file mode 100644 index 3c62217e8d..0000000000 --- a/frappe/patches/v6_1/rename_file_data.py +++ /dev/null @@ -1,37 +0,0 @@ -import frappe - -def execute(): - from frappe.core.doctype.file.file import make_home_folder - - if not frappe.db.exists("DocType", "File"): - frappe.rename_doc("DocType", "File Data", "File") - frappe.reload_doctype("File") - - if not frappe.db.exists("File", {"is_home_folder": 1}): - make_home_folder() - - # make missing folders and set parent folder - for file in frappe.get_all("File", filters={"is_folder": 0}): - file = frappe.get_doc("File", file.name) - file.flags.ignore_folder_validate = True - file.flags.ignore_file_validate = True - file.flags.ignore_duplicate_entry_error = True - file.flags.ignore_links = True - file.set_folder_name() - try: - file.save() - except: - print(frappe.get_traceback()) - raise - - from frappe.utils.nestedset import rebuild_tree - rebuild_tree("File", "folder") - - # reset file size - for folder in frappe.db.sql("""select name from tabFile f1 where is_folder = 1 and - (select count(*) from tabFile f2 where f2.folder = f1.name and f2.is_folder = 1) = 0"""): - folder = frappe.get_doc("File", folder[0]) - folder.save() - - - diff --git a/frappe/patches/v6_11/__init__.py b/frappe/patches/v6_11/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_11/rename_field_in_email_account.py b/frappe/patches/v6_11/rename_field_in_email_account.py deleted file mode 100644 index 8e600cc2b9..0000000000 --- a/frappe/patches/v6_11/rename_field_in_email_account.py +++ /dev/null @@ -1,7 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc("email", "doctype", "email_account") - if frappe.db.has_column('Email Account', 'pop3_server'): - frappe.db.sql("update `tabEmail Account` set email_server = pop3_server") diff --git a/frappe/patches/v6_15/__init__.py b/frappe/patches/v6_15/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_15/remove_property_setter_for_previous_field.py b/frappe/patches/v6_15/remove_property_setter_for_previous_field.py deleted file mode 100644 index 9f0cd69489..0000000000 --- a/frappe/patches/v6_15/remove_property_setter_for_previous_field.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -import frappe, json -from frappe.utils import cstr - -def execute(): - # deprecated on 2016-03-09 - # using insert_after instead - return - - frappe.db.sql("""delete from `tabProperty Setter` where property='previous_field'""") - - all_custom_fields = frappe._dict() - for d in frappe.db.sql("""select name, dt, fieldname, insert_after from `tabCustom Field` - where insert_after is not null and insert_after != ''""", as_dict=1): - all_custom_fields.setdefault(d.dt, frappe._dict()).setdefault(d.fieldname, d.insert_after) - - for dt, custom_fields in all_custom_fields.items(): - _idx = [] - existing_ps = frappe.db.get_value("Property Setter", - {"doc_type": dt, "property": "_idx"}, ["name", "value", "creation"], as_dict=1) - - # if no existsing property setter, build based on meta - if not existing_ps: - _idx = get_sorted_fields(dt, custom_fields) - else: - _idx = json.loads(existing_ps.value) - - idx_needs_to_be_fixed = False - for fieldname, insert_after in custom_fields.items(): - # Delete existing property setter if field is not there - if fieldname not in _idx: - idx_needs_to_be_fixed = True - break - else: - previous_field = _idx[_idx.index(fieldname) - 1] - - if previous_field != insert_after and cstr(existing_ps.creation) >= "2015-12-28": - idx_needs_to_be_fixed = True - break - - if idx_needs_to_be_fixed: - frappe.delete_doc("Property Setter", existing_ps.name) - _idx = get_sorted_fields(dt, custom_fields) - - if _idx: - frappe.make_property_setter({ - "doctype":dt, - "doctype_or_field": "DocType", - "property": "_idx", - "value": json.dumps(_idx), - "property_type": "Text" - }, validate_fields_for_doctype=False) - - -def get_sorted_fields(doctype, custom_fields): - """sort on basis of insert_after""" - fields_dict = frappe.get_meta(doctype).get("fields") - - standard_fields_count = frappe.db.sql("""select count(name) from `tabDocField` - where parent=%s""", doctype)[0][0] - - newlist = [] - pending = [d.fieldname for d in fields_dict] - - maxloops = len(custom_fields) + 20 - while (pending and maxloops>0): - maxloops -= 1 - for fieldname in pending[:]: - if fieldname in custom_fields and len(newlist) >= standard_fields_count: - # field already added - for n in newlist: - if n==custom_fields.get(fieldname): - newlist.insert(newlist.index(n)+1, fieldname) - pending.remove(fieldname) - break - else: - newlist.append(fieldname) - pending.remove(fieldname) - - # recurring at end - if pending: - newlist += pending - - return newlist diff --git a/frappe/patches/v6_15/set_username.py b/frappe/patches/v6_15/set_username.py deleted file mode 100644 index ebf01763d0..0000000000 --- a/frappe/patches/v6_15/set_username.py +++ /dev/null @@ -1,16 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype("User") - - # give preference to System Users - users = frappe.db.sql_list("""select name from `tabUser` order by if(user_type='System User', 0, 1)""") - for name in users: - user = frappe.get_doc("User", name) - if user.username or not user.first_name: - continue - - username = user.suggest_username() - if username: - user.db_set("username", username, update_modified=False) diff --git a/frappe/patches/v6_16/__init__.py b/frappe/patches/v6_16/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_16/feed_doc_owner.py b/frappe/patches/v6_16/feed_doc_owner.py deleted file mode 100644 index b7e738b6d9..0000000000 --- a/frappe/patches/v6_16/feed_doc_owner.py +++ /dev/null @@ -1,31 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype("Communication") - - for doctype, name in frappe.db.sql("""select distinct reference_doctype, reference_name - from `tabCommunication` - where - (reference_doctype is not null and reference_doctype != '') - and (reference_name is not null and reference_name != '') - and (reference_owner is null or reference_owner = '') - for update"""): - - owner = frappe.db.get_value(doctype, name, "owner") - - if not owner: - continue - - frappe.db.sql("""update `tabCommunication` - set reference_owner=%(owner)s - where - reference_doctype=%(doctype)s - and reference_name=%(name)s - and (reference_owner is null or reference_owner = '')""".format(doctype=doctype), { - "doctype": doctype, - "name": name, - "owner": owner - }) - - frappe.db.commit() diff --git a/frappe/patches/v6_16/star_to_like.py b/frappe/patches/v6_16/star_to_like.py deleted file mode 100644 index f3fc6310d9..0000000000 --- a/frappe/patches/v6_16/star_to_like.py +++ /dev/null @@ -1,15 +0,0 @@ - -import frappe -from frappe.database.schema import add_column - -def execute(): - frappe.db.sql("""update `tabSingles` set field='_liked_by' where field='_starred_by'""") - frappe.db.commit() - - for table in frappe.db.get_tables(): - columns = [r[0] for r in frappe.db.sql("DESC `{0}`".format(table))] - if "_starred_by" in columns and '_liked_by' not in columns: - frappe.db.sql_ddl("""alter table `{0}` change `_starred_by` `_liked_by` Text """.format(table)) - - if not frappe.db.has_column("Communication", "_liked_by"): - add_column("Communication", "_liked_by", "Text") diff --git a/frappe/patches/v6_19/__init__.py b/frappe/patches/v6_19/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_19/comment_feed_communication.py b/frappe/patches/v6_19/comment_feed_communication.py deleted file mode 100644 index 64c5ad9c4c..0000000000 --- a/frappe/patches/v6_19/comment_feed_communication.py +++ /dev/null @@ -1,307 +0,0 @@ - -import frappe -from frappe import _ -from frappe.model.rename_doc import get_link_fields -from frappe.model.dynamic_links import dynamic_link_queries -from frappe.permissions import reset_perms - -def execute(): - # comments stay comments in v12 - return - - frappe.reload_doctype("DocType") - frappe.reload_doctype("Communication") - reset_perms("Communication") - - migrate_comments() - frappe.delete_doc("DocType", "Comment") - # frappe.db.sql_ddl("drop table `tabComment`") - - migrate_feed() - frappe.delete_doc("DocType", "Feed") - # frappe.db.sql_ddl("drop table `tabFeed`") - - update_timeline_doc_for("Blogger") - -def migrate_comments(): - from_fields = "" - to_fields = "" - - if "reference_doctype" in frappe.db.get_table_columns("Comment"): - from_fields = "reference_doctype as link_doctype, reference_name as link_name," - to_fields = "link_doctype, link_name," - - # comments - frappe.db.sql("""insert ignore into `tabCommunication` ( - subject, - content, - sender, - sender_full_name, - comment_type, - communication_date, - reference_doctype, - reference_name, - {to_fields} - - name, - user, - owner, - creation, - modified_by, - modified, - status, - sent_or_received, - communication_type, - seen - ) - select - substring(comment, 1, 100) as subject, - comment as content, - comment_by as sender, - comment_by_fullname as sender_full_name, - comment_type, - ifnull(timestamp(comment_date, comment_time), creation) as communication_date, - comment_doctype as reference_doctype, - comment_docname as reference_name, - {from_fields} - - name, - owner as user, - owner, - creation, - modified_by, - modified, - 'Linked' as status, - 'Sent' as sent_or_received, - 'Comment' as communication_type, - 1 as seen - from `tabComment` where comment_doctype is not null and comment_doctype not in ('Message', 'My Company')""" - .format(to_fields=to_fields, from_fields=from_fields)) - - # chat and assignment notifications - frappe.db.sql("""insert ignore into `tabCommunication` ( - subject, - content, - sender, - sender_full_name, - comment_type, - communication_date, - reference_doctype, - reference_name, - {to_fields} - - name, - user, - owner, - creation, - modified_by, - modified, - status, - sent_or_received, - communication_type, - seen - ) - select - case - when parenttype='Assignment' then %(assignment)s - else substring(comment, 1, 100) - end - as subject, - comment as content, - comment_by as sender, - comment_by_fullname as sender_full_name, - comment_type, - ifnull(timestamp(comment_date, comment_time), creation) as communication_date, - 'User' as reference_doctype, - comment_docname as reference_name, - {from_fields} - - name, - owner as user, - owner, - creation, - modified_by, - modified, - 'Linked' as status, - 'Sent' as sent_or_received, - case - when parenttype='Assignment' then 'Notification' - else 'Chat' - end - as communication_type, - 1 as seen - from `tabComment` where comment_doctype in ('Message', 'My Company')""" - .format(to_fields=to_fields, from_fields=from_fields), {"assignment": _("Assignment")}) - -def migrate_feed(): - # migrate delete feed - for doctype in frappe.db.sql("""select distinct doc_type from `tabFeed` where subject=%(deleted)s""", {"deleted": _("Deleted")}): - frappe.db.sql("""insert ignore into `tabCommunication` ( - subject, - sender, - sender_full_name, - comment_type, - communication_date, - reference_doctype, - - name, - user, - owner, - creation, - modified_by, - modified, - status, - sent_or_received, - communication_type, - seen - ) - select - concat_ws(" ", %(_doctype)s, doc_name) as subject, - owner as sender, - full_name as sender_full_name, - 'Deleted' as comment_type, - creation as communication_date, - doc_type as reference_doctype, - - name, - owner as user, - owner, - creation, - modified_by, - modified, - 'Linked' as status, - 'Sent' as sent_or_received, - 'Comment' as communication_type, - 1 as seen - from `tabFeed` where subject=%(deleted)s and doc_type=%(doctype)s""", { - "deleted": _("Deleted"), - "doctype": doctype, - "_doctype": _(doctype) - }) - - # migrate feed type login or empty - frappe.db.sql("""insert ignore into `tabCommunication` ( - subject, - sender, - sender_full_name, - comment_type, - communication_date, - reference_doctype, - reference_name, - - name, - user, - owner, - creation, - modified_by, - modified, - status, - sent_or_received, - communication_type, - seen - ) - select - subject, - owner as sender, - full_name as sender_full_name, - case - when feed_type='Login' then 'Info' - else 'Updated' - end as comment_type, - creation as communication_date, - doc_type as reference_doctype, - doc_name as reference_name, - - name, - owner as user, - owner, - creation, - modified_by, - modified, - 'Linked' as status, - 'Sent' as sent_or_received, - 'Comment' as communication_type, - 1 as seen - from `tabFeed` where (feed_type in ('Login', '') or feed_type is null)""") - -def update_timeline_doc_for(timeline_doctype): - """NOTE: This method may be used by other apps for patching. It also has COMMIT after each update.""" - - # find linked doctypes - # link fields - update_for_linked_docs(timeline_doctype) - - # dynamic link fields - update_for_dynamically_linked_docs(timeline_doctype) - -def update_for_linked_docs(timeline_doctype): - for df in get_link_fields(timeline_doctype): - if df.issingle: - continue - - reference_doctype = df.parent - - if not is_valid_timeline_doctype(reference_doctype, timeline_doctype): - continue - - for doc in frappe.get_all(reference_doctype, fields=["name", df.fieldname]): - timeline_name = doc.get(df.fieldname) - update_communication(timeline_doctype, timeline_name, reference_doctype, doc.name) - -def update_for_dynamically_linked_docs(timeline_doctype): - dynamic_link_fields = [] - for query in dynamic_link_queries: - for df in frappe.db.sql(query, as_dict=True): - dynamic_link_fields.append(df) - - for df in dynamic_link_fields: - reference_doctype = df.parent - - if not is_valid_timeline_doctype(reference_doctype, timeline_doctype): - continue - - try: - docs = frappe.get_all(reference_doctype, fields=["name", df.fieldname], - filters={ df.options: timeline_doctype }) - except frappe.db.SQLError as e: - if frappe.db.is_table_missing(e): - # single - continue - else: - raise - - for doc in docs: - timeline_name = doc.get(df.fieldname) - update_communication(timeline_doctype, timeline_name, reference_doctype, doc.name) - -def update_communication(timeline_doctype, timeline_name, reference_doctype, reference_name): - if not timeline_name: - return - - frappe.db.sql("""update `tabCommunication` set timeline_doctype=%(timeline_doctype)s, timeline_name=%(timeline_name)s - where (reference_doctype=%(reference_doctype)s and reference_name=%(reference_name)s) - and (timeline_doctype is null or timeline_doctype='') - and (timeline_name is null or timeline_name='')""", { - "timeline_doctype": timeline_doctype, - "timeline_name": timeline_name, - "reference_doctype": reference_doctype, - "reference_name": reference_name - }) - - frappe.db.commit() - -def is_valid_timeline_doctype(reference_doctype, timeline_doctype): - # for reloading timeline_field - frappe.reload_doctype(reference_doctype) - - # make sure the timeline field's doctype is same as timeline doctype - meta = frappe.get_meta(reference_doctype) - if not meta.timeline_field: - return False - - doctype = meta.get_link_doctype(meta.timeline_field) - if doctype != timeline_doctype: - return False - - - return True diff --git a/frappe/patches/v6_2/__init__.py b/frappe/patches/v6_2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_2/ignore_user_permissions_if_missing.py b/frappe/patches/v6_2/ignore_user_permissions_if_missing.py deleted file mode 100644 index e216dc36b6..0000000000 --- a/frappe/patches/v6_2/ignore_user_permissions_if_missing.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype("System Settings") - system_settings = frappe.get_doc("System Settings") - system_settings.flags.ignore_mandatory = 1 - system_settings.save() diff --git a/frappe/patches/v6_2/rename_backup_manager.py b/frappe/patches/v6_2/rename_backup_manager.py deleted file mode 100644 index df2fa72c05..0000000000 --- a/frappe/patches/v6_2/rename_backup_manager.py +++ /dev/null @@ -1,20 +0,0 @@ - -import frappe - -def execute(): - unset = False - frappe.reload_doc("integrations", "doctype", "dropbox_backup") - - dropbox_backup = frappe.get_doc("Dropbox Backup", "Dropbox Backup") - for df in dropbox_backup.meta.fields: - value = frappe.db.get_single_value("Backup Manager", df.fieldname) - if value: - if df.fieldname=="upload_backups_to_dropbox" and value=="Never": - value = "Daily" - unset = True - dropbox_backup.set(df.fieldname, value) - - if unset: - dropbox_backup.set("send_backups_to_dropbox", 0) - - dropbox_backup.save() diff --git a/frappe/patches/v6_20x/__init__.py b/frappe/patches/v6_20x/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_20x/remove_roles_from_website_user.py b/frappe/patches/v6_20x/remove_roles_from_website_user.py deleted file mode 100644 index 19009ff455..0000000000 --- a/frappe/patches/v6_20x/remove_roles_from_website_user.py +++ /dev/null @@ -1,11 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "user_email") - frappe.reload_doc("core", "doctype", "user") - for user_name in frappe.get_all('User', filters={'user_type': 'Website User'}): - user = frappe.get_doc('User', user_name) - if user.roles: - user.roles = [] - user.save() diff --git a/frappe/patches/v6_20x/set_allow_draft_for_print.py b/frappe/patches/v6_20x/set_allow_draft_for_print.py deleted file mode 100644 index 0b604567ec..0000000000 --- a/frappe/patches/v6_20x/set_allow_draft_for_print.py +++ /dev/null @@ -1,5 +0,0 @@ - -import frappe - -def execute(): - frappe.db.set_value("Print Settings", "Print Settings", "allow_print_for_draft", 1) \ No newline at end of file diff --git a/frappe/patches/v6_20x/update_insert_after.py b/frappe/patches/v6_20x/update_insert_after.py deleted file mode 100644 index 37820b2437..0000000000 --- a/frappe/patches/v6_20x/update_insert_after.py +++ /dev/null @@ -1,27 +0,0 @@ - -import frappe, json - -def execute(): - for ps in frappe.get_all('Property Setter', filters={'property': '_idx'}, - fields = ['doc_type', 'value']): - custom_fields = frappe.get_all('Custom Field', - filters = {'dt': ps.doc_type}, fields=['name', 'fieldname']) - - if custom_fields: - _idx = json.loads(ps.value) - - for custom_field in custom_fields: - if custom_field.fieldname in _idx: - custom_field_idx = _idx.index(custom_field.fieldname) - if custom_field_idx == 0: - prev_fieldname = "" - - else: - prev_fieldname = _idx[custom_field_idx - 1] - - else: - prev_fieldname = _idx[-1] - custom_field_idx = len(_idx) - - frappe.db.set_value('Custom Field', custom_field.name, 'insert_after', prev_fieldname) - frappe.db.set_value('Custom Field', custom_field.name, 'idx', custom_field_idx) diff --git a/frappe/patches/v6_21/__init__.py b/frappe/patches/v6_21/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_21/print_settings_repeat_header_footer.py b/frappe/patches/v6_21/print_settings_repeat_header_footer.py deleted file mode 100644 index 0919c35903..0000000000 --- a/frappe/patches/v6_21/print_settings_repeat_header_footer.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype('Print Settings') - frappe.db.set_value('Print Settings', 'Print Settings', 'repeat_header_footer', 1) diff --git a/frappe/patches/v6_24/__init__.py b/frappe/patches/v6_24/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_24/set_language_as_code.py b/frappe/patches/v6_24/set_language_as_code.py deleted file mode 100644 index 6f862ede2e..0000000000 --- a/frappe/patches/v6_24/set_language_as_code.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -from frappe.translate import get_lang_dict - -# migrate language from name to code -def execute(): - return diff --git a/frappe/patches/v6_4/__init__.py b/frappe/patches/v6_4/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_4/reduce_varchar_length.py b/frappe/patches/v6_4/reduce_varchar_length.py deleted file mode 100644 index 7edde55778..0000000000 --- a/frappe/patches/v6_4/reduce_varchar_length.py +++ /dev/null @@ -1,36 +0,0 @@ -import frappe - -def execute(): - for doctype in frappe.get_all("DocType", filters={"issingle": 0}): - doctype = doctype.name - if not frappe.db.table_exists(doctype): - continue - - for column in frappe.db.sql("desc `tab{doctype}`".format(doctype=doctype), as_dict=True): - fieldname = column["Field"] - column_type = column["Type"] - - if not column_type.startswith("varchar"): - continue - - max_length = frappe.db.sql("""select max(char_length(`{fieldname}`)) from `tab{doctype}`"""\ - .format(fieldname=fieldname, doctype=doctype)) - - max_length = max_length[0][0] if max_length else None - - if max_length and 140 < max_length <= 255: - print( - "setting length of '{fieldname}' in '{doctype}' as {length}".format( - fieldname=fieldname, doctype=doctype, length=max_length) - ) - - # create property setter for length - frappe.make_property_setter({ - "doctype": doctype, - "fieldname": fieldname, - "property": "length", - "value": max_length, - "property_type": "Int" - }) - - frappe.clear_cache(doctype=doctype) diff --git a/frappe/patches/v6_4/rename_bengali_language.py b/frappe/patches/v6_4/rename_bengali_language.py deleted file mode 100644 index f872dea1b9..0000000000 --- a/frappe/patches/v6_4/rename_bengali_language.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -import frappe -from frappe.translate import rename_language - -def execute(): - rename_language("বাঙালি", "বাংলা") \ No newline at end of file diff --git a/frappe/patches/v6_6/__init__.py b/frappe/patches/v6_6/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_6/fix_file_url.py b/frappe/patches/v6_6/fix_file_url.py deleted file mode 100644 index 48e292f4d4..0000000000 --- a/frappe/patches/v6_6/fix_file_url.py +++ /dev/null @@ -1,36 +0,0 @@ - -import frappe -from frappe.model.meta import is_single - -def execute(): - """Fix old style file urls that start with files/""" - fix_file_urls() - fix_attach_field_urls() - -def fix_file_urls(): - for file in frappe.db.sql_list("""select name from `tabFile` where file_url like 'files/%'"""): - file = frappe.get_doc("File", file) - file.db_set("file_url", "/" + file.file_url, update_modified=False) - try: - file.validate_file() - file.db_set("file_name", file.file_name, update_modified=False) - if not file.content_hash: - file.generate_content_hash() - file.db_set("content_hash", file.content_hash, update_modified=False) - - except IOError: - pass - -def fix_attach_field_urls(): - # taken from an old patch - attach_fields = (frappe.db.sql("""select parent, fieldname from `tabDocField` where fieldtype in ('Attach', 'Attach Image')""") + - frappe.db.sql("""select dt, fieldname from `tabCustom Field` where fieldtype in ('Attach', 'Attach Image')""")) - - for doctype, fieldname in attach_fields: - if is_single(doctype): - frappe.db.sql("""update `tabSingles` set value=concat("/", `value`) - where doctype=%(doctype)s and field=%(fieldname)s - and value like 'files/%%'""", {"doctype": doctype, "fieldname": fieldname}) - else: - frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=concat("/", `{fieldname}`) - where `{fieldname}` like 'files/%'""".format(doctype=doctype, fieldname=fieldname)) diff --git a/frappe/patches/v6_6/rename_slovak_language.py b/frappe/patches/v6_6/rename_slovak_language.py deleted file mode 100644 index 198949e79c..0000000000 --- a/frappe/patches/v6_6/rename_slovak_language.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -import frappe -from frappe.translate import rename_language - -def execute(): - rename_language("slovenčina", "slovenčina (Slovak)") diff --git a/frappe/patches/v6_6/user_last_active.py b/frappe/patches/v6_6/user_last_active.py deleted file mode 100644 index b9f63fa45e..0000000000 --- a/frappe/patches/v6_6/user_last_active.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype("User") - frappe.db.sql("update `tabUser` set last_active=last_login") diff --git a/frappe/patches/v6_9/__init__.py b/frappe/patches/v6_9/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v6_9/int_float_not_null.py b/frappe/patches/v6_9/int_float_not_null.py deleted file mode 100644 index c414d6b583..0000000000 --- a/frappe/patches/v6_9/int_float_not_null.py +++ /dev/null @@ -1,30 +0,0 @@ - -import frappe -from frappe.utils import cint, flt - -def execute(): - for doctype in frappe.get_all("DocType", filters={"issingle": 0}): - doctype = doctype.name - meta = frappe.get_meta(doctype) - - for column in frappe.db.sql("desc `tab{doctype}`".format(doctype=doctype), as_dict=True): - fieldname = column["Field"] - column_type = column["Type"] - - if not (column_type.startswith("int") or column_type.startswith("decimal")): - continue - - frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=0 where `{fieldname}` is null"""\ - .format(doctype=doctype, fieldname=fieldname)) - - # alter table - if column["Null"]=='YES': - if not meta.get_field(fieldname): - continue - - default = cint(column["Default"]) if column_type.startswith("int") else flt(column["Default"]) - frappe.db.sql_ddl("""alter table `tab{doctype}` - change `{fieldname}` `{fieldname}` {column_type} not null default '{default}'""".format( - doctype=doctype, fieldname=fieldname, column_type=column_type, default=default)) - - diff --git a/frappe/patches/v6_9/rename_burmese_language.py b/frappe/patches/v6_9/rename_burmese_language.py deleted file mode 100644 index 5e1333077e..0000000000 --- a/frappe/patches/v6_9/rename_burmese_language.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -import frappe -from frappe.translate import rename_language - -def execute(): - rename_language("Melayu", "မြန်မာ") diff --git a/frappe/patches/v7_0/__init__.py b/frappe/patches/v7_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v7_0/add_communication_in_doc.py b/frappe/patches/v7_0/add_communication_in_doc.py deleted file mode 100644 index 8be229fe3a..0000000000 --- a/frappe/patches/v7_0/add_communication_in_doc.py +++ /dev/null @@ -1,14 +0,0 @@ - -import frappe - -from frappe.core.doctype.comment.comment import update_comment_in_doc - -def execute(): - for d in frappe.db.get_all("Communication", - fields = ['name', 'reference_doctype', 'reference_name', 'SUBSTRING(content,1,102)', 'communication_type'], - filters = {"reference_name":None,"reference_doctype":None,'communication_type': 'Communication'}): - - try: - update_comment_in_doc(d) - except frappe.ImplicitCommitError: - pass diff --git a/frappe/patches/v7_0/cleanup_list_settings.py b/frappe/patches/v7_0/cleanup_list_settings.py deleted file mode 100644 index 9fe2e71ed1..0000000000 --- a/frappe/patches/v7_0/cleanup_list_settings.py +++ /dev/null @@ -1,20 +0,0 @@ - -import frappe, json - -def execute(): - if frappe.db.table_exists("__ListSettings"): - list_settings = frappe.db.sql("select user, doctype, data from __ListSettings", as_dict=1) - for ls in list_settings: - if ls and ls.data: - data = json.loads(ls.data) - if "fields" not in data: - continue - fields = data["fields"] - for field in fields: - if "name as" in field: - fields.remove(field) - data["fields"] = fields - - frappe.db.sql("update __ListSettings set data = %s where user=%s and doctype=%s", - (json.dumps(data), ls.user, ls.doctype)) - diff --git a/frappe/patches/v7_0/create_private_file_folder.py b/frappe/patches/v7_0/create_private_file_folder.py deleted file mode 100644 index e89beb5d0f..0000000000 --- a/frappe/patches/v7_0/create_private_file_folder.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe, os - -def execute(): - if not os.path.exists(os.path.join(frappe.local.site_path, 'private', 'files')): - frappe.create_folder(os.path.join(frappe.local.site_path, 'private', 'files')) \ No newline at end of file diff --git a/frappe/patches/v7_0/re_route.py b/frappe/patches/v7_0/re_route.py deleted file mode 100644 index 8a4daaea86..0000000000 --- a/frappe/patches/v7_0/re_route.py +++ /dev/null @@ -1,23 +0,0 @@ - -import frappe -from frappe.model.base_document import get_controller - -def execute(): - update_routes(['Blog Post', 'Blog Category', 'Web Page']) - -def update_routes(doctypes): - """Patch old routing system""" - for d in doctypes: - frappe.reload_doctype(d) - c = get_controller(d) - - condition = '' - if c.website.condition_field: - condition = 'where {0}=1'.format(c.website.condition_field) - - try: - frappe.db.sql("""update ignore `tab{0}` set route = concat(ifnull(parent_website_route, ""), - if(ifnull(parent_website_route, "")="", "", "/"), page_name) {1}""".format(d, condition)) - - except Exception as e: - if not frappe.db.is_missing_column(e): raise diff --git a/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py b/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py deleted file mode 100644 index 42f2dfe4c2..0000000000 --- a/frappe/patches/v7_0/rename_bulk_email_to_email_queue.py +++ /dev/null @@ -1,5 +0,0 @@ - -import frappe - -def execute(): - frappe.rename_doc('DocType', 'Bulk Email', 'Email Queue') \ No newline at end of file diff --git a/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py b/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py deleted file mode 100644 index 5e40d9df35..0000000000 --- a/frappe/patches/v7_0/rename_newsletter_list_to_email_group.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - frappe.rename_doc('DocType', 'Newsletter List', 'Email Group') - frappe.rename_doc('DocType', 'Newsletter List Subscriber', 'Email Group Member') \ No newline at end of file diff --git a/frappe/patches/v7_0/set_email_group.py b/frappe/patches/v7_0/set_email_group.py deleted file mode 100644 index 251e9a27b6..0000000000 --- a/frappe/patches/v7_0/set_email_group.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - frappe.reload_doc("email", "doctype", "email_group_member") - if "newsletter_list" in frappe.db.get_table_columns("Email Group Member"): - frappe.db.sql("""update `tabEmail Group Member` set email_group = newsletter_list - where email_group is null or email_group = ''""") \ No newline at end of file diff --git a/frappe/patches/v7_0/set_user_fullname.py b/frappe/patches/v7_0/set_user_fullname.py deleted file mode 100644 index e69c180c27..0000000000 --- a/frappe/patches/v7_0/set_user_fullname.py +++ /dev/null @@ -1,10 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc("Core", "DocType", "User") - - for user in frappe.db.get_all('User'): - user = frappe.get_doc('User', user.name) - user.set_full_name() - user.db_set('full_name', user.full_name, update_modified = False) \ No newline at end of file diff --git a/frappe/patches/v7_0/update_auth.py b/frappe/patches/v7_0/update_auth.py deleted file mode 100644 index 098081563f..0000000000 --- a/frappe/patches/v7_0/update_auth.py +++ /dev/null @@ -1,42 +0,0 @@ - -import frappe -from frappe.utils.password import create_auth_table, set_encrypted_password - -def execute(): - if '__OldAuth' not in frappe.db.get_tables(): - frappe.db.sql_ddl('''alter table `__Auth` rename `__OldAuth`''') - - create_auth_table() - - # user passwords - frappe.db.sql('''insert ignore into `__Auth` (doctype, name, fieldname, `password`) - (select 'User', `name`, 'password', `password` from `__OldAuth`)''') - - frappe.db.commit() - - # other password fields - for doctype in frappe.db.sql_list('''select distinct parent from `tabDocField` - where fieldtype="Password" and parent != "User"'''): - - frappe.reload_doctype(doctype) - meta = frappe.get_meta(doctype) - - for df in meta.get('fields', {'fieldtype': 'Password'}): - if meta.issingle: - password = frappe.db.get_value(doctype, doctype, df.fieldname) - if password: - set_encrypted_password(doctype, doctype, password, fieldname=df.fieldname) - frappe.db.set_value(doctype, doctype, df.fieldname, '*'*len(password)) - - else: - for d in frappe.db.sql('''select name, `{fieldname}` from `tab{doctype}` - where `{fieldname}` is not null'''.format(fieldname=df.fieldname, doctype=doctype), as_dict=True): - - set_encrypted_password(doctype, d.name, d.get(df.fieldname), fieldname=df.fieldname) - - frappe.db.sql('''update `tab{doctype}` set `{fieldname}`=repeat("*", char_length(`{fieldname}`))''' - .format(doctype=doctype, fieldname=df.fieldname)) - - frappe.db.commit() - - frappe.db.sql_ddl('''drop table `__OldAuth`''') diff --git a/frappe/patches/v7_0/update_report_builder_json.py b/frappe/patches/v7_0/update_report_builder_json.py deleted file mode 100644 index 01a6126de7..0000000000 --- a/frappe/patches/v7_0/update_report_builder_json.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - for report in frappe.db.sql_list(""" select name from `tabReport` where report_type = 'Report Builder' - and is_standard = 'No' and `json` != '' and `json` is not null """): - doc = frappe.get_doc("Report", report) - doc.update_report_json() - doc.db_set("json", doc.json, update_modified=False) \ No newline at end of file diff --git a/frappe/patches/v7_0/update_send_after_in_bulk_email.py b/frappe/patches/v7_0/update_send_after_in_bulk_email.py deleted file mode 100644 index b9da83eaab..0000000000 --- a/frappe/patches/v7_0/update_send_after_in_bulk_email.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe -from frappe.utils import now_datetime - -def execute(): - frappe.db.sql('update `tabEmail Queue` set send_after=%s where send_after is null', now_datetime()) \ No newline at end of file diff --git a/frappe/patches/v7_1/__init__.py b/frappe/patches/v7_1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py b/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py deleted file mode 100644 index 6ab9340845..0000000000 --- a/frappe/patches/v7_1/disabled_print_settings_for_custom_print_format.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - frappe.reload_doctype('Print Format') - frappe.db.sql(""" - update - `tabPrint Format` - set - align_labels_right = 0, line_breaks = 0, show_section_headings = 0 - where - custom_format = 1 - """) diff --git a/frappe/patches/v7_1/refactor_integration_broker.py b/frappe/patches/v7_1/refactor_integration_broker.py deleted file mode 100644 index 05ccae5d46..0000000000 --- a/frappe/patches/v7_1/refactor_integration_broker.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe -import json - -def execute(): - for doctype_name in ["Razorpay Log", "Razorpay Payment", "Razorpay Settings"]: - delete_doc("DocType", doctype_name) - - reload_doctypes() - setup_services() - -def delete_doc(doctype, doctype_name): - frappe.delete_doc(doctype, doctype_name) - -def reload_doctypes(): - for doctype in ("razorpay_settings", "paypal_settings", "dropbox_settings", "ldap_settings"): - frappe.reload_doc("integrations", "doctype", doctype) - -def setup_services(): - for service in [{"old_name": "Razorpay", "new_name": "Razorpay"}, - {"old_name": "PayPal", "new_name": "PayPal"}, - {"old_name": "Dropbox Integration", "new_name": "Dropbox"}, - {"old_name": "LDAP Auth", "new_name": "LDAP"}]: - - try: - service_doc = frappe.get_doc("Integration Service", service["old_name"]) - settings = json.loads(service_doc.custom_settings_json) - - service_settings = frappe.new_doc("{0} Settings".format(service["new_name"])) - service_settings.update(settings) - - service_settings.flags.ignore_mandatory = True - service_settings.save(ignore_permissions=True) - - if service["old_name"] in ["Dropbox Integration", "LDAP Auth"]: - delete_doc("Integration Service", service["old_name"]) - - new_service_doc = frappe.get_doc({ - "doctype": "Integration Service", - "service": service["new_name"], - "enabled": 1 - }) - - new_service_doc.flags.ignore_mandatory = True - new_service_doc.save(ignore_permissions=True) - - except Exception: - pass diff --git a/frappe/patches/v7_1/rename_chinese_language_codes.py b/frappe/patches/v7_1/rename_chinese_language_codes.py deleted file mode 100644 index 91ed73ccae..0000000000 --- a/frappe/patches/v7_1/rename_chinese_language_codes.py +++ /dev/null @@ -1,11 +0,0 @@ - -import frappe - -def execute(): - frappe.rename_doc('Language', 'zh-cn', 'zh', force=True, - merge=True if frappe.db.exists('Language', 'zh') else False) - if frappe.db.get_value('Language', 'zh-tw') == 'zh-tw': - frappe.rename_doc('Language', 'zh-tw', 'zh-TW', force=True) - - frappe.db.set_value('Language', 'zh', 'language_code', 'zh') - frappe.db.set_value('Language', 'zh-TW', 'language_code', 'zh-TW') \ No newline at end of file diff --git a/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py b/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py deleted file mode 100644 index c0c9e03565..0000000000 --- a/frappe/patches/v7_1/rename_scheduler_log_to_error_log.py +++ /dev/null @@ -1,11 +0,0 @@ - -import frappe - -def execute(): - if not 'tabError Log' in frappe.db.get_tables(): - frappe.rename_doc('DocType', 'Scheduler Log', 'Error Log') - frappe.db.sql("""delete from `tabError Log` where datediff(curdate(), creation) > 30""") - frappe.db.commit() - frappe.db.sql('alter table `tabError Log` change column name name varchar(140)') - frappe.db.sql('alter table `tabError Log` change column parent parent varchar(140)') - frappe.db.sql('alter table `tabError Log` engine=MyISAM') diff --git a/frappe/patches/v7_1/set_backup_limit.py b/frappe/patches/v7_1/set_backup_limit.py deleted file mode 100644 index ce502393b2..0000000000 --- a/frappe/patches/v7_1/set_backup_limit.py +++ /dev/null @@ -1,10 +0,0 @@ - -from frappe.utils import cint -import frappe - -def execute(): - frappe.reload_doctype('System Settings') - backup_limit = frappe.db.get_single_value('System Settings', 'backup_limit') - - if cint(backup_limit) == 0: - frappe.db.set_value('System Settings', 'System Settings', 'backup_limit', 3) diff --git a/frappe/patches/v7_1/setup_integration_services.py b/frappe/patches/v7_1/setup_integration_services.py deleted file mode 100644 index 9f4c8a3915..0000000000 --- a/frappe/patches/v7_1/setup_integration_services.py +++ /dev/null @@ -1,118 +0,0 @@ - -import frappe -from frappe.exceptions import DataError -from frappe.utils.password import get_decrypted_password -from frappe.utils import cstr -import os - -app_list = [ - {"app_name": "razorpay_integration", "service_name": "Razorpay", "doctype": "Razorpay Settings", "remove": True}, - {"app_name": "paypal_integration", "service_name": "PayPal", "doctype": "PayPal Settings", "remove": True}, - {"app_name": "frappe", "service_name": "Dropbox", "doctype": "Dropbox Backup", "remove": False} -] - -def execute(): - installed_apps = frappe.get_installed_apps() - - for app_details in app_list: - if app_details["app_name"] in installed_apps: - settings = get_app_settings(app_details) - if app_details["remove"]: - uninstall_app(app_details["app_name"]) - - try: - setup_integration_service(app_details, settings) - except DataError: - pass - - frappe.delete_doc("DocType", "Dropbox Backup") - -def setup_integration_service(app_details, settings=None): - if not settings: - return - - setup_service_settings(app_details["service_name"], settings) - - doc_path = frappe.get_app_path("frappe", "integration_broker", "doctype", - "integration_service", "integration_service.json") - - if not os.path.exists(doc_path): - return - - frappe.reload_doc("integration_broker", "doctype", "integration_service") - - if frappe.db.exists("Integration Service", app_details["service_name"]): - integration_service = frappe.get_doc("Integration Service", app_details["service_name"]) - else: - integration_service = frappe.new_doc("Integration Service") - integration_service.service = app_details["service_name"] - - integration_service.enabled = 1 - integration_service.flags.ignore_mandatory = True - integration_service.save(ignore_permissions=True) - -def get_app_settings(app_details): - parameters = {} - doctype = docname = app_details["doctype"] - - app_settings = get_parameters(app_details) - if app_settings: - settings = app_settings["settings"] - frappe.reload_doc("integrations", "doctype", "{0}_settings".format(app_details["service_name"].lower())) - controller = frappe.get_meta("{0} Settings".format(app_details["service_name"])) - - for d in controller.fields: - if settings.get(d.fieldname): - if ''.join(set(cstr(settings.get(d.fieldname)))) == '*': - setattr(settings, d.fieldname, get_decrypted_password(doctype, docname, d.fieldname, raise_exception=True)) - - parameters.update({d.fieldname : settings.get(d.fieldname)}) - - return parameters - -def uninstall_app(app_name): - from frappe.installer import remove_from_installed_apps - remove_from_installed_apps(app_name) - -def get_parameters(app_details): - if app_details["service_name"] == "Razorpay": - return {"settings": frappe.get_doc(app_details["doctype"])} - - elif app_details["service_name"] == "PayPal": - if frappe.conf.paypal_username and frappe.conf.paypal_password and frappe.conf.paypal_signature: - return { - "settings": { - "api_username": frappe.conf.paypal_username, - "api_password": frappe.conf.paypal_password, - "signature": frappe.conf.paypal_signature - } - } - else: - return {"settings": frappe.get_doc(app_details["doctype"])} - - elif app_details["service_name"] == "Dropbox": - doc = frappe.db.get_value(app_details["doctype"], None, - ["dropbox_access_key", "dropbox_access_secret", "upload_backups_to_dropbox"], as_dict=1) - - if not doc: - return - - if not (frappe.conf.dropbox_access_key and frappe.conf.dropbox_secret_key): - return - - return { - "settings": { - "app_access_key": frappe.conf.dropbox_access_key, - "app_secret_key": frappe.conf.dropbox_secret_key, - "dropbox_access_key": doc.dropbox_access_key, - "dropbox_access_secret": doc.dropbox_access_secret, - "backup_frequency": doc.upload_backups_to_dropbox, - "enabled": doc.send_backups_to_dropbox - } - } - -def setup_service_settings(service_name, settings): - service_doc = frappe.get_doc("{0} Settings".format(service_name)) - service_doc.update(settings) - service_doc.flags.ignore_mandatory = True - service_doc.save(ignore_permissions=True) \ No newline at end of file diff --git a/frappe/patches/v7_1/sync_language_doctype.py b/frappe/patches/v7_1/sync_language_doctype.py deleted file mode 100644 index a5e9ad1cb1..0000000000 --- a/frappe/patches/v7_1/sync_language_doctype.py +++ /dev/null @@ -1,22 +0,0 @@ - -import frappe -from frappe.translate import get_lang_dict - -def execute(): - frappe.reload_doc('core', 'doctype', 'language') - - from frappe.core.doctype.language.language import sync_languages - sync_languages() - - # move language from old style to new style for old accounts - # i.e. from "english" to "en" - - lang_dict = get_lang_dict() - language = frappe.db.get_value('System Settings', None, 'language') - if language: - frappe.db.set_value('System Settings', None, 'language', lang_dict.get('language') or 'en') - - for user in frappe.get_all('User', fields=['name', 'language']): - if user.language: - frappe.db.set_value('User', user.name, 'language', - lang_dict.get('language') or 'en', update_modified=False) diff --git a/frappe/patches/v7_2/__init__.py b/frappe/patches/v7_2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v7_2/fix_email_queue_recipient.py b/frappe/patches/v7_2/fix_email_queue_recipient.py deleted file mode 100644 index 021397031b..0000000000 --- a/frappe/patches/v7_2/fix_email_queue_recipient.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc('email', 'doctype', 'email_queue_recipient') - frappe.db.sql('update `tabEmail Queue Recipient` set parenttype="recipients"') \ No newline at end of file diff --git a/frappe/patches/v7_2/merge_knowledge_base.py b/frappe/patches/v7_2/merge_knowledge_base.py deleted file mode 100644 index 04e6c16213..0000000000 --- a/frappe/patches/v7_2/merge_knowledge_base.py +++ /dev/null @@ -1,24 +0,0 @@ - -import frappe - -from frappe.patches.v7_0.re_route import update_routes -from frappe.installer import remove_from_installed_apps - -def execute(): - if 'knowledge_base' in frappe.get_installed_apps(): - frappe.reload_doc('website', 'doctype', 'help_category') - frappe.reload_doc('website', 'doctype', 'help_article') - update_routes(['Help Category', 'Help Article']) - remove_from_installed_apps('knowledge_base') - - # remove module def - if frappe.db.exists('Module Def', 'Knowledge Base'): - frappe.delete_doc('Module Def', 'Knowledge Base') - - # set missing routes - for doctype in ('Help Category', 'Help Article'): - for d in frappe.get_all(doctype, fields=['name', 'route']): - if not d.route: - doc = frappe.get_doc(doctype, d.name) - doc.set_route() - doc.db_update() \ No newline at end of file diff --git a/frappe/patches/v7_2/remove_in_filter.py b/frappe/patches/v7_2/remove_in_filter.py deleted file mode 100644 index 306879f996..0000000000 --- a/frappe/patches/v7_2/remove_in_filter.py +++ /dev/null @@ -1,7 +0,0 @@ - -import frappe - -def execute(): - if frappe.db.has_column('DocField', 'in_filter'): - frappe.db.sql('alter table tabDocField drop column in_filter') - frappe.clear_cache(doctype="DocField") \ No newline at end of file diff --git a/frappe/patches/v7_2/set_doctype_engine.py b/frappe/patches/v7_2/set_doctype_engine.py deleted file mode 100644 index e0df9cff87..0000000000 --- a/frappe/patches/v7_2/set_doctype_engine.py +++ /dev/null @@ -1,7 +0,0 @@ - -import frappe - -def execute(): - for t in frappe.db.sql('show table status'): - if t[0].startswith('tab'): - frappe.db.sql('update tabDocType set engine=%s where name=%s', (t[1], t[0][3:])) \ No newline at end of file diff --git a/frappe/patches/v7_2/set_in_standard_filter_property.py b/frappe/patches/v7_2/set_in_standard_filter_property.py deleted file mode 100644 index 568f43d2aa..0000000000 --- a/frappe/patches/v7_2/set_in_standard_filter_property.py +++ /dev/null @@ -1,20 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc('custom', 'doctype', 'custom_field', force=True) - - try: - frappe.db.sql('update `tabCustom Field` set in_standard_filter = in_filter_dash') - except Exception as e: - if not frappe.db.is_missing_column(e): raise e - - for doctype in frappe.get_all("DocType", {"istable": 0, "issingle": 0, "custom": 0}): - try: - frappe.reload_doctype(doctype.name, force=True) - except KeyError: - pass - except frappe.db.DataError: - pass - except Exception: - pass diff --git a/frappe/patches/v7_2/setup_custom_perms.py b/frappe/patches/v7_2/setup_custom_perms.py deleted file mode 100644 index 1f46072782..0000000000 --- a/frappe/patches/v7_2/setup_custom_perms.py +++ /dev/null @@ -1,13 +0,0 @@ - -import frappe -from frappe.permissions import setup_custom_perms -from frappe.core.page.permission_manager.permission_manager import get_standard_permissions -from frappe.utils.reset_doc import setup_perms_for - -''' -Copy DocPerm to Custom DocPerm where permissions are set differently -''' - -def execute(): - for d in frappe.db.get_all('DocType', dict(istable=0, issingle=0, custom=0)): - setup_perms_for(d.name) diff --git a/frappe/patches/v7_2/setup_ldap_config.py b/frappe/patches/v7_2/setup_ldap_config.py deleted file mode 100644 index c9ad3e6714..0000000000 --- a/frappe/patches/v7_2/setup_ldap_config.py +++ /dev/null @@ -1,22 +0,0 @@ - -import frappe -from frappe.utils import cint - -def execute(): - frappe.reload_doc("integrations", "doctype", "ldap_settings") - - if not frappe.db.exists("DocType", "Integration Service"): - return - - if not frappe.db.exists("Integration Service", "LDAP"): - return - - if not cint(frappe.db.get_value("Integration Service", "LDAP", 'enabled')): - return - - import ldap - try: - ldap_settings = frappe.get_doc("LDAP Settings") - ldap_settings.save(ignore_permissions=True) - except ldap.LDAPError: - pass diff --git a/frappe/patches/v7_2/update_communications.py b/frappe/patches/v7_2/update_communications.py deleted file mode 100644 index 114e531324..0000000000 --- a/frappe/patches/v7_2/update_communications.py +++ /dev/null @@ -1,10 +0,0 @@ - -import frappe - -def execute(): - """ - in communication move feedback details to content - remove Guest None from sender full name - setup feedback request trigger's is_manual field - """ - return diff --git a/frappe/patches/v7_2/update_feedback_request.py b/frappe/patches/v7_2/update_feedback_request.py deleted file mode 100644 index 9bc656bf67..0000000000 --- a/frappe/patches/v7_2/update_feedback_request.py +++ /dev/null @@ -1,10 +0,0 @@ - -import frappe - -def execute(): - """ - rename feedback request documents, - update the feedback request and save the rating and communication - reference in Feedback Request document - """ - return diff --git a/frappe/patches/v8_0/__init__.py b/frappe/patches/v8_0/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v8_0/deprecate_integration_broker.py b/frappe/patches/v8_0/deprecate_integration_broker.py deleted file mode 100644 index 9aeee17837..0000000000 --- a/frappe/patches/v8_0/deprecate_integration_broker.py +++ /dev/null @@ -1,51 +0,0 @@ - -import frappe -from frappe.integrations.utils import create_payment_gateway - -def execute(): - setup_enabled_integrations() - - for doctype in ["integration_request", "oauth_authorization_code", "oauth_bearer_token", "oauth_client"]: - frappe.reload_doc('integrations', 'doctype', doctype) - - frappe.reload_doc("core", "doctype", "payment_gateway") - update_doctype_module() - create_payment_gateway_master_records() - - for doctype in ["Integration Service", "Integration Service Parameter"]: - frappe.delete_doc("DocType", doctype) - - if not frappe.db.get_value("DocType", {"module": "Integration Broker"}, "name"): - frappe.delete_doc("Module Def", "Integration Broker") - -def setup_enabled_integrations(): - if not frappe.db.exists("DocType", "Integration Service"): - return - - for service in frappe.get_all("Integration Service", - filters={"enabled": 1, "service": ('in', ("Dropbox", "LDAP"))}, fields=["name"]): - - doctype = "{0} Settings".format(service.name) - frappe.db.set_value(doctype, doctype, 'enabled', 1) - -def update_doctype_module(): - frappe.db.sql("""update tabDocType set module='Integrations' - where name in ('Integration Request', 'Oauth Authorization Code', - 'Oauth Bearer Token', 'Oauth Client') """) - - frappe.db.sql(""" update tabDocType set module='Core' where name = 'Payment Gateway'""") - -def create_payment_gateway_master_records(): - for payment_gateway in ["Razorpay", "PayPal"]: - doctype = "{0} Settings".format(payment_gateway) - doc = frappe.get_doc(doctype) - doc_meta = frappe.get_meta(doctype) - all_mandatory_fields_has_value = True - - for d in doc_meta.fields: - if d.reqd and not doc.get(d.fieldname): - all_mandatory_fields_has_value = False - break - - if all_mandatory_fields_has_value: - create_payment_gateway(payment_gateway) diff --git a/frappe/patches/v8_0/drop_in_dialog.py b/frappe/patches/v8_0/drop_in_dialog.py deleted file mode 100644 index 5022333d22..0000000000 --- a/frappe/patches/v8_0/drop_in_dialog.py +++ /dev/null @@ -1,7 +0,0 @@ - -import frappe - -def execute(): - if frappe.db.has_column('DocType', 'in_dialog'): - frappe.db.sql('alter table tabDocType drop column in_dialog') - frappe.clear_cache(doctype="DocType") \ No newline at end of file diff --git a/frappe/patches/v8_0/drop_is_custom_from_docperm.py b/frappe/patches/v8_0/drop_is_custom_from_docperm.py deleted file mode 100644 index 0f17bbef5c..0000000000 --- a/frappe/patches/v8_0/drop_is_custom_from_docperm.py +++ /dev/null @@ -1,8 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doctype('DocPerm') - if frappe.db.has_column('DocPerm', 'is_custom'): - frappe.db.commit() - frappe.db.sql('alter table `tabDocPerm` drop column is_custom') \ No newline at end of file diff --git a/frappe/patches/v8_0/drop_unwanted_indexes.py b/frappe/patches/v8_0/drop_unwanted_indexes.py deleted file mode 100644 index 655bce1a4b..0000000000 --- a/frappe/patches/v8_0/drop_unwanted_indexes.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt -# -*- coding: utf-8 -*- - -import frappe - -def execute(): - # communication - unwanted_indexes = ["communication_date_index", "message_id_index", "modified_index", - "creation_index", "reference_owner", "communication_date"] - - for k in unwanted_indexes: - try: - frappe.db.sql("drop index {0} on `tabCommunication`".format(k)) - except: - pass \ No newline at end of file diff --git a/frappe/patches/v8_0/install_new_build_system_requirements.py b/frappe/patches/v8_0/install_new_build_system_requirements.py deleted file mode 100644 index 75ccfa87cd..0000000000 --- a/frappe/patches/v8_0/install_new_build_system_requirements.py +++ /dev/null @@ -1,21 +0,0 @@ -from subprocess import Popen, call, PIPE - -def execute(): - # update nodejs version if brew exists - p = Popen(['which', 'brew'], stdout=PIPE, stderr=PIPE) - output, err = p.communicate() - if output: - call(['brew', 'upgrade', 'node']) - else: - print('Please update your NodeJS version') - - call([ - 'npm', 'install', - 'babel-core', - 'less', - 'chokidar', - 'babel-preset-es2015', - 'babel-preset-es2016', - 'babel-preset-es2017', - 'babel-preset-babili' - ]) \ No newline at end of file diff --git a/frappe/patches/v8_0/newsletter_childtable_migrate.py b/frappe/patches/v8_0/newsletter_childtable_migrate.py deleted file mode 100644 index 67ff5e586f..0000000000 --- a/frappe/patches/v8_0/newsletter_childtable_migrate.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - frappe.reload_doc('email', 'doctype', 'newsletter_email_group') - frappe.reload_doctype('Newsletter') - - if "email_group" not in frappe.db.get_table_columns("Newsletter"): - return - - newsletters = frappe.get_all("Newsletter", fields=["name", "email_group"]) - for newsletter in newsletters: - if newsletter.email_group: - newsletter_doc = frappe.get_doc("Newsletter", newsletter.name) - if not newsletter_doc.get("email_group"): - newsletter_doc.append("email_group", { - "email_group": newsletter.email_group, - }) - newsletter_doc.flags.ignore_validate = True - newsletter_doc.flags.ignore_mandatory = True - newsletter_doc.save() diff --git a/frappe/patches/v8_0/rename_listsettings_to_usersettings.py b/frappe/patches/v8_0/rename_listsettings_to_usersettings.py deleted file mode 100644 index 9545953e34..0000000000 --- a/frappe/patches/v8_0/rename_listsettings_to_usersettings.py +++ /dev/null @@ -1,45 +0,0 @@ - -from frappe.model.utils.user_settings import update_user_settings -import frappe, json - - -def execute(): - if frappe.db.table_exists("__ListSettings"): - for us in frappe.db.sql('''select user, doctype, data from __ListSettings''', as_dict=True): - try: - data = json.loads(us.data) - except: - continue - - if 'List' in data: - continue - - if 'limit' in data: - data['page_length'] = data['limit'] - del data['limit'] - - new_data = dict(List=data) - new_data = json.dumps(new_data) - - frappe.db.sql('''update __ListSettings - set data=%(new_data)s - where user=%(user)s - and doctype=%(doctype)s''', - {'new_data': new_data, 'user': us.user, 'doctype': us.doctype}) - - frappe.db.sql("RENAME TABLE __ListSettings to __UserSettings") - else: - if not frappe.db.table_exists("__UserSettings"): - frappe.db.create_user_settings_table() - - for user in frappe.db.get_all('User', {'user_type': 'System User'}): - defaults = frappe.defaults.get_defaults_for(user.name) - for key, value in defaults.items(): - if key.startswith('_list_settings:'): - doctype = key.replace('_list_settings:', '') - columns = ['`tab{1}`.`{0}`'.format(*c) for c in json.loads(value)] - for col in columns: - if "name as" in col: - columns.remove(col) - - update_user_settings(doctype, {'fields': columns}) \ No newline at end of file diff --git a/frappe/patches/v8_0/rename_page_role_to_has_role.py b/frappe/patches/v8_0/rename_page_role_to_has_role.py deleted file mode 100644 index 49006ea419..0000000000 --- a/frappe/patches/v8_0/rename_page_role_to_has_role.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - if not frappe.db.exists('DocType', 'Has Role'): - frappe.rename_doc('DocType', 'Page Role', 'Has Role') - reload_doc() - set_ref_doctype_roles_to_report() - copy_user_roles_to_has_roles() - remove_doctypes() - -def reload_doc(): - frappe.reload_doc("core", 'doctype', "page") - frappe.reload_doc("core", 'doctype', "report") - frappe.reload_doc("core", 'doctype', "user") - frappe.reload_doc("core", 'doctype', "has_role") - -def set_ref_doctype_roles_to_report(): - for data in frappe.get_all('Report', fields=["name"]): - doc = frappe.get_doc('Report', data.name) - if frappe.db.exists("DocType", doc.ref_doctype): - try: - doc.set_doctype_roles() - for row in doc.roles: - row.db_update() - except: - pass - -def copy_user_roles_to_has_roles(): - if frappe.db.exists('DocType', 'UserRole'): - for data in frappe.get_all('User', fields = ["name"]): - doc = frappe.get_doc('User', data.name) - doc.set('roles',[]) - for args in frappe.get_all('UserRole', fields = ["role"], - filters = {'parent': data.name, 'parenttype': 'User'}): - doc.append('roles', { - 'role': args.role - }) - for role in doc.roles: - role.db_update() - -def remove_doctypes(): - for doctype in ['UserRole', 'Event Role']: - if frappe.db.exists('DocType', doctype): - frappe.delete_doc('DocType', doctype) \ No newline at end of file diff --git a/frappe/patches/v8_0/rename_print_to_printing.py b/frappe/patches/v8_0/rename_print_to_printing.py deleted file mode 100644 index 56889d630e..0000000000 --- a/frappe/patches/v8_0/rename_print_to_printing.py +++ /dev/null @@ -1,13 +0,0 @@ - -import frappe - -def execute(): - if frappe.db.exists('Module Def', 'Print'): - frappe.reload_doc('printing', 'doctype', 'print_format') - frappe.reload_doc('printing', 'doctype', 'print_settings') - frappe.reload_doc('printing', 'doctype', 'print_heading') - frappe.reload_doc('printing', 'doctype', 'letter_head') - frappe.reload_doc('printing', 'page', 'print_format_builder') - frappe.db.sql("""update `tabPrint Format` set module='Printing' where module='Print'""") - - frappe.delete_doc('Module Def', 'Print') \ No newline at end of file diff --git a/frappe/patches/v8_0/set_allow_traceback.py b/frappe/patches/v8_0/set_allow_traceback.py deleted file mode 100644 index bb72e7dde6..0000000000 --- a/frappe/patches/v8_0/set_allow_traceback.py +++ /dev/null @@ -1,6 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc('core', 'doctype', 'system_settings') - frappe.db.sql("update `tabSystem Settings` set allow_error_traceback=1") diff --git a/frappe/patches/v8_0/set_currency_field_precision.py b/frappe/patches/v8_0/set_currency_field_precision.py deleted file mode 100644 index 57b12ffdee..0000000000 --- a/frappe/patches/v8_0/set_currency_field_precision.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe -from frappe.utils import get_number_format_info - -def execute(): - frappe.reload_doc('core', 'doctype', 'system_settings', force=True) - if not frappe.db.get_value("System Settings", None, "currency_precision"): - default_currency = frappe.db.get_default("currency") - number_format = frappe.db.get_value("Currency", default_currency, "number_format", cache=True) \ - or frappe.db.get_default("number_format") - if number_format: - precision = get_number_format_info(number_format)[2] - else: - precision = 2 - - ss = frappe.get_doc("System Settings") - ss.currency_precision = precision - ss.flags.ignore_mandatory = True - ss.save() diff --git a/frappe/patches/v8_0/set_doctype_values_in_custom_role.py b/frappe/patches/v8_0/set_doctype_values_in_custom_role.py deleted file mode 100644 index 50e7eb83e1..0000000000 --- a/frappe/patches/v8_0/set_doctype_values_in_custom_role.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - frappe.reload_doctype('Custom Role') - - # set ref doctype in custom role for reports - frappe.db.sql(""" update `tabCustom Role` set - `tabCustom Role`.ref_doctype = (select ref_doctype from `tabReport` where name = `tabCustom Role`.report) - where `tabCustom Role`.report is not null""") diff --git a/frappe/patches/v8_0/set_user_permission_for_page_and_report.py b/frappe/patches/v8_0/set_user_permission_for_page_and_report.py deleted file mode 100644 index 55789a8301..0000000000 --- a/frappe/patches/v8_0/set_user_permission_for_page_and_report.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - if not frappe.db.exists('DocType', 'Custom Role'): - frappe.reload_doc("core", 'doctype', "custom_role") - set_user_permission_for_page_and_report() - - update_ref_doctype_in_custom_role() - -def update_ref_doctype_in_custom_role(): - frappe.reload_doc("core", 'doctype', "custom_role") - frappe.db.sql("""update `tabCustom Role` - set - ref_doctype = (select ref_doctype from tabReport where name = `tabCustom Role`.report) - where report is not null""") - -def set_user_permission_for_page_and_report(): - make_custom_roles_for_page_and_report() - -def make_custom_roles_for_page_and_report(): - for doctype in ['Page', 'Report']: - for data in get_data(doctype): - doc = frappe.get_doc(doctype, data.name) - roles = get_roles(doctype, data, doc) - make_custom_roles(doctype, doc.name, roles) - -def get_data(doctype): - fields = ["name"] if doctype == 'Page' else ["name", "ref_doctype"] - return frappe.get_all(doctype, fields = fields) - -def get_roles(doctype, data, doc): - roles = [] - if doctype == 'Page': - for d in doc.roles: - if frappe.db.exists('Role', d.role): - roles.append({'role': d.role}) - else: - out = frappe.get_all('Custom DocPerm', fields='distinct role', filters=dict(parent = data.ref_doctype)) - for d in out: - roles.append({'role': d.role}) - return roles - -def make_custom_roles(doctype, name, roles): - field = doctype.lower() - - if roles: - custom_permission = frappe.get_doc({ - 'doctype': 'Custom Role', - field : name, - 'roles' : roles - }).insert() diff --git a/frappe/patches/v8_0/setup_email_inbox.py b/frappe/patches/v8_0/setup_email_inbox.py deleted file mode 100644 index ad99068eb9..0000000000 --- a/frappe/patches/v8_0/setup_email_inbox.py +++ /dev/null @@ -1,26 +0,0 @@ - -import frappe, json -from frappe.core.doctype.user.user import ask_pass_update, setup_user_email_inbox - -def execute(): - """ - depricate email inbox page if exists - remove desktop icon for email inbox page if exists - patch to remove Custom DocPerm for communication - add user inbox child table entry for existing email account in not exists - """ - - if frappe.db.exists("Page", "email_inbox"): - frappe.delete_doc("Page", "email_inbox") - - frappe.db.sql("""update `tabCustom DocPerm` set `write`=0, email=1 where parent='Communication'""") - - frappe.reload_doc("core", "doctype", "user_email") - frappe.reload_doc("email", "doctype", "email_account") - - email_accounts = frappe.get_all("Email Account", filters={"enable_incoming": 1}, - fields=["name", "email_id", "awaiting_password", "enable_outgoing"]) - - for email_account in email_accounts: - setup_user_email_inbox(email_account.get("name"), email_account.get("awaiting_password"), - email_account.get("email_id"), email_account.get("enabled_outgoing")) diff --git a/frappe/patches/v8_0/update_gender_and_salutation.py b/frappe/patches/v8_0/update_gender_and_salutation.py deleted file mode 100644 index 913e0f714b..0000000000 --- a/frappe/patches/v8_0/update_gender_and_salutation.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors - -import frappe -from frappe.desk.page.setup_wizard.install_fixtures import update_genders, update_salutations - -def execute(): - frappe.db.set_value("DocType", "Contact", "module", "Contacts") - frappe.db.set_value("DocType", "Address", "module", "Contacts") - frappe.db.set_value("DocType", "Address Template", "module", "Contacts") - frappe.reload_doc('contacts', 'doctype', 'gender') - frappe.reload_doc('contacts', 'doctype', 'salutation') - - update_genders() - update_salutations() \ No newline at end of file diff --git a/frappe/patches/v8_0/update_global_search_table.py b/frappe/patches/v8_0/update_global_search_table.py deleted file mode 100644 index 4d5c8be9cf..0000000000 --- a/frappe/patches/v8_0/update_global_search_table.py +++ /dev/null @@ -1,13 +0,0 @@ - -import frappe - -def execute(): - if not 'published' in frappe.db.get_db_table_columns('__global_search'): - frappe.db.sql('''alter table __global_search - add column `title` varchar(140)''') - - frappe.db.sql('''alter table __global_search - add column `route` varchar(140)''') - - frappe.db.sql('''alter table __global_search - add column `published` int(1) not null default 0''') diff --git a/frappe/patches/v8_0/update_published_in_global_search.py b/frappe/patches/v8_0/update_published_in_global_search.py deleted file mode 100644 index ae86cb8b24..0000000000 --- a/frappe/patches/v8_0/update_published_in_global_search.py +++ /dev/null @@ -1,12 +0,0 @@ - -import frappe - -def execute(): - from frappe.website.router import get_doctypes_with_web_view - from frappe.utils.global_search import rebuild_for_doctype - - for doctype in get_doctypes_with_web_view(): - try: - rebuild_for_doctype(doctype) - except frappe.DoesNotExistError: - pass diff --git a/frappe/patches/v8_0/update_records_in_global_search.py b/frappe/patches/v8_0/update_records_in_global_search.py deleted file mode 100644 index 316f84b2f0..0000000000 --- a/frappe/patches/v8_0/update_records_in_global_search.py +++ /dev/null @@ -1,12 +0,0 @@ - -import frappe -from frappe.utils.global_search import get_doctypes_with_global_search, rebuild_for_doctype -from frappe.utils import update_progress_bar - -def execute(): - frappe.cache().delete_value('doctypes_with_global_search') - doctypes_with_global_search = get_doctypes_with_global_search(with_child_tables=False) - - for i, doctype in enumerate(doctypes_with_global_search): - update_progress_bar("Updating Global Search", i, len(doctypes_with_global_search)) - rebuild_for_doctype(doctype) diff --git a/frappe/patches/v8_1/__init__.py b/frappe/patches/v8_1/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py b/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py deleted file mode 100644 index 510018eb47..0000000000 --- a/frappe/patches/v8_1/delete_custom_docperm_if_doctype_not_exists.py +++ /dev/null @@ -1,7 +0,0 @@ - -import frappe - -def execute(): - frappe.db.sql("""delete from `tabCustom DocPerm` - where parent not in ( select name from `tabDocType` ) - """) diff --git a/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py b/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py deleted file mode 100644 index 513bb274bc..0000000000 --- a/frappe/patches/v8_1/enable_allow_error_traceback_in_system_settings.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - """ enable the allow_enable_traceback property in system settings """ - - frappe.reload_doc("core", "doctype", "system_settings") - doc = frappe.get_doc("System Settings", "System Settings") - doc.allow_error_traceback = 1 - doc.flags.ignore_permissions=True - doc.flags.ignore_mandatory=True - doc.save() \ No newline at end of file diff --git a/frappe/patches/v8_1/update_format_options_in_auto_email_report.py b/frappe/patches/v8_1/update_format_options_in_auto_email_report.py deleted file mode 100644 index 8bea2b7bf5..0000000000 --- a/frappe/patches/v8_1/update_format_options_in_auto_email_report.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - """ change the XLS option as XLSX in the auto email report """ - - frappe.reload_doc("email", "doctype", "auto_email_report") - - auto_email_list = frappe.get_all("Auto Email Report", filters={"format": "XLS"}) - for auto_email in auto_email_list: - frappe.db.set_value("Auto Email Report", auto_email.name, "format", "XLSX") diff --git a/frappe/patches/v8_10/__init__.py b/frappe/patches/v8_10/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v8_10/delete_static_web_page_from_global_search.py b/frappe/patches/v8_10/delete_static_web_page_from_global_search.py deleted file mode 100644 index aa6a053412..0000000000 --- a/frappe/patches/v8_10/delete_static_web_page_from_global_search.py +++ /dev/null @@ -1,5 +0,0 @@ - -import frappe - -def execute(): - frappe.db.sql("""delete from `__global_search` where doctype='Static Web Page'"""); \ No newline at end of file diff --git a/frappe/patches/v8_5/__init__.py b/frappe/patches/v8_5/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py b/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py deleted file mode 100644 index 5851e2855b..0000000000 --- a/frappe/patches/v8_5/delete_email_group_member_with_invalid_emails.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe -from frappe.utils import validate_email_address - -def execute(): - ''' update/delete the email group member with the wrong email ''' - - email_group_members = frappe.get_all("Email Group Member", fields=["name", "email"]) - for member in email_group_members: - validated_email = validate_email_address(member.email) - if (validated_email==member.email): - pass - else: - try: - frappe.db.set_value("Email Group Member", member.name, "email", validated_email) - except Exception: - frappe.delete_doc(doctype="Email Group Member", name=member.name, force=1, ignore_permissions=True) \ No newline at end of file diff --git a/frappe/patches/v8_5/patch_event_colors.py b/frappe/patches/v8_5/patch_event_colors.py deleted file mode 100644 index 3c34f7946b..0000000000 --- a/frappe/patches/v8_5/patch_event_colors.py +++ /dev/null @@ -1,25 +0,0 @@ - -import frappe - -def execute(): - - if not frappe.db.sql("SHOW COLUMNS FROM `tabEvent` LIKE 'color';"): - return - - colors = ['red', 'green', 'blue', 'yellow', 'skyblue', 'orange'] - hex_colors = ['#ffc4c4', '#cef6d1', '#d2d2ff', '#fffacd', '#d2f1ff', '#ffd2c2'] - - def get_hex_for_color(color): - index = colors.index(color) - return hex_colors[index] - - query = ''' - update tabEvent - set color='{hex}' - where color='{color}' - ''' - - for color in colors: - frappe.db.sql(query.format(color=color, hex=get_hex_for_color(color))) - - frappe.db.commit() diff --git a/frappe/patches/v8_7/__init__.py b/frappe/patches/v8_7/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v8_x/__init__.py b/frappe/patches/v8_x/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/patches/v8_x/update_user_permission.py b/frappe/patches/v8_x/update_user_permission.py deleted file mode 100644 index 387751500f..0000000000 --- a/frappe/patches/v8_x/update_user_permission.py +++ /dev/null @@ -1,28 +0,0 @@ - -import frappe - -def execute(): - frappe.reload_doc('core', 'doctype', 'user_permission') - frappe.delete_doc('core', 'page', 'user-permissions') - for perm in frappe.db.sql(""" - select - name, parent, defkey, defvalue - from - tabDefaultValue - where - parent not in ('__default', '__global') - and - substr(defkey,1,1)!='_' - and - parenttype='User Permission' - """, as_dict=True): - if frappe.db.exists(perm.defkey, perm.defvalue) and frappe.db.exists('User', perm.parent): - frappe.get_doc(dict( - doctype='User Permission', - user=perm.parent, - allow=perm.defkey, - for_value=perm.defvalue, - apply_for_all_roles=0, - )).insert(ignore_permissions = True) - - frappe.db.sql('delete from tabDefaultValue where parenttype="User Permission"') diff --git a/frappe/patches/v9_1/__init__.py b/frappe/patches/v9_1/__init__.py deleted file mode 100644 index 8b13789179..0000000000 --- a/frappe/patches/v9_1/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py b/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py deleted file mode 100644 index f63e86a340..0000000000 --- a/frappe/patches/v9_1/add_sms_sender_name_as_parameters.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2017, Frappe and Contributors -# License: GNU General Public License v3. See license.txt - -import frappe - -def execute(): - frappe.reload_doc("core", "doctype", "sms_parameter") - sms_sender_name = frappe.db.get_single_value("SMS Settings", "sms_sender_name") - if sms_sender_name: - frappe.reload_doc("core", "doctype", "sms_settings") - sms_settings = frappe.get_doc("SMS Settings") - sms_settings.append("parameters", { - "parameter": "sender_name", - "value": sms_sender_name - }) - sms_settings.flags.ignore_mandatory = True - sms_settings.flags.ignore_permissions = True - sms_settings.save() diff --git a/frappe/patches/v9_1/move_feed_to_activity_log.py b/frappe/patches/v9_1/move_feed_to_activity_log.py deleted file mode 100644 index a549296357..0000000000 --- a/frappe/patches/v9_1/move_feed_to_activity_log.py +++ /dev/null @@ -1,24 +0,0 @@ - -import frappe -from frappe.utils.background_jobs import enqueue - -def execute(): - comm_records_count = frappe.db.count("Communication", {"comment_type": "Updated"}) - if comm_records_count > 100000: - enqueue(method=move_data_from_communication_to_activity_log, queue='short', now=True) - else: - move_data_from_communication_to_activity_log() - -def move_data_from_communication_to_activity_log(): - frappe.reload_doc("core", "doctype", "communication") - frappe.reload_doc("core", "doctype", "activity_log") - - frappe.db.sql("""insert into `tabActivity Log` (name, owner, modified, creation, status, communication_date, - reference_doctype, reference_name, timeline_doctype, timeline_name, link_doctype, link_name, subject, content, user) - select name, owner, modified, creation, status, communication_date, - reference_doctype, reference_name, timeline_doctype, timeline_name, link_doctype, link_name, subject, content, user - from `tabCommunication` - where comment_type = 'Updated'""") - - frappe.db.sql("""delete from `tabCommunication` where comment_type = 'Updated'""") - frappe.delete_doc("DocType", "Authentication Log") \ No newline at end of file diff --git a/frappe/patches/v9_1/resave_domain_settings.py b/frappe/patches/v9_1/resave_domain_settings.py deleted file mode 100644 index 5814871c2e..0000000000 --- a/frappe/patches/v9_1/resave_domain_settings.py +++ /dev/null @@ -1,13 +0,0 @@ - -import frappe - -def execute(): - domain_settings = frappe.get_doc('Domain Settings') - active_domains = [d.domain for d in domain_settings.active_domains] - try: - for d in ('Education', 'Healthcare', 'Hospitality'): - if d in active_domains and frappe.db.exists('Domain', d): - domain = frappe.get_doc('Domain', d) - domain.setup_domain() - except frappe.LinkValidationError: - pass diff --git a/frappe/patches/v9_1/revert_domain_settings.py b/frappe/patches/v9_1/revert_domain_settings.py deleted file mode 100644 index 99c5561d78..0000000000 --- a/frappe/patches/v9_1/revert_domain_settings.py +++ /dev/null @@ -1,11 +0,0 @@ - -import frappe - -def execute(): - domain_settings = frappe.get_doc('Domain Settings') - active_domains = [d.domain for d in domain_settings.active_domains] - - for domain_name in ('Education', 'Healthcare', 'Hospitality'): - if frappe.db.exists('Domain', domain_name) and domain_name not in active_domains: - domain = frappe.get_doc('Domain', domain_name) - domain.remove_domain() \ No newline at end of file From 95ab1a60b435d8f80b3b420fdd031e7d66a740bd Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 17:38:03 +0530 Subject: [PATCH 246/868] ci: Add frappe patch test * Generated v10 backup archive * used old v7 erpnext backup hosted via build.erpnext.com * upgraded to v10 frappe + erpnext * uninstalled and deleted erpnext related data * Hosted backup on https://frappeframework.com/files/v10-frappe.sql.gz --- .github/workflows/patch-mariadb-tests.yml | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/patch-mariadb-tests.yml diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml new file mode 100644 index 0000000000..e8627a01fb --- /dev/null +++ b/.github/workflows/patch-mariadb-tests.yml @@ -0,0 +1,83 @@ +name: Patch + +on: [pull_request, workflow_dispatch] + +jobs: + test: + runs-on: ubuntu-18.04 + + name: Patch Test + + services: + mysql: + image: mariadb:10.3 + env: + MYSQL_ALLOW_EMPTY_PASSWORD: YES + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 + + steps: + - name: Clone + uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Add to Hosts + run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts + + - name: Cache pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + ${{ runner.os }}- + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - uses: actions/cache@v2 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install Dependencies + run: bash ${GITHUB_WORKSPACE}/.github/helper/install_dependencies.sh + env: + BEFORE: ${{ env.GITHUB_EVENT_PATH.before }} + AFTER: ${{ env.GITHUB_EVENT_PATH.after }} + TYPE: server + + - name: Install + run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh + env: + DB: mariadb + TYPE: server + + - name: Run Patch Tests + run: | + cd ~/frappe-bench/ + wget https://frappeframework.com/files/v10-frappe.sql.gz + bench --site test_site --force restore ~/frappe-bench/v10-frappe.sql.gz + bench --site test_site migrate From 5aeef088adb377d0506d13caace63e92ed67ebe4 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 18:47:31 +0530 Subject: [PATCH 247/868] fix: Remove reloading statements for non existing dts --- frappe/patches/v11_0/create_contact_for_user.py | 1 - frappe/patches/v11_0/rename_google_maps_doctype.py | 1 - 2 files changed, 2 deletions(-) diff --git a/frappe/patches/v11_0/create_contact_for_user.py b/frappe/patches/v11_0/create_contact_for_user.py index 21e681a83e..5a483b630e 100644 --- a/frappe/patches/v11_0/create_contact_for_user.py +++ b/frappe/patches/v11_0/create_contact_for_user.py @@ -8,7 +8,6 @@ def execute(): frappe.reload_doc('integrations', 'doctype', 'google_contacts') frappe.reload_doc('contacts', 'doctype', 'contact') frappe.reload_doc('core', 'doctype', 'dynamic_link') - frappe.reload_doc('communication', 'doctype', 'call_log') contact_meta = frappe.get_meta("Contact") if contact_meta.has_field("phone_nos") and contact_meta.has_field("email_ids"): diff --git a/frappe/patches/v11_0/rename_google_maps_doctype.py b/frappe/patches/v11_0/rename_google_maps_doctype.py index 4e8aee6280..8091154b9c 100644 --- a/frappe/patches/v11_0/rename_google_maps_doctype.py +++ b/frappe/patches/v11_0/rename_google_maps_doctype.py @@ -5,4 +5,3 @@ from frappe.model.rename_doc import rename_doc def execute(): if frappe.db.exists("DocType","Google Maps") and not frappe.db.exists("DocType","Google Maps Settings"): rename_doc('DocType', 'Google Maps', 'Google Maps Settings') - frappe.reload_doc('integrations', 'doctype', 'google_maps_settings') \ No newline at end of file From 0d8aeba3ee66c34072e2deb135b85016aefaf0dc Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 18:57:07 +0530 Subject: [PATCH 248/868] fix: Update coverage omit files Files that don't end with .py or .pyo ot .pyc are automatically skipped by coveragepy. Updated omit list accordingly to remove non python importable files. ref: https://coverage.readthedocs.io/en/coverage-5.5/source.html#execution --- .github/workflows/server-mariadb-tests.yml | 1 - frappe/commands/utils.py | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/server-mariadb-tests.yml b/.github/workflows/server-mariadb-tests.yml index 1c7655528c..2476102e3d 100644 --- a/.github/workflows/server-mariadb-tests.yml +++ b/.github/workflows/server-mariadb-tests.yml @@ -91,7 +91,6 @@ jobs: DB: mariadb TYPE: server - - name: Run Tests run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --use-orchestrator --with-coverage env: diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index bcb1749644..306f6278cf 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -573,18 +573,15 @@ def run_tests(context, app=None, module=None, doctype=None, test=(), profile=Fal # Generate coverage report only for app that is being tested source_path = os.path.join(get_bench_path(), 'apps', app or 'frappe') omit=[ - '*.html', - '*.js', - '*.xml', - '*.css', - '*.less', - '*.scss', - '*.vue', + '*.pyc', + '*/test_*', + '*/node_modules/*', '*/doctype/*/*_dashboard.py', '*/patches/*' ] if not app or app == 'frappe': + omit.append('*/tests/*') omit.append('*/commands/*') cov = Coverage(source=[source_path], omit=omit) From a74ffda29b833361cf22ecd6753d390f25e88642 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 18:59:29 +0530 Subject: [PATCH 249/868] chore: Drop dead code to handle webnotes frappe naming --- frappe/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index bb4e409d61..9d8c5d3607 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1110,9 +1110,7 @@ def setup_module_map(): if not (local.app_modules and local.module_app): local.module_app, local.app_modules = {}, {} - for app in get_all_apps(True): - if app == "webnotes": - app = "frappe" + for app in get_all_apps(with_internal_apps=True): local.app_modules.setdefault(app, []) for module in get_module_list(app): module = scrub(module) From 9b164571c3ee8cdeebc8cb987b11cd8c37cc7278 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 20:23:06 +0530 Subject: [PATCH 250/868] fix: Update coverage omit files Apply 0d8aeba3ee66c34072e2deb135b85016aefaf0dc for parrallel test runner --- frappe/commands/utils.py | 17 ++++++++++++++--- frappe/parallel_test_runner.py | 23 ++++++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index 306f6278cf..d6cf2309ba 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -572,19 +572,30 @@ def run_tests(context, app=None, module=None, doctype=None, test=(), profile=Fal # Generate coverage report only for app that is being tested source_path = os.path.join(get_bench_path(), 'apps', app or 'frappe') - omit=[ + incl = [ + '*.py', + ] + omit = [ + '*.js', + '*.xml', '*.pyc', + '*.css', + '*.less', + '*.scss', + '*.vue', + '*.pyc', + '*.html', '*/test_*', '*/node_modules/*', '*/doctype/*/*_dashboard.py', - '*/patches/*' + '*/patches/*', ] if not app or app == 'frappe': omit.append('*/tests/*') omit.append('*/commands/*') - cov = Coverage(source=[source_path], omit=omit) + cov = Coverage(source=[source_path], omit=omit, include=incl) cov.start() ret = frappe.test_runner.main(app, module, doctype, context.verbose, tests=tests, diff --git a/frappe/parallel_test_runner.py b/frappe/parallel_test_runner.py index 1dbb24f191..2f83b88572 100644 --- a/frappe/parallel_test_runner.py +++ b/frappe/parallel_test_runner.py @@ -114,13 +114,30 @@ class ParallelTestRunner(): # Generate coverage report only for app that is being tested source_path = os.path.join(get_bench_path(), 'apps', self.app) - omit=['*.html', '*.js', '*.xml', '*.css', '*.less', '*.scss', - '*.vue', '*/doctype/*/*_dashboard.py', '*/patches/*'] + incl = [ + '*.py', + ] + omit = [ + '*.js', + '*.xml', + '*.pyc', + '*.css', + '*.less', + '*.scss', + '*.vue', + '*.pyc', + '*.html', + '*/test_*', + '*/node_modules/*', + '*/doctype/*/*_dashboard.py', + '*/patches/*', + ] if self.app == 'frappe': + omit.append('*/tests/*') omit.append('*/commands/*') - self.coverage = Coverage(source=[source_path], omit=omit) + self.coverage = Coverage(source=[source_path], omit=omit, include=incl) self.coverage.start() def save_coverage(self): From a3b68cbc2e79a2d704108775003f1693e06b8aa3 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 3 Jun 2021 21:46:39 +0530 Subject: [PATCH 251/868] chore(cov): Drop duplicate pattern in omit list --- frappe/commands/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index d6cf2309ba..8ef70d739c 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -583,7 +583,6 @@ def run_tests(context, app=None, module=None, doctype=None, test=(), profile=Fal '*.less', '*.scss', '*.vue', - '*.pyc', '*.html', '*/test_*', '*/node_modules/*', From 70a1cfb1aba3d496d191bfd3b78b27f80451ca67 Mon Sep 17 00:00:00 2001 From: leela Date: Fri, 4 Jun 2021 06:55:17 +0530 Subject: [PATCH 252/868] fix: inbound mail handling for pop3 protocol --- frappe/email/doctype/email_account/email_account.py | 5 ++--- frappe/email/receive.py | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index c77ba00021..7aba559d1f 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -478,14 +478,13 @@ class EmailAccount(Document): email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) messages = email_server.get_messages() or {} except Exception: - raise frappe.log_error(title=_("Error while connecting to email account {0}").format(self.name)) return [] mails = [] for index, message in enumerate(messages.get("latest_messages", [])): - uid = messages['uid_list'][index] - seen_status = 1 if messages['seen_status'][uid]=='SEEN' else 0 + uid = messages['uid_list'][index] if messages.get('uid_list') else None + seen_status = 1 if messages.get('seen_status', {}).get(uid)=='SEEN' else 0 mails.append(InboundMail(message, self, uid, seen_status)) return mails diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 7da4840df1..9ad560aa4a 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -738,9 +738,6 @@ class InboundMail(Email): if not reference_document and self.email_account.append_to: reference_document = self.match_record_by_subject_and_sender(self.email_account.append_to) - # if not reference_document: - # reference_document = Create_reference_document(self.email_account.append_to) - self._reference_document = reference_document or '' return self._reference_document From 1ef83ea15f264b785cd9981bc907d8aebbc1efa1 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Fri, 4 Jun 2021 11:50:03 +0530 Subject: [PATCH 253/868] test: Add printview page test --- frappe/tests/test_website.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frappe/tests/test_website.py b/frappe/tests/test_website.py index 68ec4f1f09..6f265d9b94 100644 --- a/frappe/tests/test_website.py +++ b/frappe/tests/test_website.py @@ -196,6 +196,11 @@ class TestWebsite(unittest.TestCase): delattr(frappe.hooks, 'page_renderer') frappe.cache().delete_key('app_hooks') + def test_printview_page(self): + content = get_response_content('/Language/en') + self.assertIn('