diff --git a/frappe/__init__.py b/frappe/__init__.py index 160e679a43..80efc83987 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -110,7 +110,7 @@ def init(site, sites_path=None): local.test_objects = {} local.jenv = None local.jloader =None - local.meta = {} + local.cache = {} setup_module_map() @@ -260,8 +260,8 @@ def clear_cache(user=None, doctype=None): """clear cache""" import frappe.sessions if doctype: - import frappe.model.doctype - frappe.model.doctype.clear_cache(doctype) + import frappe.model.meta + frappe.model.meta.clear_cache(doctype) reset_metadata_version() elif user: frappe.sessions.clear_cache(user) @@ -313,10 +313,6 @@ def new_doc(doctype, parent_doc=None, parentfield=None): from frappe.model.create_new import get_new_doc return get_new_doc(doctype, parent_doc, parentfield) -def new_bean(doctype): - from frappe.model.create_new import get_new_doc - return bean([get_new_doc(doctype)]) - def doclist(lst=None): from frappe.model.doclist import DocList return DocList(lst) @@ -478,7 +474,7 @@ def call(fn, *args, **kwargs): def make_property_setter(args): args = _dict(args) - bean([{ + get_doc({ 'doctype': "Property Setter", 'doctype_or_field': args.doctype_or_field or "DocField", 'doc_type': args.doctype, @@ -487,7 +483,7 @@ def make_property_setter(args): 'value': args.value, 'property_type': args.property_type or "Data", '__islocal': 1 - }]).save() + }).save() def get_application_home_page(user='Guest'): """get home page for user""" @@ -506,7 +502,11 @@ def import_doclist(path, ignore_links=False, ignore_insert=False, insert=False): def copy_doc(doc): import copy - d = doc.as_dict() + if not isinstance(doc, dict): + d = doc.as_dict() + else: + d = doc + newdoc = get_doc(copy.deepcopy(d)) newdoc.name = None newdoc.set("__islocal", 1) @@ -601,10 +601,19 @@ def get_template(path): def get_website_route(doctype, name): return db.get_value("Website Route", {"ref_doctype": doctype, "docname": name}) -def add_version(doclist): - bean({ +def add_version(doc): + get_doc({ "doctype": "Version", - "ref_doctype": doclist[0].get("doctype"), - "docname": doclist[0].get("name"), - "doclist_json": json.dumps([d.fields for d in doclist]) + "ref_doctype": doc.doctype, + "docname": doc.name, + "doclist_json": json.dumps(doc.as_dict(), indent=1, sort_keys=True) }).insert(ignore_permissions=True) + +def get_test_records(doctype): + from frappe.modules import get_doctype_module, get_module_path + path = os.path.join(get_module_path(get_doctype_module(doctype)), "doctype", scrub(doctype), "test_records.json") + if os.path.exists(path): + with open(path, "r") as f: + return json.loads(f.read()) + else: + return [] \ No newline at end of file diff --git a/frappe/boot.py b/frappe/boot.py index 4718039dbc..f6d75f97f9 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -8,7 +8,6 @@ bootstrap client session import frappe import frappe.defaults -import frappe.model.doc import frappe.widgets.page import json diff --git a/frappe/cli.py b/frappe/cli.py index d191de2397..aaf9ae48ec 100755 --- a/frappe/cli.py +++ b/frappe/cli.py @@ -66,11 +66,24 @@ def cmd(fn): def run(fn, args): + if args.get("profile") and fn!="serve": + import cProfile, pstats, StringIO + pr = cProfile.Profile() + pr.enable() + if isinstance(args.get(fn), (list, tuple)): out = globals().get(fn)(*args.get(fn), **args) else: out = globals().get(fn)(**args) - + + if args.get("profile") and fn!="serve": + pr.disable() + s = StringIO.StringIO() + sortby = 'cumulative' + ps = pstats.Stats(pr, stream=s).sort_stats(sortby) + ps.print_stats() + print s.getvalue() + return out def get_function(args): @@ -660,27 +673,12 @@ def smtp_debug_server(): os.execv(python, [python, '-m', "smtpd", "-n", "-c", "DebuggingServer", "localhost:25"]) @cmd -def run_tests(app=None, module=None, doctype=None, verbose=False, profile=False): +def run_tests(app=None, module=None, doctype=None, verbose=False): import frappe.test_runner - def _run(): - ret = frappe.test_runner.main(app and app[0], module and module[0], doctype and doctype[0], verbose) - if len(ret.failures) > 0 or len(ret.errors) > 0: - exit(1) - - if profile: - import cProfile, pstats, StringIO - pr = cProfile.Profile() - pr.enable() - _run() - pr.disable() - s = StringIO.StringIO() - sortby = 'cumulative' - ps = pstats.Stats(pr, stream=s).sort_stats(sortby) - ps.print_stats() - print s.getvalue() - else: - _run() + ret = frappe.test_runner.main(app and app[0], module and module[0], doctype and doctype[0], verbose) + if len(ret.failures) > 0 or len(ret.errors) > 0: + exit(1) @cmd def serve(port=8000, profile=False, sites_path='.', site=None): diff --git a/frappe/core/doctype/bulk_email/bulk_email.txt b/frappe/core/doctype/bulk_email/bulk_email.json similarity index 98% rename from frappe/core/doctype/bulk_email/bulk_email.txt rename to frappe/core/doctype/bulk_email/bulk_email.json index 8eb0d162bb..782686f625 100644 --- a/frappe/core/doctype/bulk_email/bulk_email.txt +++ b/frappe/core/doctype/bulk_email/bulk_email.json @@ -42,7 +42,7 @@ "options": "DocType", "permlevel": 0, "read_only": 1, - "reqd": 1 + "reqd": 0 }, { "fieldname": "ref_docname", @@ -50,7 +50,7 @@ "label": "Reference DocName", "permlevel": 0, "read_only": 1, - "reqd": 1 + "reqd": 0 } ], "icon": "icon-envelope", diff --git a/frappe/core/doctype/comment/comment.txt b/frappe/core/doctype/comment/comment.json similarity index 100% rename from frappe/core/doctype/comment/comment.txt rename to frappe/core/doctype/comment/comment.json diff --git a/frappe/core/doctype/communication/communication.txt b/frappe/core/doctype/communication/communication.json similarity index 100% rename from frappe/core/doctype/communication/communication.txt rename to frappe/core/doctype/communication/communication.json diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 57a6ce6270..b17780da83 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -67,7 +67,7 @@ def _make(doctype=None, name=None, content=None, subject=None, sent_or_received d.recipients = recipients # add as child - sent_via = frappe.get_obj(doctype, name) + sent_via = frappe.get_doc(doctype, name) d.parent = name d.parenttype = doctype d.parentfield = "communications" diff --git a/frappe/core/doctype/control_panel/control_panel.txt b/frappe/core/doctype/control_panel/control_panel.json similarity index 100% rename from frappe/core/doctype/control_panel/control_panel.txt rename to frappe/core/doctype/control_panel/control_panel.json diff --git a/frappe/core/doctype/custom_field/custom_field.txt b/frappe/core/doctype/custom_field/custom_field.json similarity index 100% rename from frappe/core/doctype/custom_field/custom_field.txt rename to frappe/core/doctype/custom_field/custom_field.json diff --git a/frappe/core/doctype/custom_field/custom_field.py b/frappe/core/doctype/custom_field/custom_field.py index ab38710454..e4660955a2 100644 --- a/frappe/core/doctype/custom_field/custom_field.py +++ b/frappe/core/doctype/custom_field/custom_field.py @@ -23,13 +23,8 @@ class CustomField(Document): cstr(self.label).lower().replace(' ','_')) def validate(self): - from frappe.model.doctype import get - temp_doclist = get(self.dt).get_parent_doclist() - - # set idx if not self.idx: - max_idx = max(d.idx for d in temp_doclist if d.doctype=='DocField') - self.idx = cint(max_idx) + 1 + self.idx = len(frappe.get_meta(self.dt).get("fields")) + 1 def on_update(self): # validate field @@ -84,16 +79,13 @@ def get_fields_label(dt=None, form=1): """ import frappe from frappe.utils import cstr - import frappe.model.doctype fieldname = None if not dt: dt = frappe.form_dict.get('doctype') fieldname = frappe.form_dict.get('fieldname') if not dt: return "" - doclist = frappe.model.doctype.get(dt) - docfields = sorted(doclist.get({"parent": dt, "doctype": "DocField"}), - key=lambda d: d.idx) + docfields = frappe.get_meta(dt).get("fields") if fieldname: idx_label_list = [cstr(d.label) or cstr(d.fieldname) or cstr(d.fieldtype) diff --git a/frappe/core/doctype/custom_script/custom_script.txt b/frappe/core/doctype/custom_script/custom_script.json similarity index 100% rename from frappe/core/doctype/custom_script/custom_script.txt rename to frappe/core/doctype/custom_script/custom_script.json diff --git a/frappe/core/doctype/customize_form/customize_form.txt b/frappe/core/doctype/customize_form/customize_form.json similarity index 100% rename from frappe/core/doctype/customize_form/customize_form.txt rename to frappe/core/doctype/customize_form/customize_form.json diff --git a/frappe/core/doctype/customize_form/customize_form.py b/frappe/core/doctype/customize_form/customize_form.py index a30899a5e8..66829dfb26 100644 --- a/frappe/core/doctype/customize_form/customize_form.py +++ b/frappe/core/doctype/customize_form/customize_form.py @@ -57,35 +57,11 @@ class CustomizeForm(Document): self.clear() if self.doc_type: - - for d in self.get_ref_doclist(): - if d.doctype=='DocField': - new = self.append('fields', {}) - self.set( - { - 'list': self.docfield_properties, - 'doc' : d, - 'doc_to_set': new - } - ) - elif d.doctype=='DocType': - self.set({ 'list': self.doctype_properties, 'doc': d }) - - - def get_ref_doclist(self): - """ - * Gets doclist of type self.doc_type - * Applies property setter properties on the doclist - * returns the modified doclist - """ - from frappe.model.doctype import get - - ref_doclist = get(self.doc_type) - ref_doclist = frappe.doclist([ref_doclist[0]] - + ref_doclist.get({"parent": self.doc_type})) - - return ref_doclist - + meta = frappe.get_meta(self.doc_type) + for d in meta.get("fields"): + new = self.append('fields', {}) + self.set({ 'list': self.docfield_properties, 'doc' : d, 'doc_to_set': new }) + self.set({ 'list': self.doctype_properties, 'doc': d }) def clear(self): """ @@ -129,9 +105,9 @@ class CustomizeForm(Document): from frappe.model import doc from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype - this_doclist = frappe.doclist([self] + self.doclist) - ref_doclist = self.get_ref_doclist() - dt_doclist = doc.get('DocType', self.doc_type) + this_doclist = self + ref_doclist = frappe.get_meta(self.doc_type) + dt_doclist = frappe.get_doc('DocType', self.doc_type) # get a list of property setter docs self.idx_dirty = False diff --git a/frappe/core/doctype/customize_form_field/customize_form_field.txt b/frappe/core/doctype/customize_form_field/customize_form_field.json similarity index 100% rename from frappe/core/doctype/customize_form_field/customize_form_field.txt rename to frappe/core/doctype/customize_form_field/customize_form_field.json diff --git a/frappe/core/doctype/default_home_page/default_home_page.txt b/frappe/core/doctype/default_home_page/default_home_page.json similarity index 100% rename from frappe/core/doctype/default_home_page/default_home_page.txt rename to frappe/core/doctype/default_home_page/default_home_page.json diff --git a/frappe/core/doctype/defaultvalue/defaultvalue.txt b/frappe/core/doctype/defaultvalue/defaultvalue.json similarity index 100% rename from frappe/core/doctype/defaultvalue/defaultvalue.txt rename to frappe/core/doctype/defaultvalue/defaultvalue.json diff --git a/frappe/core/doctype/defaultvalue/defaultvalue.py b/frappe/core/doctype/defaultvalue/defaultvalue.py index 66b97bdbb4..b2669077b7 100644 --- a/frappe/core/doctype/defaultvalue/defaultvalue.py +++ b/frappe/core/doctype/defaultvalue/defaultvalue.py @@ -6,7 +6,7 @@ import frappe from frappe.model.document import Document -class Defaultvalue(Document): +class DefaultValue(Document): pass def on_doctype_update(): diff --git a/frappe/core/doctype/docfield/docfield.txt b/frappe/core/doctype/docfield/docfield.json similarity index 100% rename from frappe/core/doctype/docfield/docfield.txt rename to frappe/core/doctype/docfield/docfield.json diff --git a/frappe/core/doctype/docperm/docperm.txt b/frappe/core/doctype/docperm/docperm.json similarity index 100% rename from frappe/core/doctype/docperm/docperm.txt rename to frappe/core/doctype/docperm/docperm.json diff --git a/frappe/core/doctype/doctype/doctype.txt b/frappe/core/doctype/doctype/doctype.json similarity index 100% rename from frappe/core/doctype/doctype/doctype.txt rename to frappe/core/doctype/doctype/doctype.json diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 6f91bc77c5..916351a8f2 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -81,8 +81,8 @@ class DocType(Document): # update index if not self.custom: - from frappe.model.code import load_doctype_module - module = load_doctype_module( self.name, self.module) + from frappe.modules import load_doctype_module + module = load_doctype_module(self.name, self.module) if hasattr(module, "on_doctype_update"): module.on_doctype_update() frappe.clear_cache(doctype=self.name) @@ -159,9 +159,7 @@ class DocType(Document): return max_idx and max_idx[0][0] or 0 def validate_fields_for_doctype(doctype): - from frappe.model.doctype import get - validate_fields(get(doctype, cached=False).get({"parent":doctype, - "doctype":"DocField"})) + validate_fields(frappe.get_meta(doctype).get("fields")) def validate_fields(fields): def check_illegal_characters(fieldname): @@ -224,10 +222,8 @@ def validate_fields(fields): check_min_items_in_list(fields) def validate_permissions_for_doctype(doctype, for_remove=False): - from frappe.model.doctype import get - validate_permissions(get(doctype, cached=False).get({"parent":doctype, - "doctype":"DocPerm"}), for_remove) - + validate_permissions(frappe.get_meta(doctype, cached=False).get("permissions"), for_remove) + def validate_permissions(permissions, for_remove=False): doctype = permissions and permissions[0].parent issingle = issubmittable = isimportable = False diff --git a/frappe/core/doctype/event/event.txt b/frappe/core/doctype/event/event.json similarity index 100% rename from frappe/core/doctype/event/event.txt rename to frappe/core/doctype/event/event.json diff --git a/frappe/core/doctype/event/event.py b/frappe/core/doctype/event/event.py index fe1d30d35f..2923a778ea 100644 --- a/frappe/core/doctype/event/event.py +++ b/frappe/core/doctype/event/event.py @@ -27,21 +27,14 @@ def get_permission_query_conditions(): "roles": "', '".join(frappe.get_roles(frappe.session.user)) } -def has_permission(doc, bean=None): +def has_permission(doc): if doc.event_type=="Public" or doc.owner==frappe.session.user: return True - - # need full doclist to check roles and users - if not bean: - bean = frappe.get_doc("Event", doc.name) - - if len(bean.doclist)==1: - return False - - if bean.doclist.get({"doctype":"Event User", "person":frappe.session.user}): + + if doc.get("event_individuals", {"person":frappe.session.user}): return True - if bean.doclist.get({"doctype":"Event Role", "role":("in", frappe.get_roles())}): + if doc.get("event_roles", {"role":("in", frappe.get_roles())}): return True return False diff --git a/frappe/core/doctype/event/test_event.py b/frappe/core/doctype/event/test_event.py index ddc2563ec3..4f922a0d3a 100644 --- a/frappe/core/doctype/event/test_event.py +++ b/frappe/core/doctype/event/test_event.py @@ -3,36 +3,12 @@ """Use blog post test to test permission restriction logic""" -test_records = [ - [{ - "doctype": "Event", - "subject":"_Test Event 1", - "starts_on": "2014-01-01", - "event_type": "Public", - }], - [{ - "doctype": "Event", - "starts_on": "2014-01-01", - "subject":"_Test Event 2", - "event_type": "Private", - }], - [{ - "doctype": "Event", - "starts_on": "2014-01-01", - "subject":"_Test Event 3", - "event_type": "Private", - }, { - "doctype": "Event User", - "parentfield": "event_individuals", - "person": "test1@example.com" - }], - -] - import frappe import frappe.defaults import unittest +test_records = frappe.get_test_records('Event') + class TestEvent(unittest.TestCase): # def setUp(self): # user = frappe.get_doc("User", "test1@example.com") @@ -63,5 +39,4 @@ class TestEvent(unittest.TestCase): subjects = [r.subject for r in res] self.assertTrue("_Test Event 1" in subjects) self.assertTrue("_Test Event 3" in subjects) - self.assertFalse("_Test Event 2" in subjects) - \ No newline at end of file + self.assertFalse("_Test Event 2" in subjects) \ No newline at end of file diff --git a/frappe/core/doctype/event_role/event_role.txt b/frappe/core/doctype/event_role/event_role.json similarity index 100% rename from frappe/core/doctype/event_role/event_role.txt rename to frappe/core/doctype/event_role/event_role.json diff --git a/frappe/core/doctype/event_user/event_user.txt b/frappe/core/doctype/event_user/event_user.json similarity index 100% rename from frappe/core/doctype/event_user/event_user.txt rename to frappe/core/doctype/event_user/event_user.json diff --git a/frappe/core/doctype/file_data/file_data.txt b/frappe/core/doctype/file_data/file_data.json similarity index 100% rename from frappe/core/doctype/file_data/file_data.txt rename to frappe/core/doctype/file_data/file_data.json diff --git a/frappe/core/doctype/letter_head/letter_head.txt b/frappe/core/doctype/letter_head/letter_head.json similarity index 100% rename from frappe/core/doctype/letter_head/letter_head.txt rename to frappe/core/doctype/letter_head/letter_head.json diff --git a/frappe/core/doctype/letter_head/test_letter_head.py b/frappe/core/doctype/letter_head/test_letter_head.py index a6b6086caf..15899e2b27 100644 --- a/frappe/core/doctype/letter_head/test_letter_head.py +++ b/frappe/core/doctype/letter_head/test_letter_head.py @@ -1,4 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -test_records = [] \ No newline at end of file +import frappe + +test_records = frappe.get_test_records('Letter Head') \ No newline at end of file diff --git a/frappe/core/doctype/module_def/module_def.txt b/frappe/core/doctype/module_def/module_def.json similarity index 100% rename from frappe/core/doctype/module_def/module_def.txt rename to frappe/core/doctype/module_def/module_def.json diff --git a/frappe/core/doctype/notification_count/notification_count.txt b/frappe/core/doctype/notification_count/notification_count.json similarity index 100% rename from frappe/core/doctype/notification_count/notification_count.txt rename to frappe/core/doctype/notification_count/notification_count.json diff --git a/frappe/core/doctype/outgoing_email_settings/outgoing_email_settings.txt b/frappe/core/doctype/outgoing_email_settings/outgoing_email_settings.json similarity index 100% rename from frappe/core/doctype/outgoing_email_settings/outgoing_email_settings.txt rename to frappe/core/doctype/outgoing_email_settings/outgoing_email_settings.json diff --git a/frappe/core/doctype/page/page.txt b/frappe/core/doctype/page/page.json similarity index 100% rename from frappe/core/doctype/page/page.txt rename to frappe/core/doctype/page/page.json diff --git a/frappe/core/doctype/page_role/page_role.txt b/frappe/core/doctype/page_role/page_role.json similarity index 100% rename from frappe/core/doctype/page_role/page_role.txt rename to frappe/core/doctype/page_role/page_role.json diff --git a/frappe/core/doctype/patch_log/patch_log.txt b/frappe/core/doctype/patch_log/patch_log.json similarity index 100% rename from frappe/core/doctype/patch_log/patch_log.txt rename to frappe/core/doctype/patch_log/patch_log.json diff --git a/frappe/core/doctype/print_format/print_format.txt b/frappe/core/doctype/print_format/print_format.json similarity index 100% rename from frappe/core/doctype/print_format/print_format.txt rename to frappe/core/doctype/print_format/print_format.json diff --git a/frappe/core/doctype/property_setter/property_setter.txt b/frappe/core/doctype/property_setter/property_setter.json similarity index 100% rename from frappe/core/doctype/property_setter/property_setter.txt rename to frappe/core/doctype/property_setter/property_setter.json diff --git a/frappe/core/doctype/report/report.txt b/frappe/core/doctype/report/report.json similarity index 100% rename from frappe/core/doctype/report/report.txt rename to frappe/core/doctype/report/report.json diff --git a/frappe/core/doctype/role/role.txt b/frappe/core/doctype/role/role.json similarity index 100% rename from frappe/core/doctype/role/role.txt rename to frappe/core/doctype/role/role.json diff --git a/frappe/core/doctype/role/test_role.py b/frappe/core/doctype/role/test_role.py index b2c9fca743..cda62d7a2a 100644 --- a/frappe/core/doctype/role/test_role.py +++ b/frappe/core/doctype/role/test_role.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -test_records = [ - [{"doctype": "Role", "role_name":"_Test Role"}], - [{"doctype": "Role", "role_name":"_Test Role 2"}] -] \ No newline at end of file +import frappe + +test_records = frappe.get_test_records('Role') \ No newline at end of file diff --git a/frappe/core/doctype/scheduler_log/scheduler_log.txt b/frappe/core/doctype/scheduler_log/scheduler_log.json similarity index 100% rename from frappe/core/doctype/scheduler_log/scheduler_log.txt rename to frappe/core/doctype/scheduler_log/scheduler_log.json diff --git a/frappe/core/doctype/social_login_keys/social_login_keys.txt b/frappe/core/doctype/social_login_keys/social_login_keys.json similarity index 100% rename from frappe/core/doctype/social_login_keys/social_login_keys.txt rename to frappe/core/doctype/social_login_keys/social_login_keys.json diff --git a/frappe/core/doctype/tag/tag.txt b/frappe/core/doctype/tag/tag.json similarity index 100% rename from frappe/core/doctype/tag/tag.txt rename to frappe/core/doctype/tag/tag.json diff --git a/frappe/core/doctype/todo/todo.txt b/frappe/core/doctype/todo/todo.json similarity index 100% rename from frappe/core/doctype/todo/todo.txt rename to frappe/core/doctype/todo/todo.json diff --git a/frappe/core/doctype/todo/todo.py b/frappe/core/doctype/todo/todo.py index 1146c12e04..489e24807f 100644 --- a/frappe/core/doctype/todo/todo.py +++ b/frappe/core/doctype/todo/todo.py @@ -6,7 +6,7 @@ import frappe from frappe.model.document import Document -class Todo(Document): +class ToDo(Document): def validate(self): if self.is_new(): diff --git a/frappe/core/doctype/user/test_user.py b/frappe/core/doctype/user/test_user.py index bc3a18b018..7ab7ef42d8 100644 --- a/frappe/core/doctype/user/test_user.py +++ b/frappe/core/doctype/user/test_user.py @@ -5,13 +5,15 @@ import frappe, unittest from frappe.model.delete_doc import delete_doc, LinkExistsError +test_records = frappe.get_test_records('User') + class TestUser(unittest.TestCase): def test_delete(self): self.assertRaises(LinkExistsError, delete_doc, "Role", "_Test Role 2") frappe.db.sql("""delete from tabUserRole where role='_Test Role 2'""") delete_doc("Role","_Test Role 2") - user = frappe.get_doc(copy=test_records[1]) + user = frappe.copy_doc(test_records[1]) user.email = "_test@example.com" user.insert() @@ -23,7 +25,7 @@ class TestUser(unittest.TestCase): ("_test@example.com",))) from frappe.core.doctype.role.test_role import test_records as role_records - frappe.get_doc(copy=role_records[1]).insert() + frappe.copy_doc(role_records[1]).insert() def test_get_value(self): self.assertEquals(frappe.db.get_value("User", "test@example.com"), "test@example.com") @@ -46,61 +48,4 @@ class TestUser(unittest.TestCase): frappe.db.set_value("Control Panel", "Control Panel", "_test", "_test_val") self.assertEquals(frappe.db.get_value("Control Panel", None, "_test"), "_test_val") self.assertEquals(frappe.db.get_value("Control Panel", "Control Panel", "_test"), "_test_val") - - -test_records = [ - [ - { - "doctype":"User", - "email": "test@example.com", - "first_name": "_Test", - "new_password": "testpassword", - "enabled": 1 - }, - { - "doctype":"UserRole", - "parentfield":"user_roles", - "role": "_Test Role" - }, - { - "doctype":"UserRole", - "parentfield":"user_roles", - "role": "System Manager" - } - ], - [ - { - "doctype":"User", - "email": "test1@example.com", - "first_name": "_Test1", - "new_password": "testpassword" - } - ], - [ - { - "doctype":"User", - "email": "test2@example.com", - "first_name": "_Test2", - "new_password": "testpassword" - } - ], - [ - { - "doctype":"User", - "email": "testdelete@example.com", - "first_name": "_Test", - "new_password": "testpassword", - "enabled": 1 - }, - { - "doctype":"UserRole", - "parentfield":"user_roles", - "role": "_Test Role 2" - }, - { - "doctype":"UserRole", - "parentfield":"user_roles", - "role": "System Manager" - } - ], -] \ No newline at end of file + \ No newline at end of file diff --git a/frappe/core/doctype/user/user.txt b/frappe/core/doctype/user/user.json similarity index 100% rename from frappe/core/doctype/user/user.txt rename to frappe/core/doctype/user/user.json diff --git a/frappe/core/doctype/userrole/userrole.txt b/frappe/core/doctype/userrole/userrole.json similarity index 100% rename from frappe/core/doctype/userrole/userrole.txt rename to frappe/core/doctype/userrole/userrole.json diff --git a/frappe/core/doctype/userrole/userrole.py b/frappe/core/doctype/userrole/userrole.py index d72aa29048..b9ff4b704f 100644 --- a/frappe/core/doctype/userrole/userrole.py +++ b/frappe/core/doctype/userrole/userrole.py @@ -7,8 +7,7 @@ from frappe.utils import cint from frappe.model.document import Document -class Userrole(Document): - +class UserRole(Document): def validate(self): if cint(self.get("__islocal")) and frappe.db.exists("UserRole", { "parent": self.parent, "role": self.role}): diff --git a/frappe/core/doctype/version/version.txt b/frappe/core/doctype/version/version.json similarity index 100% rename from frappe/core/doctype/version/version.txt rename to frappe/core/doctype/version/version.json diff --git a/frappe/core/doctype/version/version.py b/frappe/core/doctype/version/version.py index f3bdccbf8e..5ddb2996d6 100644 --- a/frappe/core/doctype/version/version.py +++ b/frappe/core/doctype/version/version.py @@ -17,15 +17,13 @@ def restore(version): raise frappe.PermissionError version = frappe.get_doc("Version", version) - doclist = json.loads(version.doclist_json) + docdict = json.loads(version.doclist_json) # check if renamed - if doclist[0].get("name") != version.docname: - doclist[0]["name"] = version.docname - for d in doclist[1:]: - d["parent"] = version.docname + if docdict.get("name") != version.docname: + docdict["name"] = version.docname - doclist[0]["modified"] = frappe.db.get_value(version.ref_doctype, version.docname, "modified") + docdict["modified"] = frappe.db.get_value(version.ref_doctype, version.docname, "modified") # overwrite - frappe.get_doc(doclist).save() \ No newline at end of file + frappe.get_doc(docdict).save() \ No newline at end of file diff --git a/frappe/core/doctype/workflow/workflow.txt b/frappe/core/doctype/workflow/workflow.json similarity index 100% rename from frappe/core/doctype/workflow/workflow.txt rename to frappe/core/doctype/workflow/workflow.json diff --git a/frappe/core/doctype/workflow_action/workflow_action.txt b/frappe/core/doctype/workflow_action/workflow_action.json similarity index 100% rename from frappe/core/doctype/workflow_action/workflow_action.txt rename to frappe/core/doctype/workflow_action/workflow_action.json diff --git a/frappe/core/doctype/workflow_document_state/workflow_document_state.txt b/frappe/core/doctype/workflow_document_state/workflow_document_state.json similarity index 100% rename from frappe/core/doctype/workflow_document_state/workflow_document_state.txt rename to frappe/core/doctype/workflow_document_state/workflow_document_state.json diff --git a/frappe/core/doctype/workflow_state/test_workflow_state.py b/frappe/core/doctype/workflow_state/test_workflow_state.py index a6b6086caf..2bbe87dfed 100644 --- a/frappe/core/doctype/workflow_state/test_workflow_state.py +++ b/frappe/core/doctype/workflow_state/test_workflow_state.py @@ -1,4 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -test_records = [] \ No newline at end of file +import frappe + +test_records = frappe.get_test_records('Workflow State') \ No newline at end of file diff --git a/frappe/core/doctype/workflow_state/workflow_state.txt b/frappe/core/doctype/workflow_state/workflow_state.json similarity index 100% rename from frappe/core/doctype/workflow_state/workflow_state.txt rename to frappe/core/doctype/workflow_state/workflow_state.json diff --git a/frappe/core/doctype/workflow_transition/workflow_transition.txt b/frappe/core/doctype/workflow_transition/workflow_transition.json similarity index 100% rename from frappe/core/doctype/workflow_transition/workflow_transition.txt rename to frappe/core/doctype/workflow_transition/workflow_transition.json diff --git a/frappe/core/page/applications/applications.txt b/frappe/core/page/applications/applications.json similarity index 100% rename from frappe/core/page/applications/applications.txt rename to frappe/core/page/applications/applications.json diff --git a/frappe/core/page/data_import_tool/data_import_tool.txt b/frappe/core/page/data_import_tool/data_import_tool.json similarity index 100% rename from frappe/core/page/data_import_tool/data_import_tool.txt rename to frappe/core/page/data_import_tool/data_import_tool.json diff --git a/frappe/core/page/data_import_tool/data_import_tool.py b/frappe/core/page/data_import_tool/data_import_tool.py index 0537c18de4..6113ed9601 100644 --- a/frappe/core/page/data_import_tool/data_import_tool.py +++ b/frappe/core/page/data_import_tool/data_import_tool.py @@ -5,8 +5,6 @@ from __future__ import unicode_literals import frappe, json, os import frappe.permissions -import frappe.model.doctype -from frappe.model.meta import get_table_fields from frappe.utils import cstr from frappe.utils.datautils import UnicodeWriter, check_record, import_doc, getlink, cint, flt from frappe import _ @@ -31,9 +29,7 @@ def get_doctypes(): @frappe.whitelist() def get_doctype_options(): doctype = frappe.form_dict['doctype'] - return [doctype] + filter(None, map(lambda d: \ - d.doctype=='DocField' and d.fieldtype=='Table' and d.options or None, - frappe.model.doctype.get(doctype))) + return [doctype] + [d.options for d in frappe.get_meta(doctype).get_table_fields()] @frappe.whitelist() def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data="No"): @@ -47,7 +43,7 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data if all_doctypes: doctype_parentfield = {} child_doctypes = [] - for d in get_table_fields(doctype): + for d in frappe.get_meta(doctype).get_table_fields(): child_doctypes.append(d[0]) doctype_parentfield[d[0]] = d[1] @@ -74,10 +70,10 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data w.writerow(['If you are updating, please select "Overwrite" else existing rows will not be deleted.']) def build_field_columns(dt): - doctype_dl = frappe.model.doctype.get(dt) + meta = frappe.get_meta(dt) tablecolumns = filter(None, - [doctype_dl.get_field(f[0]) for f in frappe.db.sql('desc `tab%s`' % dt)]) + [meta.get_field(f[0]) for f in frappe.db.sql('desc `tab%s`' % dt)]) tablecolumns.sort(lambda a, b: a.idx - b.idx) @@ -373,7 +369,6 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, frappe.db.begin() if not overwrite: overwrite = params.get('overwrite') - doctype_dl = frappe.model.doctype.get(doctype) # delete child rows (if parenttype) if parenttype and overwrite: @@ -396,7 +391,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, if len(doclist) > 1: for d in doclist: # ignoring parent check as it will be automatically added - check_record(d, None, doctype_dl) + check_record(d) if overwrite and frappe.db.exists(doctype, doclist[0]["name"]): bean = frappe.get_doc(doctype, doclist[0]["name"]) @@ -413,7 +408,7 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, bean.submit() ret.append('Submitted row (#%d) %s' % (row_idx + 1, getlink(bean.doctype, bean.name))) else: - check_record(doclist[0], parenttype, doctype_dl) + check_record(doclist[0]) if parenttype: # child doc @@ -469,8 +464,8 @@ def get_parent_field(doctype, parenttype): # get parentfield if parenttype: - for d in frappe.model.doctype.get(parenttype): - if d.fieldtype=='Table' and d.options==doctype: + for d in frappe.get_meta(parenttype).get_table_fields(): + if d.options==doctype: parentfield = d.fieldname break diff --git a/frappe/core/page/desktop/desktop.txt b/frappe/core/page/desktop/desktop.json similarity index 100% rename from frappe/core/page/desktop/desktop.txt rename to frappe/core/page/desktop/desktop.json diff --git a/frappe/core/page/messages/messages.txt b/frappe/core/page/messages/messages.json similarity index 100% rename from frappe/core/page/messages/messages.txt rename to frappe/core/page/messages/messages.json diff --git a/frappe/core/page/modules_setup/modules_setup.txt b/frappe/core/page/modules_setup/modules_setup.json similarity index 100% rename from frappe/core/page/modules_setup/modules_setup.txt rename to frappe/core/page/modules_setup/modules_setup.json diff --git a/frappe/core/page/permission_manager/permission_manager.txt b/frappe/core/page/permission_manager/permission_manager.json similarity index 100% rename from frappe/core/page/permission_manager/permission_manager.txt rename to frappe/core/page/permission_manager/permission_manager.json diff --git a/frappe/core/page/user_properties/user_properties.txt b/frappe/core/page/user_properties/user_properties.json similarity index 100% rename from frappe/core/page/user_properties/user_properties.txt rename to frappe/core/page/user_properties/user_properties.json diff --git a/frappe/core/report/todo/todo.txt b/frappe/core/report/todo/todo.json similarity index 100% rename from frappe/core/report/todo/todo.txt rename to frappe/core/report/todo/todo.json diff --git a/frappe/database.py b/frappe/database.py index c7970e3375..14d9a6c903 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -9,6 +9,7 @@ import MySQLdb import warnings import frappe import datetime +from frappe.utils import now class Database: """ @@ -385,7 +386,6 @@ class Database: return {} def set_value(self, dt, dn, field, val, modified=None, modified_by=None): - from frappe.utils import now if not modified: modified = now() if not modified_by: @@ -409,7 +409,9 @@ class Database: def set(self, doc, field, val): doc.set(field, val) - frappe.db.set_value(doc.doctype, doc.name, field, val) + doc.set("modified", now()) + doc.set("modified_by", frappe.session.user) + frappe.db.set_value(doc.doctype, doc.name, field, val, doc.modified, doc.modified_by) def touch(self, doctype, docname): from frappe.utils import now diff --git a/frappe/memc.py b/frappe/memc.py index 6471cca959..4c3f030049 100644 --- a/frappe/memc.py +++ b/frappe/memc.py @@ -10,13 +10,16 @@ class MClient(memcache.Client): return (frappe.conf.db_name + ":" + key.replace(" ", "_")).encode('utf-8') def set_value(self, key, val): + frappe.local.cache[key] = val self.set(self.n(key), val) def get_value(self, key, builder=None): - val = self.get(self.n(key)) - if not val and builder: - val = builder() - self.set_value(key, val) + val = frappe.local.cache.get(key) + if not val: + val = self.get(self.n(key)) + if not val and builder: + val = builder() + self.set_value(key, val) return val def delete_value(self, keys): @@ -24,3 +27,5 @@ class MClient(memcache.Client): keys = (keys,) for key in keys: self.delete(self.n(key)) + if key in frappe.local.cache: + del frappe.local.cache[key] diff --git a/frappe/model/__init__.py b/frappe/model/__init__.py index 40a9e624a9..2c760f33ae 100644 --- a/frappe/model/__init__.py +++ b/frappe/model/__init__.py @@ -29,8 +29,6 @@ def rename(doctype, old, new, debug=False): frappe.model.rename_doc.rename_doc(doctype, old, new, debug) def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfields=[]): - import frappe.model.doc - if not tarfields: tarfields = srcfields l = [] diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index adfb3c2706..398f51f0ee 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -5,26 +5,29 @@ 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.db_schema import type_map from frappe.model.naming import set_new_name class BaseDocument(object): - def __init__(self, d, valid_columns=None): - self.update(d, valid_columns=valid_columns) + def __init__(self, d): + self.update(d) def __getattr__(self, key): - if self.__dict__.has_key(key): - return self.__dict__[key] + try: + return super(BaseDocument, self).__getattr__(key) + except AttributeError: + if not key.startswith("__") and key not in ("doctype", "_meta", "meta") and key in self.meta.get_valid_columns(): + return None + else: + raise - if key!= "_valid_columns" and key in self.get_valid_columns(): - return None + @property + def meta(self): + if not hasattr(self, "_meta"): + self._meta = frappe.get_meta(self.doctype) + + return self._meta - raise AttributeError(key) - - def update(self, d, valid_columns=None): - if valid_columns: - self.__dict__["_valid_columns"] = valid_columns + def update(self, d): if "doctype" in d: self.set("doctype", d.get("doctype")) for key, value in d.iteritems(): @@ -42,7 +45,7 @@ class BaseDocument(object): else: value = self.__dict__.get(key, default) - if value is None and key!="_meta" and key in (d.fieldname for d in self.get_table_fields()): + if value is None and key!="_meta" and key in (d.fieldname for d in self.meta.get_table_fields()): self.set(key, []) value = self.__dict__.get(key) @@ -50,11 +53,11 @@ class BaseDocument(object): else: return self.__dict__ - def set(self, key, value, valid_columns=None): + def set(self, key, value): if isinstance(value, list): tmp = [] for v in value: - tmp.append(self._init_child(v, key, valid_columns)) + tmp.append(self._init_child(v, key)) value = tmp self.__dict__[key] = value @@ -78,71 +81,45 @@ class BaseDocument(object): else: raise ValueError - def _init_child(self, value, key, valid_columns=None): + def _init_child(self, value, key): if not self.doctype: return value if not isinstance(value, BaseDocument): - if not value.get("doctype"): + if not "doctype" in value: value["doctype"] = self.get_table_field_doctype(key) - if not value.get("doctype"): - raise AttributeError, key - value = BaseDocument(value, valid_columns=valid_columns) + if not value["doctype"]: + raise AttributeError, key + value = BaseDocument(value) value.parent = self.name value.parenttype = self.doctype value.parentfield = key if not value.idx: value.idx = len(self.get(key) or []) + 1 - + return value - @property - def doc(self): - return self - - @property - def meta(self): - if not self.get("_meta"): - self._meta = frappe.get_meta(self.doctype) - return self._meta - def get_valid_dict(self): d = {} - for fieldname in self.valid_columns: + for fieldname in self.meta.get_valid_columns(): d[fieldname] = self.get(fieldname) return d def is_new(self): return self.get("__islocal") - - @property - def valid_columns(self): - return self.get_valid_columns() - - def get_valid_columns(self): - if not hasattr(self, "_valid_columns"): - doctype = self.__dict__.get("doctype") - self._valid_columns = default_fields[1:] + \ - [df.fieldname for df in frappe.get_meta(doctype).get("fields") - if df.fieldtype in type_map] - - return self._valid_columns - + def as_dict(self): doc = self.get_valid_dict() doc["doctype"] = self.doctype - for df in self.get_table_fields(): + for df in self.meta.get_table_fields(): doc[df.fieldname] = [d.as_dict() for d in (self.get(df.fieldname) or [])] return doc - - def get_table_fields(self): - return self.meta.get('fields', {"fieldtype":"Table"}) - + def get_table_field_doctype(self, fieldname): - return self.meta.get("fields", {"fieldname":fieldname})[0].options + return self.meta.get_field(fieldname).options def get_parentfield_of_doctype(self, doctype): - fieldname = [df.fieldname for df in self.get_table_fields() if df.options==doctype] + fieldname = [df.fieldname for df in self.meta.get_table_fields() if df.options==doctype] return fieldname[0] if fieldname else None def db_insert(self): @@ -240,7 +217,7 @@ class BaseDocument(object): for fieldname in constants: if self.get(fieldname) != values.get(fieldname): frappe.throw("{0}: {1}".format(_("Value cannot be changed for"), - _(meta.get("fields", {"fieldname":fieldname})[0].label)), + _(self.meta.get_label(fieldname))), frappe.CannotChangeConstantError) def _filter(data, filters, limit=None): @@ -257,14 +234,14 @@ def _filter(data, filters, limit=None): fval = filters[f] if fval is True: - fval = ["not None", fval] + fval = ("not None", fval) elif fval is False: - fval = ["None", fval] + fval = ("None", fval) elif not isinstance(fval, (tuple, list)): if isinstance(fval, basestring) and fval.startswith("^"): - fval = ["^", fval[1:]] + fval = ("^", fval[1:]) else: - fval = ["=", fval] + fval = ("=", fval) if not frappe.compare(d.get(f), fval[0], fval[1]): add = False diff --git a/frappe/model/code.py b/frappe/model/code.py deleted file mode 100644 index 09644e623b..0000000000 --- a/frappe/model/code.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -from __future__ import unicode_literals -""" -This is where all the plug-in code is executed. The standard method for DocTypes is declaration of a -standardized `DocType` class that has the methods of any DocType. When an object is instantiated using the -`get_obj` method, it creates an instance of the `DocType` class of that particular DocType and sets the -`doc` and `doclist` attributes that represent the fields (properties) of that record. - -methods in following modules are imported for backward compatibility - - * frappe.* - * frappe.utils.* - * frappe.model.* - * frappe.model.bean.* -""" - -import frappe -from frappe.modules import get_doctype_module, load_doctype_module, get_module_name -import frappe.model.doc - -def get_obj(dt = None, dn = None, doc=None, doclist=None, with_children = 0): - import frappe.model.doc - if not doclist: doclist = [] - if dt: - if isinstance(dt, list): - return get_server_obj(dt[0], dt) - if isinstance(dt, frappe.model.Document): - return get_server_obj(dt, [dt]) - if not dn: - dn = dt - if with_children: - doclist = frappe.model.get(dt, dn, from_controller=1) - else: - doclist = frappe.model.get(dt, dn, with_children = 0, from_controller=1) - return get_server_obj(doclist[0], doclist) - else: - return get_server_obj(doc, doclist) - -def get_server_obj(doc, doclist = [], basedoctype = ''): - # for test - module = get_doctype_module(doc.doctype) - classname = doc.doctype.replace(" ", "") - return load_doctype_module(doc.doctype, module).DocType(doc, doclist) - -def run_server_obj(server_obj, method_name, arg=None): - """ - Executes a method (`method_name`) from the given object (`server_obj`) - """ - if server_obj and hasattr(server_obj, method_name): - if arg: - return getattr(server_obj, method_name)(arg) - else: - return getattr(server_obj, method_name)() - else: - raise Exception, 'No method %s' % method_name diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 96a13b97e8..1c9c263c6a 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -7,7 +7,6 @@ from __future__ import unicode_literals import frappe, json import frappe.defaults import frappe.permissions -import frappe.model.doctype from frappe.utils import cstr, flt class DatabaseQuery(object): diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 02638497f8..bdab3baee2 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -56,7 +56,7 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa return 'okay' -def check_permission_and_not_submitted(doctype, name, ignore_permissions=False): +def check_permission_and_not_submitted(doc, ignore_permissions=False): # permission if not ignore_permissions and frappe.session.user!="Administrator" and not doc.has_permission("cancel"): frappe.msgprint(_("User not allowed to delete."), raise_exception=True) diff --git a/frappe/model/document.py b/frappe/model/document.py index 7ab4e25f91..98d4e2109e 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -7,6 +7,7 @@ from frappe import _, msgprint from frappe.utils import cint, flt, cstr, now from frappe.modules import load_doctype_module from frappe.model.base_document import BaseDocument +from frappe.model.naming import set_new_name # once_only validation # methods @@ -23,15 +24,25 @@ def get_doc(arg1, arg2=None): if controller: return controller(arg1, arg2) - return Document(arg1, arg2) + raise ImportError, arg1 + +_classes = {} def get_controller(doctype): - module = load_doctype_module(doctype) - classname = doctype.replace(" ", "") - if hasattr(module, classname): - _class = getattr(module, classname) - if issubclass(_class, Document): - return getattr(module, classname) + if not doctype in _classes: + module = load_doctype_module(doctype) + classname = doctype.replace(" ", "") + if hasattr(module, classname): + _class = getattr(module, classname) + if issubclass(_class, Document): + _class = getattr(module, classname) + else: + raise ImportError, doctype + else: + raise ImportError, doctype + _classes[doctype] = _class + + return _classes[doctype] class Document(BaseDocument): def __init__(self, arg1, arg2=None): @@ -69,14 +80,20 @@ class Document(BaseDocument): if not d: frappe.throw("{}: {}, {}".format(_("Not Found"), self.doctype, self.name), frappe.DoesNotExistError) - self.update(d, valid_columns = d.keys()) + 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() - for df in self.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) if children: - self.set(df.fieldname, children, children[0].keys()) + self.set(df.fieldname, children) else: self.set(df.fieldname, []) @@ -95,7 +112,8 @@ class Document(BaseDocument): raise frappe.PermissionError self._set_defaults() self._set_docstatus_user_and_timestamp() - self._check_if_latest() + self.check_if_latest() + set_new_name(self) self.run_method("before_insert") self.run_before_save_methods() self._validate() @@ -127,7 +145,7 @@ class Document(BaseDocument): raise frappe.PermissionError self._set_docstatus_user_and_timestamp() - self._check_if_latest() + self.check_if_latest() self.run_before_save_methods() self._validate() @@ -147,7 +165,7 @@ class Document(BaseDocument): d.db_update() child_map.setdefault(d.doctype, []).append(d.name) - for df in self.get_table_fields(): + for df in self.meta.get_table_fields(): if df.options not in ignore_children_type: cnames = child_map.get(df.options) or [] if cnames: @@ -203,14 +221,14 @@ class Document(BaseDocument): self.set_missing_values(new_doc) # children - for df in self.get_table_fields(): + for df in self.meta.get_table_fields(): new_doc = frappe.new_doc(df.options) value = self.get(df.fieldname) if isinstance(value, list): for d in value: d.set_missing_values(new_doc) - def _check_if_latest(self): + def check_if_latest(self): conflict = False self._action = "save" if not self.get('__islocal'): diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index 6cb6c9bec7..f2f132ffcc 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -26,7 +26,7 @@ def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None, row_exists_for_parentfield = {} # children - for df in source_doc.get_table_fields(): + for df in source_doc.meta.get_table_fields(): source_child_doctype = df.options table_map = table_maps.get(source_child_doctype) if table_map: diff --git a/frappe/model/meta.py b/frappe/model/meta.py index b020cf36c6..b8f016aba1 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -6,23 +6,22 @@ from __future__ import unicode_literals import frappe, json from frappe.utils import cstr, cint -from frappe.model import integer_docfield_properties +from frappe.model import integer_docfield_properties, default_fields from frappe.model.document import Document from frappe.model.base_document import BaseDocument +from frappe.model.db_schema import type_map ###### def get_meta(doctype, cached=True): - # TODO: cache to be cleared - if cached and not frappe.flags.in_install_app: - if doctype not in frappe.local.meta: - frappe.local.meta[doctype] = frappe.cache().get_value("meta:" + doctype, lambda: Meta(doctype)) - return frappe.local.meta.get(doctype) + if cached: + return frappe.cache().get_value("meta:" + doctype, lambda: Meta(doctype)) else: return Meta(doctype) class Meta(Document): _metaclass = True + _fields = {} def __init__(self, doctype): super(Meta, self).__init__("DocType", doctype) @@ -32,7 +31,7 @@ class Meta(Document): except frappe.DoesNotExistError: if self.doctype=="DocType" and self.name in ("DocField", "DocPerm", "Role", "DocType", "Module Def"): fname = frappe.scrub(self.name) - with open(frappe.get_app_path("frappe", "core", "doctype", fname, fname + ".txt"), "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)) @@ -44,28 +43,38 @@ class Meta(Document): def get_link_fields(self): tmp = self.get("fields", {"fieldtype":"Link"}) - tmp.extend(self.get("fields", {"fieldtype":"Select", "options": "^link:"})) - return tmp + for df in self.get("fields", {"fieldtype":"Select", "options": "^link:"}): + tmp.append(frappe._dict({"fieldname":df.fieldname, "label":df.label, + "fieldtype":"Link", "options": df.options[5:]})) + return tmp def get_table_fields(self): - return [ - frappe._dict({"fieldname": "fields", "options": "DocField"}), - frappe._dict({"fieldname": "permissions", "options": "DocPerm"}) - ] - + if not hasattr(self, "_table_fields"): + if self.name!="DocType": + self._table_fields = self.get('fields', {"fieldtype":"Table"}) + else: + self._table_fields = doctype_table_fields + + return self._table_fields + def get_valid_columns(self): if not hasattr(self, "_valid_columns"): - doctype = self.__dict__.get("doctype") - self._valid_columns = frappe.db.get_table_columns(doctype) + if self.name in ("DocType", "DocField", "DocPerm"): + self._valid_columns = frappe.db.get_table_columns(self.name) + else: + self._valid_columns = default_fields[1:] + \ + [df.fieldname for df in self.get("fields") if df.fieldtype in type_map] return self._valid_columns - + def get_table_field_doctype(self, fieldname): return { "fields": "DocField", "permissions": "DocPerm"}.get(fieldname) def get_field(self, fieldname): - fields = self.get("fields", {"fieldname":fieldname}) - return fields[0] if fields else None + if not fieldname in self._fields: + fields = self.get("fields", {"fieldname":fieldname}) + self._fields[fieldname] = fields[0] if fields else frappe._dict() + return self._fields[fieldname] def get_label(self, fieldname): return self.get_field(fieldname).label @@ -158,6 +167,11 @@ class Meta(Document): return restricted_fields +doctype_table_fields = [ + frappe._dict({"fieldname": "fields", "options": "DocField"}), + frappe._dict({"fieldname": "permissions", "options": "DocPerm"}) +] + ####### def is_single(doctype): @@ -175,15 +189,6 @@ def get_parent_dt(dt): def set_fieldname(field_id, fieldname): frappe.db.set_value('DocField', field_id, 'fieldname', fieldname) -def get_link_fields(doctype): - """ - Returns list of link fields for a doctype in tuple (fieldname, options, label) - """ - import frappe.model.doctype - doclist = frappe.model.doctype.get(doctype) - return [(d.get('fieldname'), d.get('options'), d.get('label')) - for d in doclist.get_link_fields() if d.get('fieldname')!='owner'] - def get_table_fields(doctype): child_tables = [[d[0], d[1]] for d in frappe.db.sql("""select options, fieldname from tabDocField where parent=%s and fieldtype='Table'""", doctype, as_list=1)] @@ -197,9 +202,6 @@ def get_table_fields(doctype): custom_child_tables = [] return child_tables + custom_child_tables - -def has_field(doctype, fieldname, parent=None, parentfield=None): - return get_field(doctype, fieldname, parent=None, parentfield=None) and True or False def get_field_currency(df, doc): """get currency based on DocField options and fieldvalue in doc""" @@ -233,4 +235,28 @@ def get_field_precision(df, doc): if df.fieldtype == "Float": precision = cint(frappe.db.get_default("float_precision")) or 3 - return precision \ No newline at end of file + return precision + +def clear_cache(doctype=None): + def clear_single(dt): + frappe.cache().delete_value("meta:" + dt) + frappe.cache().delete_value("form_meta:" + dt) + + if doctype: + clear_single(doctype) + + # clear all parent doctypes + for dt in frappe.db.sql("""select parent from tabDocField + where fieldtype="Table" and options=%s""", (doctype,)): + clear_single(dt[0]) + + # clear all notifications + from frappe.core.doctype.notification_count.notification_count import delete_notification_count_for + delete_notification_count_for(doctype) + + else: + # clear all + for dt in frappe.db.sql("""select name from tabDocType"""): + clear_single(dt[0]) + + frappe.cache().delete_value("is_table") \ No newline at end of file diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 216e68d76a..659247134b 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -123,8 +123,7 @@ def getseries(key, digits, doctype=''): def get_default_naming_series(doctype): """get default value for `naming_series` property""" - from frappe.model.doctype import get_property - naming_series = get_property(doctype, "options", "naming_series") + naming_series = frappe.get_meta(doctype).get_field("naming_series").options or "" if naming_series: naming_series = naming_series.split("\n") return naming_series[0] or naming_series[1] @@ -150,3 +149,16 @@ def _get_amended_name(doc): doc.name = am_prefix + '-' + str(am_id) return doc.name +def append_number_if_name_exists(doc): + if frappe.db.exists(doc.doctype, doc.name): + last = frappe.db.sql("""select name from `tab{}` + where name regexp '{}-[[:digit:]]+' + order by name desc limit 1""".format(doc.doctype, doc.name)) + + if last: + count = str(cint(last[0][0].rsplit("-", 1)[1]) + 1) + else: + count = "1" + + doc.name = "{0}-{1}".format(doc.name, count) + diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index fc199c601d..ed33e50950 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -4,8 +4,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint -import frappe.model.doctype -from frappe.model.doc import validate_name +from frappe.model.naming import validate_name @frappe.whitelist() def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=False): @@ -19,16 +18,15 @@ def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=F force = cint(force) merge = cint(merge) - # get doclist of given doctype - doclist = frappe.model.doctype.get(doctype) + meta = frappe.get_meta(doctype) # call before_rename out = frappe.get_doc(doctype, old).run_method("before_rename", old, new, merge) or {} new = out.get("new") or new - new = validate_rename(doctype, new, doclist, merge, force, ignore_permissions) + new = validate_rename(doctype, new, meta, merge, force, ignore_permissions) if not merge: - rename_parent_and_child(doctype, old, new, doclist) + rename_parent_and_child(doctype, old, new, meta) # update link fields' values link_fields = get_link_fields(doctype) @@ -66,14 +64,14 @@ def rename_versions(doctype, old, new): frappe.db.sql("""update tabVersion set docname=%s where ref_doctype=%s and docname=%s""", (new, doctype, old)) -def rename_parent_and_child(doctype, old, new, doclist): +def rename_parent_and_child(doctype, old, new, meta): # rename the doc frappe.db.sql("update `tab%s` set name=%s where name=%s" \ % (doctype, '%s', '%s'), (new, old)) - update_child_docs(old, new, doclist) + update_child_docs(old, new, meta) -def validate_rename(doctype, new, doclist, merge, force, ignore_permissions): +def validate_rename(doctype, new, meta, merge, force, ignore_permissions): exists = frappe.db.exists(doctype, new) if merge and not exists: @@ -85,7 +83,7 @@ def validate_rename(doctype, new, doclist, merge, force, ignore_permissions): if not (ignore_permissions or frappe.has_permission(doctype, "write")): frappe.msgprint("You need write permission to rename", raise_exception=1) - if not force and not doclist[0].allow_rename: + if not force and not meta.allow_rename: frappe.msgprint("%s cannot be renamed" % doctype, raise_exception=1) # validate naming like it's done in doc.py @@ -109,12 +107,9 @@ def rename_doctype(doctype, old, new, force=False): frappe.db.sql("""update tabComment set comment_doctype=%s where comment_doctype=%s""", (new, old)) -def update_child_docs(old, new, doclist): +def update_child_docs(old, new, meta): # update "parent" - child_doctypes = (d.options for d in doclist - if d.doctype=='DocField' and d.fieldtype=='Table') - - for child in child_doctypes: + for child in meta.get_table_fields(): frappe.db.sql("update `tab%s` set parent=%s where parent=%s" \ % (child, '%s', '%s'), (new, old)) diff --git a/frappe/model/sync.py b/frappe/model/sync.py index 747b3d3b4a..697c96820e 100644 --- a/frappe/model/sync.py +++ b/frappe/model/sync.py @@ -40,8 +40,8 @@ def walk_and_sync(start_path, force=0, sync_everything = False, verbose=False): if sync_everything or (os.path.basename(os.path.dirname(path)) in document_type): for f in files: f = cstr(f) - if f.endswith(".txt"): - doc_name = f.split(".txt")[0] + if f.endswith(".json"): + doc_name = f.split(".json")[0] if doc_name == os.path.basename(path): module_name = path.split(os.sep)[-3] diff --git a/frappe/modules/__init__.py b/frappe/modules/__init__.py index d37bc52eea..50950de9dc 100644 --- a/frappe/modules/__init__.py +++ b/frappe/modules/__init__.py @@ -37,10 +37,9 @@ def reload_doc(module, dt=None, dn=None, force=True): def export_doc(doctype, name, module=None): """write out a doc""" from frappe.modules.export_file import write_document_file - import frappe.model.doc if not module: module = frappe.db.get_value(doctype, name, 'module') - write_document_file(frappe.model.get(doctype, name), module) + write_document_file(frappe.get_doc(doctype, name), module) def get_doctype_module(doctype): return frappe.db.get_value('DocType', doctype, 'module') or "core" diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index db01558b14..549426830d 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -25,7 +25,7 @@ def write_document_file(doc, record_module=None, create_init=None): newdoc = doc.as_dict() # strip out default fields from children - for df in doc.get_table_fields(): + for df in doc.meta.get_table_fields(): for d in newdoc.get(df.fieldname): for fieldname in frappe.model.default_fields: if fieldname in d: @@ -40,7 +40,7 @@ def write_document_file(doc, record_module=None, create_init=None): # write the data file fname = (doc.doctype in lower_case_files_for and scrub(doc.name)) or doc.name - with open(os.path.join(folder, fname +'.txt'),'w+') as txtfile: + with open(os.path.join(folder, fname +".json"),'w+') as txtfile: txtfile.write(json.dumps(newdoc, indent=1, sort_keys=True)) def get_module_name(doc): diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index 87cff6b819..ee6e9469c6 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -25,7 +25,7 @@ def get_file_path(module, dt, dn): dt, dn = scrub_dt_dn(dt, dn) path = os.path.join(get_module_path(module), - os.path.join(dt, dn, dn + '.txt')) + os.path.join(dt, dn, dn + ".json")) return path @@ -82,7 +82,7 @@ def import_doc(docdict): doc.set(key, old_doc.get(key)) # update ignored docs into new doc - for df in doc.get_table_fields(): + for df in doc.meta.get_table_fields(): if df.options in ignore_doctypes: doc.set(df.fieldname, []) ignore.append(df.options) diff --git a/frappe/sessions.py b/frappe/sessions.py index 668926db14..21d3d56ceb 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -12,7 +12,7 @@ import frappe, os, json import frappe import frappe.utils from frappe.utils import cint -import frappe.model.doctype +import frappe.model.meta import frappe.defaults import frappe.translate @@ -27,7 +27,7 @@ def clear(user=None): def clear_cache(user=None): cache = frappe.cache() - frappe.model.doctype.clear_cache() + frappe.model.meta.clear_cache() cache.delete_value(["app_hooks", "installed_apps", "app_modules", "module_apps", "home_page"]) if user: diff --git a/frappe/test_runner.py b/frappe/test_runner.py index 159f11e0dc..7636a48eed 100644 --- a/frappe/test_runner.py +++ b/frappe/test_runner.py @@ -6,8 +6,7 @@ from __future__ import unicode_literals import frappe import unittest, sys, json -from frappe.model.code import load_doctype_module, get_module_name -from frappe.model.doctype import get_link_fields +from frappe.modules import load_doctype_module, get_module_name from frappe.utils import cstr @@ -63,7 +62,7 @@ def _run_test(path, filename, verbose, test_suite=None, run=True): test_suite = unittest.TestSuite() if os.path.basename(os.path.dirname(path))=="doctype": - txt_file = os.path.join(path, filename[5:].replace(".py", ".txt")) + txt_file = os.path.join(path, filename[5:].replace(".py", ".json")) with open(txt_file, 'r') as f: doc = json.loads(f.read()) doctype = doc["name"] @@ -105,9 +104,14 @@ def get_modules(doctype): def get_dependencies(doctype): module, test_module = get_modules(doctype) + meta = frappe.get_meta(doctype) + link_fields = meta.get_link_fields() - options_list = list(set([df.options for df in get_link_fields(doctype)] + [doctype])) + for df in meta.get_table_fields(): + link_fields.extend(frappe.get_meta(df.options).get_link_fields()) + options_list = list(set([df.options for df in link_fields] + [doctype])) + if hasattr(test_module, "test_dependencies"): options_list += test_module.test_dependencies @@ -115,7 +119,7 @@ def get_dependencies(doctype): for doctype_name in test_module.test_ignore: if doctype_name in options_list: options_list.remove(doctype_name) - + return options_list def make_test_records_for_doctype(doctype, verbose=0): @@ -138,7 +142,7 @@ def make_test_objects(doctype, test_records, verbose=None): for doc in test_records: if not hasattr(doc, "doctype"): - doc.doctype = doctype + doc["doctype"] = doctype d = frappe.copy_doc(doc) diff --git a/frappe/tests/__init__.py b/frappe/tests/__init__.py index 5d22462144..00e6b358eb 100644 --- a/frappe/tests/__init__.py +++ b/frappe/tests/__init__.py @@ -24,14 +24,14 @@ def get_test_doclist(doctype, name=None): conf.test_data_path, doctype) if name: - with open(os.path.join(doctype_path, scrub(name) + '.txt'), 'r') as txtfile: + with open(os.path.join(doctype_path, scrub(name) + ".json"), 'r') as txtfile: doclist = peval_doclist(txtfile.read()) return doclist else: all_doclists = [] - for fname in filter(lambda n: n.endswith('.txt'), os.listdir(doctype_path)): + for fname in filter(lambda n: n.endswith(".json"), os.listdir(doctype_path)): with open(os.path.join(doctype_path, scrub(fname)), 'r') as txtfile: all_doclists.append(peval_doclist(txtfile.read())) diff --git a/frappe/tests/test_document.py b/frappe/tests/test_document.py index 4e4b80d44e..39be2462d3 100644 --- a/frappe/tests/test_document.py +++ b/frappe/tests/test_document.py @@ -113,7 +113,7 @@ class TestDocument(unittest.TestCase): }) self.assertRaises(frappe.LinkValidationError, d.insert) d.user_roles = [] - d.set("user_roles", { + d.append("user_roles", { "role": "System Manager" }) d.insert() diff --git a/frappe/utils/email_lib/bulk.py b/frappe/utils/email_lib/bulk.py index b0e1cb30bc..d47c4a6d42 100644 --- a/frappe/utils/email_lib/bulk.py +++ b/frappe/utils/email_lib/bulk.py @@ -78,7 +78,7 @@ def send(recipients=None, sender=None, doctype='User', email_field='email', def add(email, sender, subject, formatted, text_content=None, ref_doctype=None, ref_docname=None): """add to bulk mail queue""" - e = frappe.get_doc('Bulk Email') + e = frappe.new_doc('Bulk Email') e.sender = sender e.recipient = email try: diff --git a/frappe/utils/file_manager.py b/frappe/utils/file_manager.py index ce25e3ba63..e0a23e962a 100644 --- a/frappe/utils/file_manager.py +++ b/frappe/utils/file_manager.py @@ -94,7 +94,7 @@ def save_file(fname, content, dt, dn, decode=False): content = base64.b64decode(content) import filecmp - from frappe.model.code import load_doctype_module + from frappe.modules import load_doctype_module files_path = os.path.join(frappe.local.site_path, "public", "files") module = load_doctype_module(dt, frappe.db.get_value("DocType", dt, "module")) diff --git a/frappe/utils/nestedset.py b/frappe/utils/nestedset.py index 25f175ac1b..8aa57f370b 100644 --- a/frappe/utils/nestedset.py +++ b/frappe/utils/nestedset.py @@ -22,38 +22,29 @@ class NestedSetChildExistsError(frappe.ValidationError): pass class NestedSetInvalidMergeError(frappe.ValidationError): pass # called in the on_update method -def update_nsm(doc_obj): +def update_nsm(doc): # get fields, data from the DocType opf = 'old_parent' + pf = "parent_" + frappe.scrub(doc.doctype) - if str(doc_obj.__class__)=='frappe.model.Document': - # passed as a Document object - d = doc_obj - pf = "parent_" + frappe.scrub(d.doctype) - else: - # passed as a DocType object - d = doc_obj.doc - pf = "parent_" + frappe.scrub(d.doctype) - - if hasattr(doc_obj,'nsm_parent_field'): - pf = doc_obj.nsm_parent_field - if hasattr(doc_obj,'nsm_oldparent_field'): - opf = doc_obj.nsm_oldparent_field + if hasattr(doc,'nsm_parent_field'): + pf = doc.nsm_parent_field + if hasattr(doc,'nsm_oldparent_field'): + opf = doc.nsm_oldparent_field - p, op = d.get(pf) or None, d.get(opf) or None + p, op = doc.get(pf) or None, doc.get(opf) or None # has parent changed (?) or parent is None (root) - if not d.lft and not d.rgt: - update_add_node(d, p or '', pf) + if not doc.lft and not doc.rgt: + update_add_node(doc, p or '', pf) elif op != p: - update_move_node(d, pf) + update_move_node(doc, pf) # set old parent - d.set(opf, p) - frappe.db.set_value(d.doctype, d.name, opf, p or '') - - # reload - d._loadfromdb() + doc.set(opf, p) + frappe.db.set_value(doc.doctype, doc.name, opf, p or '') + + doc.load_from_db() def update_add_node(doc, parent, parent_field): """ diff --git a/frappe/utils/response.py b/frappe/utils/response.py index 32e5eb1ca2..356cdf6061 100644 --- a/frappe/utils/response.py +++ b/frappe/utils/response.py @@ -9,7 +9,6 @@ import mimetypes import os import frappe from frappe import _ -import frappe.model.doc import frappe.model.document import frappe.utils import frappe.sessions @@ -107,8 +106,6 @@ def json_handler(obj): return unicode(obj) elif isinstance(obj, LocalProxy): return unicode(obj) - elif isinstance(obj, frappe.model.Document): - return obj.fields elif isinstance(obj, frappe.model.document.Document): return obj.as_dict() else: diff --git a/frappe/website/doctype/about_us_settings/about_us_settings.txt b/frappe/website/doctype/about_us_settings/about_us_settings.json similarity index 100% rename from frappe/website/doctype/about_us_settings/about_us_settings.txt rename to frappe/website/doctype/about_us_settings/about_us_settings.json 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 b5c198cbc5..8186ac9342 100644 --- a/frappe/website/doctype/about_us_settings/about_us_settings.py +++ b/frappe/website/doctype/about_us_settings/about_us_settings.py @@ -15,7 +15,7 @@ class AboutUsSettings(Document): clear_cache("about") def get_args(): - obj = frappe.get_obj("About Us Settings") + obj = frappe.get_doc("About Us Settings") return { "obj": obj } \ No newline at end of file diff --git a/frappe/website/doctype/about_us_team_member/about_us_team_member.txt b/frappe/website/doctype/about_us_team_member/about_us_team_member.json similarity index 100% rename from frappe/website/doctype/about_us_team_member/about_us_team_member.txt rename to frappe/website/doctype/about_us_team_member/about_us_team_member.json diff --git a/frappe/website/doctype/blog_category/blog_category.txt b/frappe/website/doctype/blog_category/blog_category.json similarity index 100% rename from frappe/website/doctype/blog_category/blog_category.txt rename to frappe/website/doctype/blog_category/blog_category.json diff --git a/frappe/website/doctype/blog_category/test_blog_category.py b/frappe/website/doctype/blog_category/test_blog_category.py index 6c6ee45a2a..5a227df02b 100644 --- a/frappe/website/doctype/blog_category/test_blog_category.py +++ b/frappe/website/doctype/blog_category/test_blog_category.py @@ -1,17 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -test_records = [ - [{ - "doctype": "Blog Category", - "category_name": "_Test Blog Category", - "title": "_Test Blog Category", - "parent_website_route": "blog" - }], - [{ - "doctype": "Blog Category", - "category_name": "_Test Blog Category 1", - "title": "_Test Blog Category 1", - "parent_website_route": "blog" - }] -] \ No newline at end of file +import frappe + +test_records = frappe.get_test_records('Blog Category') \ No newline at end of file diff --git a/frappe/website/doctype/blog_post/blog_post.txt b/frappe/website/doctype/blog_post/blog_post.json similarity index 100% rename from frappe/website/doctype/blog_post/blog_post.txt rename to frappe/website/doctype/blog_post/blog_post.json diff --git a/frappe/website/doctype/blog_post/test_blog_post.py b/frappe/website/doctype/blog_post/test_blog_post.py index e37a55c908..3e9064827a 100644 --- a/frappe/website/doctype/blog_post/test_blog_post.py +++ b/frappe/website/doctype/blog_post/test_blog_post.py @@ -3,31 +3,12 @@ """Use blog post test to test permission restriction logic""" -test_records = [ - [{ - "doctype": "Blog Post", - "title":"_Test Blog Post", - "blog_category": "_Test Blog Category", - "blogger": "_Test Blogger", - "blog_intro": "Test Blog Intro", - "content": "Test Blog Content" - }], - [{ - "doctype": "Blog Post", - "title":"_Test Blog Post 1", - "blog_category": "_Test Blog Category 1", - "blogger": "_Test Blogger", - "blog_intro": "Test Blog Intro", - "content": "Test Blog Content" - }] - -] - import frappe import frappe.defaults import unittest from frappe.core.page.user_properties.user_properties import add, remove, get_properties, clear_restrictions +test_records = frappe.get_test_records('Blog Post') test_dependencies = ["User"] class TestBlogPost(unittest.TestCase): @@ -54,17 +35,17 @@ class TestBlogPost(unittest.TestCase): def test_basic_permission(self): post = frappe.get_doc("Blog Post", "_test-blog-post") - self.assertTrue(post.has_read_perm()) + self.assertTrue(post.has_permission("read")) def test_restriction_in_bean(self): frappe.defaults.add_default("Blog Category", "_Test Blog Category 1", "test1@example.com", "Restriction") post = frappe.get_doc("Blog Post", "_test-blog-post") - self.assertFalse(post.has_read_perm()) + self.assertFalse(post.has_permission("read")) post1 = frappe.get_doc("Blog Post", "_test-blog-post-1") - self.assertTrue(post1.has_read_perm()) + self.assertTrue(post1.has_permission("read")) def test_restriction_in_report(self): frappe.defaults.add_default("Blog Category", "_Test Blog Category 1", "test1@example.com", @@ -93,10 +74,10 @@ class TestBlogPost(unittest.TestCase): frappe.set_user("test2@example.com") post = frappe.get_doc("Blog Post", "_test-blog-post") - self.assertTrue(post.has_read_perm()) + self.assertTrue(post.has_permission("read")) post1 = frappe.get_doc("Blog Post", "_test-blog-post-1") - self.assertFalse(post1.has_read_perm()) + self.assertFalse(post1.has_permission("read")) def test_owner_match_report(self): frappe.db.sql("""update tabDocPerm set `restricted`=1 where parent='Blog Post' @@ -131,11 +112,11 @@ class TestBlogPost(unittest.TestCase): # user can only access restricted blog post bean = frappe.get_doc("Blog Post", "_test-blog-post") - self.assertTrue(bean.has_read_perm()) + self.assertTrue(bean.has_permission("read")) # and not this one bean = frappe.get_doc("Blog Post", "_test-blog-post-1") - self.assertFalse(bean.has_read_perm()) + self.assertFalse(bean.has_permission("read")) def test_not_allowed_to_remove_self(self): self.add_restriction_to_user2() @@ -152,7 +133,7 @@ class TestBlogPost(unittest.TestCase): frappe.set_user("test2@example.com") bean = frappe.get_doc("Blog Post", "_test-blog-post-1") - self.assertFalse(bean.has_read_perm()) + self.assertFalse(bean.has_permission("read")) frappe.set_user("test1@example.com") add("test2@example.com", "Blog Post", "_test-blog-post-1") @@ -160,7 +141,7 @@ class TestBlogPost(unittest.TestCase): frappe.set_user("test2@example.com") bean = frappe.get_doc("Blog Post", "_test-blog-post-1") - self.assertTrue(bean.has_read_perm()) + self.assertTrue(bean.has_permission("read")) def test_set_only_once(self): blog_post = frappe.get_meta("Blog Post") @@ -168,5 +149,4 @@ class TestBlogPost(unittest.TestCase): bean = frappe.get_doc("Blog Post", "_test-blog-post-1") bean.title = "New" self.assertRaises(frappe.CannotChangeConstantError, bean.save) - blog_post.get_field("title").set_only_once = 0 - + blog_post.get_field("title").set_only_once = 0 \ No newline at end of file diff --git a/frappe/website/doctype/blog_settings/blog_settings.txt b/frappe/website/doctype/blog_settings/blog_settings.json similarity index 100% rename from frappe/website/doctype/blog_settings/blog_settings.txt rename to frappe/website/doctype/blog_settings/blog_settings.json diff --git a/frappe/website/doctype/blogger/blogger.txt b/frappe/website/doctype/blogger/blogger.json similarity index 100% rename from frappe/website/doctype/blogger/blogger.txt rename to frappe/website/doctype/blogger/blogger.json diff --git a/frappe/website/doctype/blogger/test_blogger.py b/frappe/website/doctype/blogger/test_blogger.py index 15b31b34c7..db7feb4970 100644 --- a/frappe/website/doctype/blogger/test_blogger.py +++ b/frappe/website/doctype/blogger/test_blogger.py @@ -1,16 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -test_records = [ - [{ - "doctype": "Blogger", - "short_name": "_Test Blogger", - "full_name": "_Test Blogger" - }], - [{ - "doctype": "Blogger", - "short_name": "_Test Blogger 1", - "full_name": "_Test Blogger 1" - }] - -] \ No newline at end of file + +import frappe +test_records = frappe.get_test_records('Blogger') \ No newline at end of file diff --git a/frappe/website/doctype/company_history/company_history.txt b/frappe/website/doctype/company_history/company_history.json similarity index 100% rename from frappe/website/doctype/company_history/company_history.txt rename to frappe/website/doctype/company_history/company_history.json diff --git a/frappe/website/doctype/contact_us_settings/contact_us_settings.txt b/frappe/website/doctype/contact_us_settings/contact_us_settings.json similarity index 100% rename from frappe/website/doctype/contact_us_settings/contact_us_settings.txt rename to frappe/website/doctype/contact_us_settings/contact_us_settings.json diff --git a/frappe/website/doctype/post/post.txt b/frappe/website/doctype/post/post.json similarity index 100% rename from frappe/website/doctype/post/post.txt rename to frappe/website/doctype/post/post.json diff --git a/frappe/website/doctype/style_settings/style_settings.txt b/frappe/website/doctype/style_settings/style_settings.json similarity index 100% rename from frappe/website/doctype/style_settings/style_settings.txt rename to frappe/website/doctype/style_settings/style_settings.json diff --git a/frappe/website/doctype/top_bar_item/top_bar_item.txt b/frappe/website/doctype/top_bar_item/top_bar_item.json similarity index 100% rename from frappe/website/doctype/top_bar_item/top_bar_item.txt rename to frappe/website/doctype/top_bar_item/top_bar_item.json diff --git a/frappe/website/doctype/user_vote/user_vote.txt b/frappe/website/doctype/user_vote/user_vote.json similarity index 100% rename from frappe/website/doctype/user_vote/user_vote.txt rename to frappe/website/doctype/user_vote/user_vote.json diff --git a/frappe/website/doctype/web_page/test_web_page.py b/frappe/website/doctype/web_page/test_web_page.py index edffd53e37..234255e6fa 100644 --- a/frappe/website/doctype/web_page/test_web_page.py +++ b/frappe/website/doctype/web_page/test_web_page.py @@ -2,41 +2,7 @@ from __future__ import unicode_literals import unittest import frappe -test_records = [ - [{ - "doctype": "Web Page", - "title": "Test Web Page 1", - "main_section": "Test Content 1", - "published": 1 - }], - [{ - "doctype": "Web Page", - "title": "Test Web Page 2", - "main_section": "Test Content 2", - "published": 1, - "parent_website_route": "test-web-page-1" - }], - [{ - "doctype": "Web Page", - "title": "Test Web Page 3", - "main_section": "Test Content 3", - "published": 1, - "parent_website_route": "test-web-page-1" - }], - [{ - "doctype": "Web Page", - "title": "Test Web Page 4", - "main_section": "Test Content 4", - "published": 1, - }], - [{ - "doctype": "Web Page", - "title": "Test Web Page 5", - "main_section": "Test Content 5", - "published": 1, - "parent_website_route": "test-web-page-1" - }], -] +test_records = frappe.get_test_records('Web Page') class TestWebPage(unittest.TestCase): def test_check_sitemap(self): @@ -91,7 +57,4 @@ class TestWebPage(unittest.TestCase): web_page = frappe.get_doc("Web Page", "test-web-page-3") web_page.parent_website_route = "test-web-page-1" - web_page.save() - - - \ No newline at end of file + web_page.save() \ No newline at end of file diff --git a/frappe/website/doctype/web_page/web_page.txt b/frappe/website/doctype/web_page/web_page.json similarity index 100% rename from frappe/website/doctype/web_page/web_page.txt rename to frappe/website/doctype/web_page/web_page.json diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index fefcecb3cf..7ec632b776 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -7,5 +7,5 @@ from frappe.website.website_generator import WebsiteGenerator from frappe.website.utils import cleanup_page_name from frappe.utils import cint -class WebsitePage(WebsiteGenerator): +class WebPage(WebsiteGenerator): save_versions = True diff --git a/frappe/website/doctype/website_group/website_group.txt b/frappe/website/doctype/website_group/website_group.json similarity index 100% rename from frappe/website/doctype/website_group/website_group.txt rename to frappe/website/doctype/website_group/website_group.json diff --git a/frappe/website/doctype/website_route/website_route.txt b/frappe/website/doctype/website_route/website_route.json similarity index 100% rename from frappe/website/doctype/website_route/website_route.txt rename to frappe/website/doctype/website_route/website_route.json diff --git a/frappe/website/doctype/website_route_permission/website_route_permission.txt b/frappe/website/doctype/website_route_permission/website_route_permission.json similarity index 100% rename from frappe/website/doctype/website_route_permission/website_route_permission.txt rename to frappe/website/doctype/website_route_permission/website_route_permission.json diff --git a/frappe/website/doctype/website_script/website_script.txt b/frappe/website/doctype/website_script/website_script.json similarity index 100% rename from frappe/website/doctype/website_script/website_script.txt rename to frappe/website/doctype/website_script/website_script.json diff --git a/frappe/website/doctype/website_settings/website_settings.txt b/frappe/website/doctype/website_settings/website_settings.json similarity index 100% rename from frappe/website/doctype/website_settings/website_settings.txt rename to frappe/website/doctype/website_settings/website_settings.json diff --git a/frappe/website/doctype/website_slideshow/website_slideshow.txt b/frappe/website/doctype/website_slideshow/website_slideshow.json similarity index 100% rename from frappe/website/doctype/website_slideshow/website_slideshow.txt rename to frappe/website/doctype/website_slideshow/website_slideshow.json diff --git a/frappe/website/doctype/website_slideshow_item/website_slideshow_item.txt b/frappe/website/doctype/website_slideshow_item/website_slideshow_item.json similarity index 100% rename from frappe/website/doctype/website_slideshow_item/website_slideshow_item.txt rename to frappe/website/doctype/website_slideshow_item/website_slideshow_item.json diff --git a/frappe/website/doctype/website_template/website_template.txt b/frappe/website/doctype/website_template/website_template.json similarity index 100% rename from frappe/website/doctype/website_template/website_template.txt rename to frappe/website/doctype/website_template/website_template.json diff --git a/frappe/website/page/sitemap_browser/sitemap_browser.txt b/frappe/website/page/sitemap_browser/sitemap_browser.json similarity index 100% rename from frappe/website/page/sitemap_browser/sitemap_browser.txt rename to frappe/website/page/sitemap_browser/sitemap_browser.json diff --git a/frappe/website/page/sitemap_browser/sitemap_browser.py b/frappe/website/page/sitemap_browser/sitemap_browser.py index df04e9f27a..66aabafbda 100644 --- a/frappe/website/page/sitemap_browser/sitemap_browser.py +++ b/frappe/website/page/sitemap_browser/sitemap_browser.py @@ -64,7 +64,7 @@ def update_parent(name, new_parent): if sitemap.ref_doctype: generator = frappe.get_doc(sitemap.ref_doctype, sitemap.docname) - if not generator.meta.has_field("parent_website_route"): + if not generator.meta.get_field("parent_website_route"): frappe.throw("Does not allow moving.") generator.parent_website_route = new_parent generator.save() diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index ef6a2cdae9..b4da621ad1 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -4,18 +4,19 @@ from __future__ import unicode_literals import frappe from frappe.model.controller import DocListController +from frappe.model.naming import append_number_if_name_exists from frappe.website.utils import cleanup_page_name from frappe.utils import now from frappe.website.doctype.website_route.website_route import add_to_sitemap, update_sitemap, remove_sitemap -def call_website_generator(bean, method, *args, **kwargs): - getattr(WebsiteGenerator(bean.doc, bean.doclist), method)(*args, **kwargs) +def call_website_generator(doc, method, *args, **kwargs): + getattr(WebsiteGenerator(doc), method)(*args, **kwargs) class WebsiteGenerator(DocListController): def autoname(self): self.name = self.get_page_name() - self.append_number_if_name_exists() + append_number_if_name_exists(self) def set_page_name(self): """set page name based on parent page_name and title""" @@ -39,7 +40,7 @@ class WebsiteGenerator(DocListController): def on_update(self): self.update_sitemap() if getattr(self, "save_versions", False): - frappe.add_version(self.doclist) + frappe.add_version(self) def after_rename(self, olddn, newdn, merge): frappe.db.sql("""update `tabWebsite Route` @@ -114,7 +115,7 @@ class WebsiteGenerator(DocListController): def _get_page_name(self): self.setup_generator() - if self.meta.has_field(self.website_template.page_name_field): + if self.meta.get_field(self.website_template.page_name_field): return self.get(self.website_template.page_name_field) else: return cleanup_page_name(self.get_page_title()) diff --git a/frappe/widgets/event.py b/frappe/widgets/event.py index 30f1d977bf..0ce7a7abf2 100644 --- a/frappe/widgets/event.py +++ b/frappe/widgets/event.py @@ -7,9 +7,7 @@ from __future__ import unicode_literals import frappe @frappe.whitelist() -def get_cal_events(m_st, m_end): - import frappe.model.doc - +def get_cal_events(m_st, m_end): # load owned events res1 = frappe.db.sql("""select name from `tabEvent` WHERE ifnull(event_date,'2000-01-01') between %s and %s and owner = %s diff --git a/frappe/widgets/form/assign_to.py b/frappe/widgets/form/assign_to.py index c787451aec..d80185ecb9 100644 --- a/frappe/widgets/form/assign_to.py +++ b/frappe/widgets/form/assign_to.py @@ -47,8 +47,7 @@ def add(args=None): }).insert(ignore_permissions=True).doc # set assigned_to if field exists - from frappe.model.meta import has_field - if has_field(args['doctype'], "assigned_to"): + if frappe.get_meta(args['doctype']).get_field("assigned_to"): frappe.db.set_value(args['doctype'], args['name'], "assigned_to", args['assign_to']) try: @@ -84,8 +83,7 @@ def remove(doctype, name, assign_to): todo.save(ignore_permissions=True) # clear assigned_to if field exists - from frappe.model.meta import has_field - if has_field(doctype, "assigned_to"): + if frappe.get_meta(doctype).get_field("assigned_to"): frappe.db.set_value(doctype, name, "assigned_to", None) notify_assignment(todo.assigned_by, todo.owner, todo.reference_type, todo.reference_name) diff --git a/frappe/widgets/form/load.py b/frappe/widgets/form/load.py index 298aaf005a..69688f29b8 100644 --- a/frappe/widgets/form/load.py +++ b/frappe/widgets/form/load.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe, json -import frappe.model.doc import frappe.utils import frappe.widgets.form.meta diff --git a/frappe/widgets/form/run_method.py b/frappe/widgets/form/run_method.py index ae5adb2807..dd2e80e891 100644 --- a/frappe/widgets/form/run_method.py +++ b/frappe/widgets/form/run_method.py @@ -10,8 +10,6 @@ def runserverobj(): """ Run server objects """ - import frappe.model.code - from frappe.model.bean import Bean from frappe.utils import cint wrapper = None @@ -22,33 +20,25 @@ def runserverobj(): if dt: # not called from a doctype (from a page) if not dn: dn = dt # single - so = frappe.model.code.get_obj(dt, dn) + doc = frappe.get_doc(dt, dn) else: - bean = Bean() - bean.from_compressed(frappe.form_dict.get('docs'), dn) - if not bean.has_read_perm(): - frappe.msgprint(_("No Permission"), raise_exception = True) - so = bean.make_controller() - bean.check_if_latest(method="runserverobj") + doc = frappe.get_doc(json.loads(frappe.form_dict.get('docs'))) + doc.check_if_latest() - check_guest_access(so.doc) + if not doc.has_permission("read"): + frappe.msgprint(_("No Permission"), raise_exception = True) - if so: - r = frappe.model.code.run_server_obj(so, method, arg) + if doc: + r = doc.run_method(method, arg) if r: #build output as csv if cint(frappe.form_dict.get('as_csv')): - make_csv_output(r, so.doctype) + make_csv_output(r, doc.doctype) else: frappe.response['message'] = r - frappe.response['docs'] += so.doclist - -def check_guest_access(doc): - if frappe.session['user']=='Guest' and not frappe.db.sql("select name from tabDocPerm where role='Guest' and parent=%s and ifnull(`read`,0)=1", doc.doctype): - frappe.msgprint("Guest not allowed to call this object") - raise Exception + frappe.response.docs.append(doc) def make_csv_output(res, dt): """send method response as downloadable CSV file""" diff --git a/frappe/widgets/form/utils.py b/frappe/widgets/form/utils.py index a32b445146..41fe0fc3a7 100644 --- a/frappe/widgets/form/utils.py +++ b/frappe/widgets/form/utils.py @@ -95,7 +95,7 @@ def get_linked_docs(doctype, name, metadata_loaded=None): link["doctype"] = dt linkmeta = frappe.widgets.form.meta.get_meta(dt) if not linkmeta.get("issingle"): - fields = [d.fieldname for d in linkmeta.get({"parent":dt, "in_list_view":1, + fields = [d.fieldname for d in linkmeta.get("fields", {"in_list_view":1, "fieldtype": ["not in", ["Image", "HTML", "Button", "Table"]]})] \ + ["name", "modified", "docstatus"] @@ -113,6 +113,6 @@ def get_linked_docs(doctype, name, metadata_loaded=None): results[dt] = ret if not dt in metadata_loaded: - frappe.local.response.docs += linkmeta + frappe.local.response.docs.append(linkmeta) return results \ No newline at end of file diff --git a/frappe/widgets/page.py b/frappe/widgets/page.py index 526ce46c88..d586339146 100644 --- a/frappe/widgets/page.py +++ b/frappe/widgets/page.py @@ -3,8 +3,6 @@ from __future__ import unicode_literals import frappe -import frappe.model.doc -import frappe.model.code @frappe.whitelist() def get(name): diff --git a/frappe/widgets/query_report.py b/frappe/widgets/query_report.py index d489280be0..17182a6471 100644 --- a/frappe/widgets/query_report.py +++ b/frappe/widgets/query_report.py @@ -14,7 +14,7 @@ import frappe.widgets.reportview def get_report_doc(report_name): bean = frappe.get_doc("Report", report_name) - if not bean.has_read_perm(): + if not bean.has_permission("read"): raise frappe.PermissionError("You don't have access to: {report}".format(report=report_name)) if not frappe.has_permission(bean.ref_doctype, "report"): diff --git a/frappe/widgets/reportview.py b/frappe/widgets/reportview.py index a6447579af..d5ea74624d 100644 --- a/frappe/widgets/reportview.py +++ b/frappe/widgets/reportview.py @@ -118,14 +118,13 @@ def get_labels(columns): def delete_items(): """delete selected items""" import json - from frappe.model.code import get_obj - + il = json.loads(frappe.form_dict.get('items')) doctype = frappe.form_dict.get('doctype') for d in il: try: - dt_obj = get_obj(doctype, d) + dt_obj = frappe.get_doc(doctype, d) if hasattr(dt_obj, 'on_trash'): dt_obj.on_trash() frappe.delete_doc(doctype, d)