diff --git a/frappe/cli.py b/frappe/cli.py index 01c3c48e36..36786c4f5c 100755 --- a/frappe/cli.py +++ b/frappe/cli.py @@ -117,7 +117,7 @@ def setup_parser(): help="Force execution where applicable (look for [-f] in help)") parser.add_argument("--verbose", default=False, action="store_true", help="Show verbose output (where applicable)") - parser.add_argument("--quiet", default=True, action="store_false", + parser.add_argument("--quiet", default=False, action="store_true", help="Do not show verbose output (where applicable)") return parser.parse_args() @@ -272,9 +272,9 @@ def use(sites_path): # install @cmd def install(db_name, root_login="root", root_password=None, source_sql=None, - admin_password = 'admin', verbose=True, force=False, site_config=None, reinstall=False, quiet=False): + admin_password = 'admin', force=False, site_config=None, reinstall=False, quiet=False): from frappe.installer import install_db, install_app, make_site_dirs - verbose = verbose or not quiet + verbose = not quiet install_db(root_login=root_login, root_password=root_password, db_name=db_name, source_sql=source_sql, admin_password = admin_password, verbose=verbose, force=force, site_config=site_config, reinstall=reinstall) @@ -283,8 +283,8 @@ def install(db_name, root_login="root", root_password=None, source_sql=None, frappe.destroy() @cmd -def install_app(app_name, verbose=True, quiet=False): - verbose = verbose or not quiet +def install_app(app_name, quiet=False): + verbose = not quiet from frappe.installer import install_app frappe.connect() install_app(app_name, verbose=verbose) @@ -301,8 +301,8 @@ def add_to_installed_apps(*apps): frappe.destroy() @cmd -def reinstall(verbose=True, quiet=False): - verbose = verbose or not quiet +def reinstall(quiet=False): + verbose = not quiet try: frappe.connect() frappe.clear_cache() @@ -314,8 +314,8 @@ def reinstall(verbose=True, quiet=False): install(db_name=frappe.conf.db_name, verbose=verbose, force=True, reinstall=True) @cmd -def restore(db_name, source_sql, verbose=True, force=False, quiet=False): - verbose = verbose or not quiet +def restore(db_name, source_sql, force=False, quiet=False): + verbose = not quiet install(db_name, source_sql=source_sql, verbose=verbose, force=force) @cmd @@ -341,7 +341,7 @@ def update(remote=None, branch=None, reload_gunicorn=False): subprocess.check_output("killall -HUP gunicorn".split()) @cmd -def latest(verbose=True, rebuild_website_config=True, quiet=False): +def latest(rebuild_website_config=True, quiet=False): import frappe.modules.patch_handler import frappe.model.sync from frappe.website import rebuild_config @@ -349,7 +349,7 @@ def latest(verbose=True, rebuild_website_config=True, quiet=False): import frappe.translate from frappe.website import statics - verbose = verbose or not quiet + verbose = not quiet frappe.connect() @@ -379,9 +379,9 @@ def latest(verbose=True, rebuild_website_config=True, quiet=False): frappe.destroy() @cmd -def sync_all(force=False, verbose=True, quiet=False): +def sync_all(force=False, quiet=False): import frappe.model.sync - verbose = verbose or not quiet + verbose = not quiet frappe.connect() frappe.model.sync.sync_all(force=force, verbose=verbose) frappe.destroy() @@ -396,8 +396,8 @@ def patch(patch_module, force=False): frappe.destroy() @cmd -def update_all_sites(remote=None, branch=None, verbose=True, quiet=False): - verbose = verbose or not quiet +def update_all_sites(remote=None, branch=None, quiet=False): + verbose = not quiet pull(remote, branch) # maybe there are new framework changes, any consequences? @@ -427,9 +427,9 @@ def watch(): frappe.build.watch(True) @cmd -def backup(with_files=False, verbose=True, backup_path_db=None, backup_path_files=None, quiet=False): +def backup(with_files=False, backup_path_db=None, backup_path_files=None, quiet=False): from frappe.utils.backups import scheduled_backup - verbose = verbose or not quiet + verbose = not quiet frappe.connect() odb = scheduled_backup(ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files) if verbose: @@ -696,10 +696,8 @@ 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, quiet=True, tests=()): +def run_tests(app=None, module=None, doctype=None, verbose=False, tests=()): import frappe.test_runner - verbose = verbose or not quiet - ret = frappe.test_runner.main(app and app[0], module and module[0], doctype and doctype[0], verbose, tests=tests) @@ -781,15 +779,13 @@ def search_replace_with_prompt(fpath, txt1, txt2, force=False): print colored('Updated', 'green') @cmd -def get_site_status(verbose=False, quiet=True): +def get_site_status(verbose=False): import frappe import frappe.utils from frappe.utils.user import get_system_managers from frappe.core.doctype.user.user import get_total_users, get_active_users, \ get_website_users, get_active_website_users - verbose = verbose or not quiet - import json frappe.connect() ret = { @@ -822,9 +818,8 @@ def get_site_status(verbose=False, quiet=True): return ret @cmd -def update_site_config(site_config, verbose=False, quiet=True): +def update_site_config(site_config, verbose=False): import json - verbose = verbose or not quiet if isinstance(site_config, basestring): site_config = json.loads(site_config) 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 4488d84710..266587c8e6 100644 --- a/frappe/core/page/data_import_tool/data_import_tool.py +++ b/frappe/core/page/data_import_tool/data_import_tool.py @@ -6,7 +6,6 @@ from __future__ import unicode_literals import frappe, json, os import frappe.modules.import_file from frappe.utils import cstr, cint, flt -from frappe.utils.datautils import check_record, import_doc data_keys = frappe._dict({ "data_separator": 'Start entering data below this line', @@ -30,7 +29,6 @@ def get_doctype_options(): return [doctype] + [d.options for d in frappe.get_meta(doctype).get_table_fields()] -import csv def import_file_by_path(path, ignore_links=False, overwrite=False, submit=False): from frappe.utils.datautils import read_csv_content from frappe.core.page.data_import_tool.importer import upload diff --git a/frappe/core/page/data_import_tool/importer.py b/frappe/core/page/data_import_tool/importer.py index f791487c70..7ad46df252 100644 --- a/frappe/core/page/data_import_tool/importer.py +++ b/frappe/core/page/data_import_tool/importer.py @@ -6,7 +6,9 @@ from __future__ import unicode_literals import frappe, json, os import frappe.permissions -from frappe.utils.datautils import check_record, import_doc, getlink +from frappe.utils.datautils import getlink +from frappe.utils.dateutils import parse_date + from frappe.utils import cint, cstr, flt from frappe.core.page.data_import_tool.data_import_tool import data_keys @@ -103,6 +105,8 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, d[fieldname] = cint(d[fieldname]) elif fieldtype in ("Float", "Currency"): d[fieldname] = flt(d[fieldname]) + elif d[fieldname] and fieldtype == "Date": + d[fieldname] = parse_date(d[fieldname]) except IndexError, e: pass @@ -184,6 +188,9 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, doc = None doc = get_doc(row_idx) + if doc.get("name"): + doc["_new_name_set"] = True + try: frappe.local.message_log = [] if doc.get("parentfield"): diff --git a/frappe/exceptions.py b/frappe/exceptions.py index e0954b4080..19919f757f 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -1,5 +1,5 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# MIT License. See license.txt from __future__ import unicode_literals @@ -19,16 +19,16 @@ class DoesNotExistError(ValidationError): class DuplicateEntryError(Exception): http_status_code = 409 - + class OutgoingEmailError(Exception): http_status_code = 501 - + class SessionStopped(Exception): http_status_code = 503 - + class UnsupportedMediaType(Exception): http_status_code = 415 - + class DataError(ValidationError): pass class UnknownDomainError(Exception): pass class MappingMismatchError(ValidationError): pass @@ -39,4 +39,5 @@ class RateLimitExceededError(ValidationError): pass class CannotChangeConstantError(ValidationError): pass class LinkValidationError(ValidationError): pass class DocstatusTransitionError(ValidationError): pass -class TimestampMismatchError(ValidationError): pass \ No newline at end of file +class TimestampMismatchError(ValidationError): pass +class EmptyTableError(ValidationError): pass diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 734f94d4bb..900a649150 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -46,7 +46,7 @@ class BaseDocument(object): return _filter(self.get_all_children(), key, limit=limit) if filters: if isinstance(filters, dict): - value = _filter(self.__dict__.get(key), filters, limit=limit) + value = _filter(self.__dict__.get(key, []), filters, limit=limit) else: default = filters filters = None diff --git a/frappe/model/controller.py b/frappe/model/controller.py index 3a8ed70990..67109edd54 100644 --- a/frappe/model/controller.py +++ b/frappe/model/controller.py @@ -1,5 +1,5 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# MIT License. See license.txt from __future__ import unicode_literals import frappe @@ -8,14 +8,12 @@ from frappe.utils import flt, cint, cstr from frappe.model.meta import get_field_precision from frappe.model.document import Document -class EmptyTableError(frappe.ValidationError): pass - class DocListController(Document): def __init__(self, arg1, arg2=None): super(DocListController, self).__init__(arg1, arg2) if hasattr(self, "setup"): self.setup() - + def validate_value(self, fieldname, condition, val2, doc=None, raise_exception=None): """check that value of fieldname should be 'condition' val2 else throw exception""" @@ -33,51 +31,51 @@ class DocListController(Document): if not doc: doc = self - + df = doc.meta.get_field(fieldname) - + val1 = doc.get(fieldname) - + if df.fieldtype in ("Currency", "Float"): val1 = flt(val1, self.precision(df.fieldname, doc.parentfield or None)) val2 = flt(val2, self.precision(df.fieldname, doc.parentfield or None)) elif df.fieldtype in ("Int", "Check"): val1 = cint(val1) val2 = cint(val2) - elif df.fieldtype in ("Data", "Text", "Small Text", "Long Text", + elif df.fieldtype in ("Data", "Text", "Small Text", "Long Text", "Text Editor", "Select", "Link"): val1 = cstr(val1) val2 = cstr(val2) - + if not frappe.compare(val1, condition, val2): msg = _("Error") + ": " if doc.parentfield: msg += _("Row") + (" # %d: " % doc.idx) - + msg += _(doc.meta.get_label(fieldname)) \ + " " + error_condition_map.get(condition, "") + " " + cstr(val2) - + # raise passed exception or True msgprint(msg, raise_exception=raise_exception or True) - + def validate_table_has_rows(self, parentfield, raise_exception=None): - if not self.get(parentfield): + if not (isinstance(self.get(parentfield), list) and len(self.get(parentfield)) > 0): label = self.meta.get_label(parentfield) msgprint(_("Error") + ": " + _(label) + " " + _("cannot be empty"), - raise_exception=raise_exception or EmptyTableError) - + raise_exception=raise_exception or frappe.EmptyTableError) + def round_floats_in(self, doc, fieldnames=None): if not fieldnames: - fieldnames = [df.fieldname for df in doc.meta.get("fields", + fieldnames = [df.fieldname for df in doc.meta.get("fields", {"fieldtype": ["in", ["Currency", "Float"]]})] - + for fieldname in fieldnames: doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.parentfield))) - + def precision(self, fieldname, parentfield=None): if parentfield and not isinstance(parentfield, basestring): parentfield = parentfield.parentfield - + if not hasattr(self, "_precision"): self._precision = frappe._dict({ "default": cint(frappe.db.get_default("float_precision")) or 3, @@ -87,14 +85,14 @@ class DocListController(Document): if self._precision.setdefault(parentfield or "main", {}).get(fieldname) is None: meta = frappe.get_meta(self.meta.get_field(parentfield).options if parentfield else self.doctype) df = meta.get_field(fieldname) - + if df.fieldtype == "Currency" and df.options and not self._precision.options.get(df.options): self._precision.options[df.options] = get_field_precision(df, self) - + if df.fieldtype == "Currency": self._precision[parentfield or "main"][fieldname] = cint(self._precision.options.get(df.options)) or \ self._precision.default elif df.fieldtype == "Float": self._precision[parentfield or "main"][fieldname] = self._precision.default - - return self._precision[parentfield or "main"][fieldname] \ No newline at end of file + + return self._precision[parentfield or "main"][fieldname] diff --git a/frappe/utils/install.py b/frappe/utils/install.py index 8d7ed41f26..380de62328 100644 --- a/frappe/utils/install.py +++ b/frappe/utils/install.py @@ -1,5 +1,5 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt +# MIT License. See license.txt from __future__ import unicode_literals @@ -13,20 +13,20 @@ def before_install(): def after_install(): # reset installed apps for re-install frappe.db.set_global("installed_apps", '["frappe"]') - + # core users / roles install_docs = [ - {'doctype':'User', 'name':'Administrator', 'first_name':'Administrator', + {'doctype':'User', 'name':'Administrator', 'first_name':'Administrator', 'email':'admin@localhost', 'enabled':1}, {'doctype':'User', 'name':'Guest', 'first_name':'Guest', 'email':'guest@localhost', 'enabled':1}, - {'doctype':'UserRole', 'parent': 'Administrator', 'role': 'Administrator', + {'doctype':'UserRole', 'parent': 'Administrator', 'role': 'Administrator', 'parenttype':'User', 'parentfield':'user_roles'}, - {'doctype':'UserRole', 'parent': 'Guest', 'role': 'Guest', + {'doctype':'UserRole', 'parent': 'Guest', 'role': 'Guest', 'parenttype':'User', 'parentfield':'user_roles'}, {'doctype': "Role", "role_name": "Report Manager"} ] - + for d in install_docs: try: frappe.get_doc(d).insert()