@@ -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() | |||
@@ -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"): | |||
@@ -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 | |||
@@ -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") | |||
@@ -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() | |||
@@ -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] | |||