diff --git a/frappe/celery_app.py b/frappe/celery_app.py index 5a085ced28..d816b58c3a 100644 --- a/frappe/celery_app.py +++ b/frappe/celery_app.py @@ -11,7 +11,6 @@ task_logger = get_task_logger(__name__) from datetime import timedelta import frappe import os -import threading import time SITES_PATH = os.environ.get('SITES_PATH', '.') @@ -127,14 +126,6 @@ class FrappeTask(get_celery().Task): def celery_task(*args, **kwargs): return get_celery().task(*args, **kwargs) -def make_async_task(args): - task = frappe.new_doc("Async Task") - task.update(args) - task.status = "Queued" - task.set_docstatus_user_and_timestamp() - task.db_insert() - task.notify_update() - def run_test(): for i in xrange(30): test.delay(site=frappe.local.site) @@ -144,107 +135,6 @@ def test(site=None): time.sleep(1) print "task" -class MonitorThread(object): - """Thread manager for monitoring celery events""" - def __init__(self, celery_app, interval=1): - self.celery_app = celery_app - self.interval = interval - - self.state = self.celery_app.events.State() - - self.thread = threading.Thread(target=self.run, args=()) - self.thread.daemon = True - self.thread.start() - - def catchall(self, event): - if event['type'] != 'worker-heartbeat': - self.state.event(event) - - if not 'uuid' in event: - return - - task = self.state.tasks.get(event['uuid']) - info = task.info() - - if 'name' in event and 'enqueue_events_for_site' in event['name']: - return - - try: - kwargs = eval(info.get('kwargs')) - - if 'site' in kwargs: - frappe.connect(kwargs['site']) - - if event['type']=='task-sent': - make_async_task({ - 'name': event['uuid'], - 'task_name': kwargs.get("cmd") or event['name'] - }) - - elif event['type']=='task-received': - try: - task = frappe.get_doc("Async Task", event['uuid']) - task.status = 'Started' - task.set_docstatus_user_and_timestamp() - task.db_update() - task.notify_update() - except frappe.DoesNotExistError: - pass - - elif event['type']=='task-succeeded': - try: - task = frappe.get_doc("Async Task", event['uuid']) - task.status = 'Succeeded' - task.result = info.get('result') - task.runtime = info.get('runtime') - task.set_docstatus_user_and_timestamp() - task.db_update() - task.notify_update() - except frappe.DoesNotExistError: - pass - - elif event['type']=='task-failed': - try: - task = frappe.get_doc("Async Task", event['uuid']) - task.status = 'Failed' - task.traceback = event.get('traceback') or event.get('exception') - task.traceback = frappe.as_json(info) + "\n\n" + task.traceback - task.runtime = info.get('runtime') - task.set_docstatus_user_and_timestamp() - task.db_update() - task.notify_update() - except frappe.DoesNotExistError: - pass - - frappe.db.commit() - except Exception: - print frappe.get_traceback() - finally: - frappe.destroy() - - - def run(self): - while True: - try: - with self.celery_app.connection() as connection: - recv = self.celery_app.events.Receiver(connection, handlers={ - '*': self.catchall - }) - recv.capture(limit=None, timeout=None, wakeup=True) - - except (KeyboardInterrupt, SystemExit): - raise - - except Exception: - # unable to capture - print "unable to capture:" - print frappe.get_traceback() - - time.sleep(self.interval) - - if __name__ == '__main__': app = get_celery() - if get_site_config().get("monitor_celery"): - MonitorThread(app) app.start() diff --git a/frappe/commands.py b/frappe/commands.py index b8468a84d5..cdacf47691 100644 --- a/frappe/commands.py +++ b/frappe/commands.py @@ -41,7 +41,7 @@ def pass_context(f): return click.pass_context(_func) def get_single_site(context): - if not len(context.sites) == 1: + if not context.sites or not len(context.sites) == 1: print 'please select a site' sys.exit(1) site = context.sites[0] @@ -714,6 +714,22 @@ def update_translations(context, lang, untranslated_file, translated_file): finally: frappe.destroy() +@click.command('import-translations') +@click.argument('lang') +@click.argument('path') +@pass_context +def import_translations(context, lang, path): + "Update translated strings" + import frappe.translate + site = get_single_site(context) + try: + frappe.init(site=site) + frappe.connect() + frappe.translate.import_translations(lang, path) + finally: + frappe.destroy() + + @click.command('set-admin-password') @click.argument('admin-password') @pass_context @@ -1032,6 +1048,7 @@ commands = [ build_message_files, get_untranslated, update_translations, + import_translations, set_admin_password, mysql, run_tests, diff --git a/frappe/core/doctype/async_task/__init__.py b/frappe/core/doctype/async_task/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/core/doctype/async_task/async_task.json b/frappe/core/doctype/async_task/async_task.json deleted file mode 100644 index d62cc8ce12..0000000000 --- a/frappe/core/doctype/async_task/async_task.json +++ /dev/null @@ -1,240 +0,0 @@ -{ - "allow_copy": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "", - "creation": "2015-07-03 11:28:03.496346", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "\nQueued\nRunning\nSucceeded\nFailed\n", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "task_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Task Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "runtime", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Runtime", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "result", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Result", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "traceback", - "fieldtype": "Code", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Traceback", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "section_break_6", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "reference_doctype", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Reference DocType", - "length": 0, - "no_copy": 0, - "options": "DocType", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "reference_name", - "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Reference Doc", - "length": 0, - "no_copy": 0, - "options": "reference_doctype", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2015-11-16 06:29:42.038458", - "modified_by": "Administrator", - "module": "Core", - "name": "Async Task", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "read_only": 0, - "read_only_onload": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "task_name" -} \ No newline at end of file diff --git a/frappe/core/doctype/async_task/async_task.py b/frappe/core/doctype/async_task/async_task.py deleted file mode 100644 index 85d043524b..0000000000 --- a/frappe/core/doctype/async_task/async_task.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.document import Document - -class AsyncTask(Document): - pass diff --git a/frappe/core/doctype/async_task/async_task_list.js b/frappe/core/doctype/async_task/async_task_list.js deleted file mode 100644 index 699da13084..0000000000 --- a/frappe/core/doctype/async_task/async_task_list.js +++ /dev/null @@ -1,10 +0,0 @@ -frappe.listview_settings['Async Task'] = { - add_fields: ["status"], - get_indicator: function(doc) { - if(doc.status==="Succeeded") { - return [__("Succeeded"), "green", "status,=,Succeeded"]; - } else if(doc.status==="Failed") { - return [__("Failed"), "red", "status,=,Failed"]; - } - } -}; diff --git a/frappe/core/doctype/async_task/test_async_task.py b/frappe/core/doctype/async_task/test_async_task.py deleted file mode 100644 index 1e885f27f9..0000000000 --- a/frappe/core/doctype/async_task/test_async_task.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt -from __future__ import unicode_literals - -import frappe -import unittest - -# test_records = frappe.get_test_records('Async Task') - -class TestAsyncTask(unittest.TestCase): - pass diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 0912d12ed5..85cf7fcd8b 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -59,5 +59,5 @@ class InvalidEmailAddressError(ValidationError): pass class TemplateNotFoundError(ValidationError): pass class UniqueValidationError(ValidationError): pass class AppNotInstalledError(ValidationError): pass -class IncorrectSitePath(DoesNotExistError): pass +class IncorrectSitePath(NotFound): pass diff --git a/frappe/translate.py b/frappe/translate.py index 210edcc319..ec6f6f42c9 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -186,26 +186,30 @@ def load_lang(lang, apps=None): out = {} for app in (apps or frappe.get_all_apps(True)): path = os.path.join(frappe.get_pymodule_path(app), "translations", lang + ".csv") - if os.path.exists(path): - csv_content = read_csv_file(path) - - cleaned = {} - for item in csv_content: - if len(item)==3: - # with file and line numbers - cleaned[item[1]] = strip(item[2]) - - elif len(item)==2: - cleaned[item[0]] = strip(item[1]) - - else: - raise Exception("Bad translation in '{app}' for language '{lang}': {values}".format( - app=app, lang=lang, values=repr(item).encode("utf-8") - )) - - out.update(cleaned) + out.update(get_translation_dict_from_file(path, lang, app)) return out +def get_translation_dict_from_file(path, lang, app): + """load translation dict from given path""" + cleaned = {} + if os.path.exists(path): + csv_content = read_csv_file(path) + + for item in csv_content: + if len(item)==3: + # with file and line numbers + cleaned[item[1]] = strip(item[2]) + + elif len(item)==2: + cleaned[item[0]] = strip(item[1]) + + else: + raise Exception("Bad translation in '{app}' for language '{lang}': {values}".format( + app=app, lang=lang, values=repr(item).encode("utf-8") + )) + + return cleaned + def clear_cache(): """Clear all translation assets from :meth:`frappe.cache`""" cache = frappe.cache() @@ -507,6 +511,16 @@ def update_translations(lang, untranslated_file, translated_file): for app in frappe.get_all_apps(True): write_translations_file(app, lang, full_dict) +def import_translations(lang, path): + """Import translations from file in standard format""" + clear_cache() + full_dict = get_full_dict(lang) + full_dict.update(get_translation_dict_from_file(path, lang, 'import')) + + for app in frappe.get_all_apps(True): + write_translations_file(app, lang, full_dict) + + def rebuild_all_translation_files(): """Rebuild all translation files: `[app]/translations/[lang].csv`.""" for lang in get_all_languages():