diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 5a91016e32..738fb73a34 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -87,10 +87,6 @@ class DocType(Document): if self.default_print_format and not self.custom: frappe.throw(_('Standard DocType cannot have default print format, use Customize Form')) - if frappe.conf.get('developer_mode'): - self.owner = 'Administrator' - self.modified_by = 'Administrator' - def validate_field_name_conflicts(self): """Check if field names dont conflict with controller properties and methods""" core_doctypes = [ @@ -177,7 +173,6 @@ class DocType(Document): if self.is_virtual and self.custom: frappe.throw(_("Not allowed to create custom Virtual DocType."), CannotCreateStandardDoctypeError) - if frappe.conf.get('developer_mode'): self.owner = 'Administrator' self.modified_by = 'Administrator' @@ -315,9 +310,7 @@ class DocType(Document): if allow_doctype_export: self.export_doc() self.make_controller_template() - - if self.has_web_view: - self.set_base_class_for_controller() + self.set_base_class_for_controller() # update index if not self.custom: @@ -355,23 +348,49 @@ class DocType(Document): now=now, doctype=self.name) def set_base_class_for_controller(self): - '''Updates the controller class to subclass from `WebsiteGenertor`, - if it is a subclass of `Document`''' - controller_path = frappe.get_module_path(frappe.scrub(self.module), - 'doctype', frappe.scrub(self.name), frappe.scrub(self.name) + '.py') + """If DocType.has_web_view has been changed, updates the controller class and import + from `WebsiteGenertor` to `Document` or viceversa""" - with open(controller_path, 'r') as f: + if not self.has_value_changed("has_web_view"): + return + + despaced_name = self.name.replace(" ", "_") + scrubbed_name = frappe.scrub(self.name) + scrubbed_module = frappe.scrub(self.module) + controller_path = frappe.get_module_path( + scrubbed_module, "doctype", scrubbed_name, f"{scrubbed_name}.py" + ) + + document_cls_tag = f"class {despaced_name}(Document)" + document_import_tag = "from frappe.model.document import Document" + website_generator_cls_tag = f"class {despaced_name}(WebsiteGenerator)" + website_generator_import_tag = "from frappe.website.generators.website_generator import WebsiteGenerator" + + with open(controller_path) as f: code = f.read() + updated_code = code - class_string = '\nclass {0}(Document)'.format(self.name.replace(' ', '')) - if '\nfrom frappe.model.document import Document' in code and class_string in code: - code = code.replace('from frappe.model.document import Document', - 'from frappe.website.website_generator import WebsiteGenerator') - code = code.replace('class {0}(Document)'.format(self.name.replace(' ', '')), - 'class {0}(WebsiteGenerator)'.format(self.name.replace(' ', ''))) + is_website_generator_class = all([ + website_generator_cls_tag in code, + website_generator_import_tag in code + ]) - with open(controller_path, 'w') as f: - f.write(code) + if self.has_web_view and not is_website_generator_class: + updated_code = updated_code.replace( + document_import_tag, website_generator_import_tag + ).replace( + document_cls_tag, website_generator_cls_tag + ) + elif not self.has_web_view and is_website_generator_class: + updated_code = updated_code.replace( + website_generator_import_tag, document_import_tag + ).replace( + website_generator_cls_tag, document_cls_tag + ) + + if updated_code != code: + with open(controller_path, "w") as f: + f.write(updated_code) def run_module_method(self, method): from frappe.modules import load_doctype_module diff --git a/frappe/database/database.py b/frappe/database/database.py index df5ad6dfda..c0d377fd42 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -170,6 +170,12 @@ class Database(object): frappe.errprint('Syntax error in query:') frappe.errprint(query) + elif self.is_deadlocked(e): + raise frappe.QueryDeadlockError + + elif self.is_timedout(e): + raise frappe.QueryTimeoutError + if ignore_ddl and (self.is_missing_column(e) or self.is_missing_table(e) or self.cant_drop_field_or_key(e)): pass else: diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 4b59f8f38f..8449425bc1 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -101,6 +101,8 @@ class DataTooLongException(ValidationError): pass class FileAlreadyAttachedException(Exception): pass class DocumentAlreadyRestored(ValidationError): pass class AttachmentLimitReached(ValidationError): pass +class QueryTimeoutError(Exception): pass +class QueryDeadlockError(Exception): pass # OAuth exceptions class InvalidAuthorizationHeader(CSRFTokenError): pass class InvalidAuthorizationPrefix(CSRFTokenError): pass diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index 17e84ee488..ab6ffd4985 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -24,7 +24,7 @@ def write_document_file(doc, record_module=None, create_init=True, folder_name=N doc_export = doc.as_dict(no_nulls=True) doc.run_method("before_export", doc_export) - strip_default_fields(doc, doc_export) + doc_export = strip_default_fields(doc, doc_export) module = record_module or get_module_name(doc) # create folder @@ -42,12 +42,17 @@ def write_document_file(doc, record_module=None, create_init=True, folder_name=N def strip_default_fields(doc, doc_export): # strip out default fields from children + if doc.doctype == "DocType" and doc.migration_hash: + del doc_export["migration_hash"] + for df in doc.meta.get_table_fields(): for d in doc_export.get(df.fieldname): for fieldname in frappe.model.default_fields: if fieldname in d: del d[fieldname] + return doc_export + def write_code_files(folder, fname, doc, doc_export): '''Export code files and strip from values''' if hasattr(doc, 'get_code_fields'): @@ -59,8 +64,6 @@ def write_code_files(folder, fname, doc, doc_export): # remove from exporting del doc_export[key] - - def get_module_name(doc): if doc.doctype == 'Module Def': module = doc.name diff --git a/frappe/patches/v11_0/remove_skip_for_doctype.py b/frappe/patches/v11_0/remove_skip_for_doctype.py index 1063dca3ff..1bbe74bb6d 100644 --- a/frappe/patches/v11_0/remove_skip_for_doctype.py +++ b/frappe/patches/v11_0/remove_skip_for_doctype.py @@ -75,7 +75,7 @@ def execute(): if new_user_permissions_list: frappe.qb.into("User Permission").columns( "name", "user", "allow", "for_value", "applicable_for", "apply_to_all_doctypes", "creation", "modified" - ).insert(tuple(new_user_permissions_list)).run() + ).insert(*new_user_permissions_list).run() if user_permissions_to_delete: frappe.db.delete( diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index de174cf37f..311a5b7a1e 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -320,7 +320,7 @@ export default class GridRow {
@@ -397,7 +397,7 @@ export default class GridRow { ${frappe.utils.icon('drag', 'xs')}