[fix] NotFound if site is not found, remove Async Task, cleanup in translate
This commit is contained in:
parent
247a484cd0
commit
6ba4bb06ff
9 changed files with 51 additions and 402 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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"];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue