From 0cbf1e41910e90e31a2880f37fb9a9e0d01addc0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 4 Apr 2014 13:00:59 +0530 Subject: [PATCH] init valid columns, improved load from db - no need to override __getattr__ #478 --- frappe/core/doctype/comment/comment.py | 3 +++ frappe/core/doctype/doctype/doctype.py | 2 +- frappe/database.py | 20 +++++++++++------ frappe/model/base_document.py | 31 ++++++++++++++++---------- frappe/model/document.py | 30 +++++++++++++------------ frappe/model/meta.py | 12 +++++++--- 6 files changed, 61 insertions(+), 37 deletions(-) diff --git a/frappe/core/doctype/comment/comment.py b/frappe/core/doctype/comment/comment.py index 13cf125036..536bc66425 100644 --- a/frappe/core/doctype/comment/comment.py +++ b/frappe/core/doctype/comment/comment.py @@ -36,6 +36,9 @@ class Comment(Document): self.update_comments_in_parent(_comments) except Exception, e: if e.args[0]==1054: + if frappe.flags.in_test: + return + from frappe.model.db_schema import add_column add_column(self.comment_doctype, "_comments", "Text") self.update_comment_in_doc() diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index a1017c0c5d..f64e86c77c 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -80,7 +80,7 @@ class DocType(Document): self.make_controller_template() # update index - if not self.custom: + if not getattr(self, "custom", False): from frappe.modules import load_doctype_module module = load_doctype_module(self.name, self.module) if hasattr(module, "on_doctype_update"): diff --git a/frappe/database.py b/frappe/database.py index afdbc3bfab..127d2d0bf0 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -301,7 +301,7 @@ class Database: return ((len(ret[0]) > 1 or as_dict) and ret[0] or ret[0][0]) if ret else None - def get_values(self, doctype, filters=None, fieldname="name", ignore=None, as_dict=False, debug=False, order_by=None): + def get_values(self, doctype, filters=None, fieldname="name", ignore=None, as_dict=False, debug=False, order_by=None, update=None): if isinstance(filters, list): return self.get_value_for_many_names(doctype, filters, fieldname, debug=debug) @@ -314,7 +314,7 @@ class Database: if (filters is not None) and (filters!=doctype or doctype=="DocType"): try: - return self.get_values_from_table(fields, filters, doctype, as_dict, debug, order_by) + return self.get_values_from_table(fields, filters, doctype, as_dict, debug, order_by, update) except Exception, e: if ignore and e.args[0] in (1146, 1054): # table or column not found, return None @@ -325,9 +325,9 @@ class Database: else: raise - return self.get_values_from_single(fields, filters, doctype, as_dict, debug) + return self.get_values_from_single(fields, filters, doctype, as_dict, debug, update) - def get_values_from_single(self, fields, filters, doctype, as_dict=False, debug=False): + def get_values_from_single(self, fields, filters, doctype, as_dict=False, debug=False, update=None): if fields=="*" or isinstance(filters, dict): # check if single doc matches with filters values = self.get_singles_dict(doctype) @@ -349,7 +349,13 @@ class Database: tuple(fields) + (doctype,), as_dict=False, debug=debug) if as_dict: - return r and [frappe._dict(r)] or [] + if r: + r = frappe._dict(r) + if update: + r.update(update) + return [r] + else: + return [] else: return r and [[i[1] for i in r]] or [] @@ -358,7 +364,7 @@ class Database: tabSingles where doctype=%s""", doctype)) - def get_values_from_table(self, fields, filters, doctype, as_dict, debug, order_by=None): + def get_values_from_table(self, fields, filters, doctype, as_dict, debug, order_by=None, update=None): fl = [] if isinstance(fields, (list, tuple)): for f in fields: @@ -377,7 +383,7 @@ class Database: order_by = ("order by " + order_by) if order_by else "" r = self.sql("select %s from `tab%s` where %s %s" % (fl, doctype, - conditions, order_by), filters, as_dict=as_dict, debug=debug) + conditions, order_by), filters, as_dict=as_dict, debug=debug, update=update) return r diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index f5baee9433..8eb173f75e 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _, msgprint from frappe.utils import cint, flt, cstr, now +from frappe.model import default_fields from frappe.model.naming import set_new_name class BaseDocument(object): @@ -13,14 +14,6 @@ class BaseDocument(object): def __init__(self, d): self.update(d) - def __getattr__(self, key): - # this is called only when something is not found in dir or __dict__ - if not key.startswith("__") and key not in self.ignore_in_getter \ - and key in self.meta.get_valid_columns(): - return None - else: - raise AttributeError, key - @property def meta(self): if not hasattr(self, "_meta"): @@ -69,6 +62,7 @@ class BaseDocument(object): return value else: return self.__dict__ + def getone(self, key, filters=None): return self.get(key, filters=filters, limit=1)[0] @@ -83,10 +77,10 @@ class BaseDocument(object): if value==None: value={} if isinstance(value, (dict, BaseDocument)): - if not self.get(key): + if not self.__dict__.get(key): self.__dict__[key] = [] value = self._init_child(value, key) - self.get(key).append(value) + self.__dict__[key].append(value) return value else: raise ValueError @@ -105,16 +99,17 @@ class BaseDocument(object): if not self.doctype: return value if not isinstance(value, BaseDocument): - if not "doctype" in value: + if "doctype" not in value: value["doctype"] = self.get_table_field_doctype(key) if not value["doctype"]: raise AttributeError, key value = BaseDocument(value) + value.init_valid_columns() value.parent = self.name value.parenttype = self.doctype value.parentfield = key - if not value.idx: + if not getattr(value, "idx", None): value.idx = len(self.get(key) or []) + 1 return value @@ -125,6 +120,18 @@ class BaseDocument(object): d[fieldname] = self.get(fieldname) return d + def init_valid_columns(self): + for key in default_fields: + if key not in self.__dict__: + self.__dict__[key] = None + + if getattr(self, "_metaclass", False) or self.doctype in ("DocType", "DocField", "DocPerm"): + return + + for key in self.meta.get_valid_columns(): + if key not in self.__dict__: + self.__dict__[key] = None + def is_new(self): return self.get("__islocal") diff --git a/frappe/model/document.py b/frappe/model/document.py index 7373de2c2b..6443ae9982 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -65,6 +65,7 @@ class Document(BaseDocument): elif isinstance(arg1, dict): super(Document, self).__init__(arg1) + self.init_valid_columns() else: # incorrect arguments. let's not proceed. @@ -73,6 +74,7 @@ class Document(BaseDocument): def load_from_db(self): if not getattr(self, "_metaclass", False) and self.meta.issingle: self.update(frappe.db.get_singles_dict(self.doctype)) + self.init_valid_columns() self._fix_numeric_types() else: @@ -82,20 +84,20 @@ class Document(BaseDocument): self.doctype, self.name), frappe.DoesNotExistError) self.update(d) - if self.name=="DocType" and self.doctype=="DocType": - from frappe.model.meta import doctype_table_fields - table_fields = doctype_table_fields - else: - table_fields = self.meta.get_table_fields() + if self.name=="DocType" and self.doctype=="DocType": + from frappe.model.meta import doctype_table_fields + table_fields = doctype_table_fields + else: + table_fields = self.meta.get_table_fields() - for df in table_fields: - children = frappe.db.get_values(df.options, - {"parent": self.name, "parenttype": self.doctype, "parentfield": df.fieldname}, - "*", as_dict=True, order_by="idx asc") - if children: - self.set(df.fieldname, children) - else: - self.set(df.fieldname, []) + for df in table_fields: + children = frappe.db.get_values(df.options, + {"parent": self.name, "parenttype": self.doctype, "parentfield": df.fieldname}, + "*", as_dict=True, order_by="idx asc") + if children: + self.set(df.fieldname, children) + else: + self.set(df.fieldname, []) def has_permission(self, permtype): if getattr(self, "ignore_permissions", False): @@ -121,7 +123,7 @@ class Document(BaseDocument): # run validate, on update etc. # parent - if self.meta.issingle: + if getattr(self.meta, "issingle", 0): self.update_single(self.get_valid_dict()) else: self.db_insert() diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 67122247cc..099d8ea22b 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -36,9 +36,15 @@ class Meta(Document): if self.doctype=="DocType" and self.name in self.special_doctypes: fname = frappe.scrub(self.name) with open(frappe.get_app_path("frappe", "core", "doctype", fname, fname + ".json"), "r") as f: - txt = f.read() - - self.__dict__.update(json.loads(txt)) + txt = json.loads(f.read()) + + for d in txt.get("fields", []): + d["doctype"] = "DocField" + + for d in txt.get("permissions", []): + d["doctype"] = "DocPerm" + + self.__dict__.update(txt) self.fields = [BaseDocument(d) for d in self.fields] if hasattr(self, "permissions"): self.permissions = [BaseDocument(d) for d in self.permissions]