@@ -36,6 +36,9 @@ class Comment(Document): | |||||
self.update_comments_in_parent(_comments) | self.update_comments_in_parent(_comments) | ||||
except Exception, e: | except Exception, e: | ||||
if e.args[0]==1054: | if e.args[0]==1054: | ||||
if frappe.flags.in_test: | |||||
return | |||||
from frappe.model.db_schema import add_column | from frappe.model.db_schema import add_column | ||||
add_column(self.comment_doctype, "_comments", "Text") | add_column(self.comment_doctype, "_comments", "Text") | ||||
self.update_comment_in_doc() | self.update_comment_in_doc() | ||||
@@ -80,7 +80,7 @@ class DocType(Document): | |||||
self.make_controller_template() | self.make_controller_template() | ||||
# update index | # update index | ||||
if not self.custom: | |||||
if not getattr(self, "custom", False): | |||||
from frappe.modules import load_doctype_module | from frappe.modules import load_doctype_module | ||||
module = load_doctype_module(self.name, self.module) | module = load_doctype_module(self.name, self.module) | ||||
if hasattr(module, "on_doctype_update"): | if hasattr(module, "on_doctype_update"): | ||||
@@ -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 | 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): | if isinstance(filters, list): | ||||
return self.get_value_for_many_names(doctype, filters, fieldname, debug=debug) | 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"): | if (filters is not None) and (filters!=doctype or doctype=="DocType"): | ||||
try: | 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: | except Exception, e: | ||||
if ignore and e.args[0] in (1146, 1054): | if ignore and e.args[0] in (1146, 1054): | ||||
# table or column not found, return None | # table or column not found, return None | ||||
@@ -325,9 +325,9 @@ class Database: | |||||
else: | else: | ||||
raise | 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): | if fields=="*" or isinstance(filters, dict): | ||||
# check if single doc matches with filters | # check if single doc matches with filters | ||||
values = self.get_singles_dict(doctype) | values = self.get_singles_dict(doctype) | ||||
@@ -349,7 +349,13 @@ class Database: | |||||
tuple(fields) + (doctype,), as_dict=False, debug=debug) | tuple(fields) + (doctype,), as_dict=False, debug=debug) | ||||
if as_dict: | 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: | else: | ||||
return r and [[i[1] for i in r]] or [] | return r and [[i[1] for i in r]] or [] | ||||
@@ -358,7 +364,7 @@ class Database: | |||||
tabSingles where doctype=%s""", doctype)) | 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 = [] | fl = [] | ||||
if isinstance(fields, (list, tuple)): | if isinstance(fields, (list, tuple)): | ||||
for f in fields: | for f in fields: | ||||
@@ -377,7 +383,7 @@ class Database: | |||||
order_by = ("order by " + order_by) if order_by else "" | order_by = ("order by " + order_by) if order_by else "" | ||||
r = self.sql("select %s from `tab%s` where %s %s" % (fl, doctype, | 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 | return r | ||||
@@ -5,6 +5,7 @@ from __future__ import unicode_literals | |||||
import frappe | import frappe | ||||
from frappe import _, msgprint | from frappe import _, msgprint | ||||
from frappe.utils import cint, flt, cstr, now | from frappe.utils import cint, flt, cstr, now | ||||
from frappe.model import default_fields | |||||
from frappe.model.naming import set_new_name | from frappe.model.naming import set_new_name | ||||
class BaseDocument(object): | class BaseDocument(object): | ||||
@@ -13,14 +14,6 @@ class BaseDocument(object): | |||||
def __init__(self, d): | def __init__(self, d): | ||||
self.update(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 | @property | ||||
def meta(self): | def meta(self): | ||||
if not hasattr(self, "_meta"): | if not hasattr(self, "_meta"): | ||||
@@ -69,6 +62,7 @@ class BaseDocument(object): | |||||
return value | return value | ||||
else: | else: | ||||
return self.__dict__ | return self.__dict__ | ||||
def getone(self, key, filters=None): | def getone(self, key, filters=None): | ||||
return self.get(key, filters=filters, limit=1)[0] | return self.get(key, filters=filters, limit=1)[0] | ||||
@@ -83,10 +77,10 @@ class BaseDocument(object): | |||||
if value==None: | if value==None: | ||||
value={} | value={} | ||||
if isinstance(value, (dict, BaseDocument)): | if isinstance(value, (dict, BaseDocument)): | ||||
if not self.get(key): | |||||
if not self.__dict__.get(key): | |||||
self.__dict__[key] = [] | self.__dict__[key] = [] | ||||
value = self._init_child(value, key) | value = self._init_child(value, key) | ||||
self.get(key).append(value) | |||||
self.__dict__[key].append(value) | |||||
return value | return value | ||||
else: | else: | ||||
raise ValueError | raise ValueError | ||||
@@ -105,16 +99,17 @@ class BaseDocument(object): | |||||
if not self.doctype: | if not self.doctype: | ||||
return value | return value | ||||
if not isinstance(value, BaseDocument): | if not isinstance(value, BaseDocument): | ||||
if not "doctype" in value: | |||||
if "doctype" not in value: | |||||
value["doctype"] = self.get_table_field_doctype(key) | value["doctype"] = self.get_table_field_doctype(key) | ||||
if not value["doctype"]: | if not value["doctype"]: | ||||
raise AttributeError, key | raise AttributeError, key | ||||
value = BaseDocument(value) | value = BaseDocument(value) | ||||
value.init_valid_columns() | |||||
value.parent = self.name | value.parent = self.name | ||||
value.parenttype = self.doctype | value.parenttype = self.doctype | ||||
value.parentfield = key | value.parentfield = key | ||||
if not value.idx: | |||||
if not getattr(value, "idx", None): | |||||
value.idx = len(self.get(key) or []) + 1 | value.idx = len(self.get(key) or []) + 1 | ||||
return value | return value | ||||
@@ -125,6 +120,18 @@ class BaseDocument(object): | |||||
d[fieldname] = self.get(fieldname) | d[fieldname] = self.get(fieldname) | ||||
return d | 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): | def is_new(self): | ||||
return self.get("__islocal") | return self.get("__islocal") | ||||
@@ -65,6 +65,7 @@ class Document(BaseDocument): | |||||
elif isinstance(arg1, dict): | elif isinstance(arg1, dict): | ||||
super(Document, self).__init__(arg1) | super(Document, self).__init__(arg1) | ||||
self.init_valid_columns() | |||||
else: | else: | ||||
# incorrect arguments. let's not proceed. | # incorrect arguments. let's not proceed. | ||||
@@ -73,6 +74,7 @@ class Document(BaseDocument): | |||||
def load_from_db(self): | def load_from_db(self): | ||||
if not getattr(self, "_metaclass", False) and self.meta.issingle: | if not getattr(self, "_metaclass", False) and self.meta.issingle: | ||||
self.update(frappe.db.get_singles_dict(self.doctype)) | self.update(frappe.db.get_singles_dict(self.doctype)) | ||||
self.init_valid_columns() | |||||
self._fix_numeric_types() | self._fix_numeric_types() | ||||
else: | else: | ||||
@@ -82,20 +84,20 @@ class Document(BaseDocument): | |||||
self.doctype, self.name), frappe.DoesNotExistError) | self.doctype, self.name), frappe.DoesNotExistError) | ||||
self.update(d) | 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): | def has_permission(self, permtype): | ||||
if getattr(self, "ignore_permissions", False): | if getattr(self, "ignore_permissions", False): | ||||
@@ -121,7 +123,7 @@ class Document(BaseDocument): | |||||
# run validate, on update etc. | # run validate, on update etc. | ||||
# parent | # parent | ||||
if self.meta.issingle: | |||||
if getattr(self.meta, "issingle", 0): | |||||
self.update_single(self.get_valid_dict()) | self.update_single(self.get_valid_dict()) | ||||
else: | else: | ||||
self.db_insert() | self.db_insert() | ||||
@@ -36,9 +36,15 @@ class Meta(Document): | |||||
if self.doctype=="DocType" and self.name in self.special_doctypes: | if self.doctype=="DocType" and self.name in self.special_doctypes: | ||||
fname = frappe.scrub(self.name) | fname = frappe.scrub(self.name) | ||||
with open(frappe.get_app_path("frappe", "core", "doctype", fname, fname + ".json"), "r") as f: | 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] | self.fields = [BaseDocument(d) for d in self.fields] | ||||
if hasattr(self, "permissions"): | if hasattr(self, "permissions"): | ||||
self.permissions = [BaseDocument(d) for d in self.permissions] | self.permissions = [BaseDocument(d) for d in self.permissions] | ||||