def import_csv(context, path, only_insert=False, submit_after_import=False, ignore_encoding_errors=False): "Import CSV using data import tool" from frappe.core.page.data_import_tool import importer from frappe.utils.csvutils import read_csv_content site = get_site(context) with open(path, "r") as csvfile: content = read_csv_content(csvfile.read()) frappe.init(site=site) frappe.connect() try: importer.upload( content, submit_after_import=submit_after_import, ignore_encoding_errors=ignore_encoding_errors, overwrite=not only_insert, via_console=True, ) frappe.db.commit() except Exception: print frappe.get_traceback() frappe.destroy()
def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_password=None, db_name=None, verbose=None, install_app=None, admin_password=None, force=None, with_public_files=None, with_private_files=None): "Restore site database from an sql file" from frappe.installer import extract_sql_gzip, extract_tar_files # Extract the gzip file if user has passed *.sql.gz file instead of *.sql file if not os.path.exists(sql_file_path): sql_file_path = '../' + sql_file_path if not os.path.exists(sql_file_path): print('Invalid path {0}' + sql_file_path[3:]) sys.exit(1) if sql_file_path.endswith('sql.gz'): sql_file_path = extract_sql_gzip(os.path.abspath(sql_file_path)) site = get_site(context) frappe.init(site=site) _new_site(frappe.conf.db_name, site, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, admin_password=admin_password, verbose=context.verbose, install_apps=install_app, source_sql=sql_file_path, force=context.force) # Extract public and/or private files to the restored site, if user has given the path if with_public_files: public = extract_tar_files(site, with_public_files, 'public') os.remove(public) if with_private_files: private = extract_tar_files(site, with_private_files, 'private') os.remove(private)
def list_apps(context): "List apps in site" site = get_site(context) frappe.init(site=site) frappe.connect() print("\n".join(frappe.get_installed_apps())) frappe.destroy()
def scheduler_task(site, event, handler, now=False): from frappe.utils.scheduler import log traceback = "" task_logger.info('running {handler} for {site} for event: {event}'.format(handler=handler, site=site, event=event)) try: frappe.init(site=site) if not create_lock(handler): return if not now: frappe.connect(site=site) frappe.get_attr(handler)() except Exception: frappe.db.rollback() traceback = log(handler, "Method: {event}, Handler: {handler}".format(event=event, handler=handler)) task_logger.warn(traceback) raise else: frappe.db.commit() finally: delete_lock(handler) if not now: frappe.destroy() task_logger.info('ran {handler} for {site} for event: {event}'.format(handler=handler, site=site, event=event))
def run_async_task(self, site, user, cmd, form_dict): ret = {} frappe.init(site) frappe.connect() sys.stdout, sys.stderr = get_std_streams(self.request.id) frappe.local.stdout, frappe.local.stderr = sys.stdout, sys.stderr frappe.local.task_id = self.request.id frappe.cache() try: set_task_status(self.request.id, "Running") frappe.db.commit() frappe.set_user(user) # sleep(60) frappe.local.form_dict = frappe._dict(form_dict) execute_cmd(cmd, from_async=True) ret = frappe.local.response except Exception, e: frappe.db.rollback() if not frappe.flags.in_test: frappe.db.commit() ret = frappe.local.response http_status_code = getattr(e, "http_status_code", 500) ret['status_code'] = http_status_code frappe.errprint(frappe.get_traceback()) frappe.utils.response.make_logs() set_task_status(self.request.id, "Failed", response=ret) task_logger.error('Exception in running {}: {}'.format(cmd, ret['exc']))
def get_version(): "Show the versions of all the installed apps" frappe.init('') for m in sorted(frappe.get_all_apps()): module = frappe.get_module(m) if hasattr(module, "__version__"): print("{0} {1}".format(m, module.__version__))
def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None, profile=False): "Run tests" import frappe.test_runner from frappe.utils import sel tests = test site = get_site(context) frappe.init(site=site) if frappe.conf.run_selenium_tests and False: sel.start(context.verbose, driver) try: ret = frappe.test_runner.main( app, module, doctype, context.verbose, tests=tests, force=context.force, profile=profile ) if len(ret.failures) == 0 and len(ret.errors) == 0: ret = 0 finally: pass if frappe.conf.run_selenium_tests: sel.close() sys.exit(ret)
def dump_queue_status(): "Dump detailed diagnostic infomation for task queues in JSON format" frappe.init("") from frappe.utils.doctor import dump_queue_status as _dump_queue_status, inspect_queue print json.dumps(_dump_queue_status(), indent=1) inspect_queue()
def run_async_task(self, site=None, user=None, cmd=None, form_dict=None, hijack_std=False): ret = {} frappe.init(site) frappe.connect() frappe.local.task_id = self.request.id if hijack_std: original_stdout, original_stderr = sys.stdout, sys.stderr sys.stdout, sys.stderr = get_std_streams(self.request.id) frappe.local.stdout, frappe.local.stderr = sys.stdout, sys.stderr try: set_task_status(self.request.id, "Running") frappe.db.commit() frappe.set_user(user) # sleep(60) frappe.local.form_dict = frappe._dict(form_dict) execute_cmd(cmd, from_async=True) ret = frappe.local.response except Exception, e: frappe.db.rollback() ret = frappe.local.response http_status_code = getattr(e, "http_status_code", 500) ret['status_code'] = http_status_code frappe.errprint(frappe.get_traceback()) frappe.utils.response.make_logs() set_task_status(self.request.id, "Error", response=ret) task_logger.error('Exception in running {}: {}'.format(cmd, ret['exc']))
def console(context): "Start ipython console for a site" site = get_single_site(context) frappe.init(site=site) frappe.connect() import IPython IPython.embed()
def enqueue_events_for_site(site, queued_jobs): try: frappe.init(site=site) if frappe.local.conf.maintenance_mode: return if frappe.local.conf.pause_scheduler: return frappe.connect() if is_scheduler_disabled(): return enqueue_events(site=site, queued_jobs=queued_jobs) # TODO this print call is a tempfix till logging is fixed! print 'Queued events for site {0}'.format(site) frappe.logger(__name__).debug('Queued events for site {0}'.format(site)) except: frappe.logger(__name__).error('Exception in Enqueue Events for Site {0}'.format(site)) raise finally: frappe.destroy()
def backup( context, with_files=False, backup_path_db=None, backup_path_files=None, backup_path_private_files=None, quiet=False ): "Backup" from frappe.utils.backups import scheduled_backup verbose = context.verbose for site in context.sites: frappe.init(site=site) frappe.connect() odb = scheduled_backup( ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files, backup_path_private_files=backup_path_private_files, force=True, ) if verbose: from frappe.utils import now print "database backup taken -", odb.backup_path_db, "- on", now() if with_files: print "files backup taken -", odb.backup_path_files, "- on", now() print "private files backup taken -", odb.backup_path_private_files, "- on", now() frappe.destroy()
def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None, profile=False, coverage=False, junit_xml_output=False, ui_tests = False, doctype_list_path=None, skip_test_records=False, skip_before_tests=False, failfast=False): "Run tests" import frappe.test_runner tests = test site = get_site(context) frappe.init(site=site) frappe.flags.skip_before_tests = skip_before_tests frappe.flags.skip_test_records = skip_test_records if coverage: # Generate coverage report only for app that is being tested source_path = os.path.join(get_bench_path(), 'apps', app or 'frappe') cov = Coverage(source=[source_path], omit=['*.html', '*.js', '*.css']) cov.start() ret = frappe.test_runner.main(app, module, doctype, context.verbose, tests=tests, force=context.force, profile=profile, junit_xml_output=junit_xml_output, ui_tests = ui_tests, doctype_list_path = doctype_list_path, failfast=failfast) if coverage: cov.stop() cov.save() if len(ret.failures) == 0 and len(ret.errors) == 0: ret = 0 if os.environ.get('CI'): sys.exit(ret)
def import_csv(context, path, only_insert=False, submit_after_import=False, ignore_encoding_errors=False, no_email=True): "Import CSV using data import tool" from frappe.core.page.data_import_tool import importer from frappe.utils.csvutils import read_csv_content site = get_site(context) if not os.path.exists(path): path = os.path.join('..', path) if not os.path.exists(path): print('Invalid path {0}'.format(path)) sys.exit(1) with open(path, 'r') as csvfile: content = read_csv_content(csvfile.read()) frappe.init(site=site) frappe.connect() try: importer.upload(content, submit_after_import=submit_after_import, no_email=no_email, ignore_encoding_errors=ignore_encoding_errors, overwrite=not only_insert, via_console=True) frappe.db.commit() except Exception: print(frappe.get_traceback()) frappe.destroy()
def purge_all_tasks(): "Purge any pending periodic tasks of 'all' event. Doesn't purge hourly, daily and weekly" frappe.init("") from frappe.utils.doctor import purge_pending_tasks count = purge_pending_tasks() print "Purged {} tasks".format(count)
def scheduler(context, state, site=None): from frappe.installer import update_site_config import frappe.utils.scheduler if not site: site = get_site(context) try: frappe.init(site=site) if state == 'pause': update_site_config('pause_scheduler', 1) elif state == 'resume': update_site_config('pause_scheduler', 0) elif state == 'disable': frappe.connect() frappe.utils.scheduler.disable_scheduler() frappe.db.commit() elif state == 'enable': frappe.connect() frappe.utils.scheduler.enable_scheduler() frappe.db.commit() print('Scheduler {0}d for site {1}'.format(state, site)) finally: frappe.destroy()
def new_site( site, mariadb_root_username=None, mariadb_root_password=None, admin_password=None, verbose=False, install_apps=None, source_sql=None, force=None, install_app=None, db_name=None, ): "Install a new site" if not db_name: db_name = hashlib.sha1(site).hexdigest()[:10] frappe.init(site=site) _new_site( db_name, site, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, admin_password=admin_password, verbose=verbose, install_apps=install_app, source_sql=source_sql, force=force, ) if len(frappe.utils.get_sites()) == 1: use(site)
def _new_site(db_name, site, mariadb_root_username=None, mariadb_root_password=None, admin_password=None, verbose=False, install_apps=None, source_sql=None,force=False, reinstall=False): "Install a new Frappe site" from frappe.installer import install_db, make_site_dirs from frappe.installer import install_app as _install_app import frappe.utils.scheduler frappe.init(site=site) try: # enable scheduler post install? enable_scheduler = _is_scheduler_enabled() except: enable_scheduler = False install_db(root_login=mariadb_root_username, root_password=mariadb_root_password, db_name=db_name, admin_password=admin_password, verbose=verbose, source_sql=source_sql,force=force, reinstall=reinstall) make_site_dirs() _install_app("frappe", verbose=verbose, set_as_patched=not source_sql) if frappe.conf.get("install_apps"): for app in frappe.conf.install_apps: _install_app(app, verbose=verbose, set_as_patched=not source_sql) if install_apps: for app in install_apps: _install_app(app, verbose=verbose, set_as_patched=not source_sql) frappe.utils.scheduler.toggle_scheduler(enable_scheduler) scheduler_status = "disabled" if frappe.utils.scheduler.is_scheduler_disabled() else "enabled" print "*** Scheduler is", scheduler_status, "***" frappe.destroy()
def set_config(context, key, value): "Insert/Update a value in site_config.json" from frappe.installer import update_site_config for site in context.sites: frappe.init(site=site) update_site_config(key, value) frappe.destroy()
def execute(context, method, args=None, kwargs=None): "execute a function" for site in context.sites: try: frappe.init(site=site) frappe.connect() if args: args = eval(args) else: args = () if kwargs: kwargs = eval(args) else: kwargs = {} ret = frappe.get_attr(method)(*args, **kwargs) if frappe.db: frappe.db.commit() finally: frappe.destroy() if ret: print json.dumps(ret)
def purge_jobs(site=None, queue=None, event=None): "Purge any pending periodic tasks, if event option is not given, it will purge everything for the site" from frappe.utils.doctor import purge_pending_jobs frappe.init(site or "") count = purge_pending_jobs(event=event, site=site, queue=queue) print "Purged {} jobs".format(count)
def restore( context, sql_file_path, mariadb_root_username=None, mariadb_root_password=None, db_name=None, verbose=None, install_app=None, admin_password=None, force=None, ): "Restore site database from an sql file" site = get_single_site(context) frappe.init(site=site) if not db_name: db_name = frappe.conf.db_name _new_site( db_name, site, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, admin_password=admin_password, verbose=context.verbose, install_apps=install_app, source_sql=sql_file_path, force=context.force, )
def list_apps(context): "Reinstall site ie. wipe all data and start over" site = get_single_site(context) frappe.init(site=site) frappe.connect() print "\n".join(frappe.get_installed_apps()) frappe.destroy()
def init_site(request): site = _site or request.headers.get('X-Frappe-Site-Name') or get_site_name(request.host) frappe.init(site=site, sites_path=_sites_path) if not (frappe.local.conf and frappe.local.conf.db_name): # site does not exist raise NotFound
def build(make_copy=False, verbose=False): "Minify + concatenate JS and CSS files, build translations" import frappe.build import frappe frappe.init("") frappe.build.bundle(False, make_copy=make_copy, verbose=verbose)
def request(context, args=None, path=None): "Run a request as an admin" import frappe.handler import frappe.api for site in context.sites: try: frappe.init(site=site) frappe.connect() if args: if "?" in args: frappe.local.form_dict = frappe._dict([a.split("=") for a in args.split("?")[-1].split("&")]) else: frappe.local.form_dict = frappe._dict() if args.startswith("/api/method"): frappe.local.form_dict.cmd = args.split("?")[0].split("/")[-1] elif path: with open(os.path.join('..', path), 'r') as f: args = json.loads(f.read()) frappe.local.form_dict = frappe._dict(args) frappe.handler.execute_cmd(frappe.form_dict.cmd) print(frappe.response) finally: frappe.destroy()
def watch(): "Watch and concatenate JS and CSS files as and when they change" # if os.environ.get('CI'): # return import frappe.build frappe.init('') frappe.build.watch(True)
def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_password=None, db_name=None, verbose=None, install_app=None, admin_password=None, force=None): "Restore site database from an sql file" site = get_single_site(context) frappe.init(site=site) db_name = db_name or frappe.conf.db_name or hashlib.sha1(site).hexdigest()[:10] _new_site(db_name, site, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, admin_password=admin_password, verbose=context.verbose, install_apps=install_app, source_sql=sql_file_path, force=context.force)
def scheduler(context, state, site=None): from frappe.installer import update_site_config import frappe.utils.scheduler if not site: site = get_site(context) try: frappe.init(site=site) if state == "pause": update_site_config("pause_scheduler", 1) elif state == "resume": update_site_config("pause_scheduler", 0) elif state == "disable": frappe.connect() frappe.utils.scheduler.disable_scheduler() frappe.db.commit() elif state == "enable": frappe.connect() frappe.utils.scheduler.enable_scheduler() frappe.db.commit() print "Scheduler {0}d for site {1}".format(state, site) finally: frappe.destroy()
def migrate(context, rebuild_website=False): "Run patches, sync schema and rebuild files/translations" import frappe.modules.patch_handler import frappe.model.sync from frappe.utils.fixtures import sync_fixtures import frappe.translate from frappe.desk.notifications import clear_notifications for site in context.sites: print 'Migrating', site frappe.init(site=site) frappe.connect() try: prepare_for_update() # run patches frappe.modules.patch_handler.run_all() # sync frappe.model.sync.sync_all(verbose=context.verbose) frappe.translate.clear_cache() sync_fixtures() clear_notifications() finally: frappe.destroy() if rebuild_website: call_command(build_website, context) else: call_command(sync_www, context)
def migrate(context, rebuild_website=False, skip_failing=False): "Run patches, sync schema and rebuild files/translations" from frappe.migrate import migrate for site in context.sites: print('Migrating', site) frappe.init(site=site) frappe.connect() try: migrate(context.verbose, rebuild_website=rebuild_website, skip_failing=skip_failing) finally: frappe.destroy() if not context.sites: raise SiteNotSpecifiedError print("Compiling Python Files...") compileall.compile_dir('../apps', quiet=1, rx=re.compile('.*node_modules.*'))
def request(context, args): "Run a request as an admin" import frappe.handler import frappe.api for site in context.sites: try: frappe.init(site=site) frappe.connect() if "?" in args: frappe.local.form_dict = frappe._dict([a.split("=") for a in args.split("?")[-1].split("&")]) else: frappe.local.form_dict = frappe._dict() if args.startswith("/api/method"): frappe.local.form_dict.cmd = args.split("?")[0].split("/")[-1] frappe.handler.execute_cmd(frappe.form_dict.cmd) print frappe.response finally: frappe.destroy()
def set_admin_password(context, admin_password, logout_all_sessions=False): "Set Administrator password for a site" import getpass from frappe.utils.password import update_password for site in context.sites: try: frappe.init(site=site) while not admin_password: admin_password = getpass.getpass( "Administrator's password for {0}: ".format(site)) frappe.connect() update_password(user='******', pwd=admin_password, logout_all_sessions=logout_all_sessions) frappe.db.commit() admin_password = None finally: frappe.destroy()
def init_request(request): frappe.local.request = request frappe.local.is_ajax = frappe.get_request_header( "X-Requested-With") == "XMLHttpRequest" site = _site or request.headers.get('X-Frappe-Site-Name') or get_site_name( request.host) frappe.init(site=site, sites_path=_sites_path) if not (frappe.local.conf and frappe.local.conf.db_name): # site does not exist raise NotFound if frappe.local.conf.get('maintenance_mode'): frappe.connect() raise frappe.SessionStopped('Session Stopped') make_form_dict(request) if request.method != "OPTIONS": frappe.local.http_request = frappe.auth.HTTPRequest()
def extract_tar_files(site_name, file_path, folder_name): # Need to do frappe.init to maintain the site locals frappe.init(site=site_name) abs_site_path = os.path.abspath(frappe.get_site_path()) # Copy the files to the parent directory and extract shutil.copy2(os.path.abspath(file_path), abs_site_path) # Get the file name splitting the file path on tar_name = os.path.split(file_path)[1] tar_path = os.path.join(abs_site_path, tar_name) try: subprocess.check_output(['tar', 'xvf', tar_path, '--strip', '2'], cwd=abs_site_path) except: raise finally: frappe.destroy() return tar_path
def import_csv(context, path, only_insert=False, submit_after_import=False, ignore_encoding_errors=False): "Import CSV using data import tool" from frappe.core.page.data_import_tool import importer from frappe.utils.csvutils import read_csv_content site = get_single_site(context) with open(path, 'r') as csvfile: content = read_csv_content(csvfile.read()) frappe.init(site=site) frappe.connect() try: importer.upload(content, submit_after_import=submit_after_import, ignore_encoding_errors=ignore_encoding_errors, overwrite=not only_insert, via_console=True) frappe.db.commit() except Exception: print frappe.get_traceback() frappe.destroy()
def trigger_scheduler_event(context, event): import frappe.utils.scheduler exit_code = 0 for site in context.sites: try: frappe.init(site=site) frappe.connect() try: frappe.get_doc("Scheduled Job Type", {"method": event}).execute() except frappe.DoesNotExistError: click.secho(f"Event {event} does not exist!", fg="red") exit_code = 1 finally: frappe.destroy() if not context.sites: raise SiteNotSpecifiedError sys.exit(exit_code)
def execute(**kwargs): """ Use this to install apps; it checks for apps that are already installed. bench --site [site_name] execute [module_name].install_apps.execute --kwargs "{'apps': ['rebrandly_integration', 'printnode_integration']}" """ apps_installed = frappe.db.sql( """SELECT DISTINCT app_name FROM `tabModule Def`""", as_dict=True) apps_installed = [v.app_name for v in apps_installed] for app in kwargs['apps']: if app not in apps_installed: print 'Installing app {0}'.format(app) frappe.init(site=kwargs['site']) frappe.connect() try: _install_app(app, verbose=False) finally: frappe.destroy()
def migrate_sites(maintenance_mode=False): installed_sites = ":".join(get_sites()) sites = os.environ.get("SITES", installed_sites).split(":") if not maintenance_mode: maintenance_mode = cint(os.environ.get("MAINTENANCE_MODE")) if maintenance_mode: set_maintenance_mode(True) for site in sites: print('Migrating', site) frappe.init(site=site) frappe.connect() try: from frappe.migrate import migrate migrate() finally: frappe.destroy() # Disable maintenance mode after migration set_maintenance_mode(False)
def migrate_sites(maintenance_mode=False): installed_sites = ":".join(get_sites()) sites = os.environ.get("SITES", installed_sites).split(":") if not maintenance_mode: maintenance_mode = True if os.environ.get( "MAINTENANCE_MODE") else False if maintenance_mode: set_maintenance_mode(True) for site in sites: print('Migrating', site) frappe.init(site=site) frappe.connect() try: migrate() finally: frappe.destroy() if maintenance_mode: set_maintenance_mode(False)
def _build_docs_once(site, app, docs_version, target, local, only_content_updated=False): from frappe.utils.setup_docs import setup_docs try: frappe.init(site=site) frappe.connect() make = setup_docs(app) if not only_content_updated: make.build(docs_version) make.make_docs(target, local) finally: frappe.destroy()
def auto_deploy(context, app, migrate=False, restart=False, remote='upstream'): '''Pull and migrate sites that have new version''' from frappe.utils.gitutils import get_app_branch from frappe.utils import get_sites branch = get_app_branch(app) app_path = frappe.get_app_path(app) # fetch subprocess.check_output(['git', 'fetch', remote, branch], cwd=app_path) # get diff if subprocess.check_output( ['git', 'diff', '{0}..upstream/{0}'.format(branch)], cwd=app_path): print('Updates found for {0}'.format(app)) if app == 'frappe': # run bench update subprocess.check_output(['bench', 'update', '--no-backup'], cwd='..') else: updated = False subprocess.check_output( ['git', 'pull', '--rebase', 'upstream', branch], cwd=app_path) # find all sites with that app for site in get_sites(): frappe.init(site) if app in frappe.get_installed_apps(): print('Updating {0}'.format(site)) updated = True subprocess.check_output( ['bench', '--site', site, 'clear-cache'], cwd='..') if migrate: subprocess.check_output( ['bench', '--site', site, 'migrate'], cwd='..') frappe.destroy() if updated and restart: subprocess.check_output(['bench', 'restart'], cwd='..') else: print('No Updates')
def import_csv( context, path, only_insert=False, submit_after_import=False, ignore_encoding_errors=False, no_email=True, ): "Import CSV using data import" from frappe.core.doctype.data_import_legacy import importer from frappe.utils.csvutils import read_csv_content site = get_site(context) if not os.path.exists(path): path = os.path.join("..", path) if not os.path.exists(path): print("Invalid path {0}".format(path)) sys.exit(1) with open(path, "r") as csvfile: content = read_csv_content(csvfile.read()) frappe.init(site=site) frappe.connect() try: importer.upload( content, submit_after_import=submit_after_import, no_email=no_email, ignore_encoding_errors=ignore_encoding_errors, overwrite=not only_insert, via_console=True, ) frappe.db.commit() except Exception: print(frappe.get_traceback()) frappe.destroy()
def main(): parsed_args = frappe._dict(vars(setup_parser())) fn = get_function(parsed_args) if parsed_args.get("sites_path"): parsed_args["sites_path"] = parsed_args["sites_path"][0] else: parsed_args["sites_path"] = os.environ.get("SITES_PATH", ".") sites_path = parsed_args.get("sites_path") if not parsed_args.get("make_app"): if parsed_args.get("site") == "all": for site in get_sites(parsed_args["sites_path"]): print "\nRunning", fn, "for", site print "-" * 50 args = parsed_args.copy() args["site"] = site frappe.init(site, sites_path=sites_path) ret = run(fn, args) if ret: # if there's a return value, it's an error, so quit return ret else: site = get_site(parsed_args) if fn not in site_arg_optional and not site: print 'site argument required' return 1 elif site: frappe.init(site, sites_path=sites_path) else: # site argument optional frappe.init("", sites_path=sites_path) return run(fn, parsed_args) else: return run(fn, parsed_args)
def get_version(output): """Show the versions of all the installed apps.""" from git import Repo from frappe.utils.commands import render_table from frappe.utils.change_log import get_app_branch frappe.init("") data = [] for app in sorted(frappe.get_all_apps()): module = frappe.get_module(app) app_hooks = frappe.get_module(app + ".hooks") repo = Repo(frappe.get_app_path(app, "..")) app_info = frappe._dict() app_info.app = app app_info.branch = get_app_branch(app) app_info.commit = repo.head.object.hexsha[:7] app_info.version = getattr(app_hooks, f"{app_info.branch}_version", None) or module.__version__ data.append(app_info) { "legacy": lambda: [ click.echo(f"{app_info.app} {app_info.version}") for app_info in data ], "plain": lambda: [ click.echo(f"{app_info.app} {app_info.version} {app_info.branch} ({app_info.commit})") for app_info in data ], "table": lambda: render_table( [["App", "Version", "Branch", "Commit"]] + [ [app_info.app, app_info.version, app_info.branch, app_info.commit] for app_info in data ] ), "json": lambda: click.echo(json.dumps(data, indent=4)), }[output]()
def build(app=None, apps=None, hard_link=False, make_copy=False, restore=False, production=False, verbose=False, force=False): "Compile JS and CSS source files" from frappe.build import bundle, download_frappe_assets frappe.init('') if not apps and app: apps = app # dont try downloading assets if force used, app specified or running via CI if not (force or apps or os.environ.get('CI')): # skip building frappe if assets exist remotely skip_frappe = download_frappe_assets(verbose=verbose) else: skip_frappe = False # don't minify in developer_mode for faster builds development = frappe.local.conf.developer_mode or frappe.local.dev_server mode = "development" if development else "production" if production: mode = "production" if make_copy or restore: hard_link = make_copy or restore click.secho( "bench build: --make-copy and --restore options are deprecated in favour of --hard-link", fg="yellow", ) bundle(mode, apps=apps, hard_link=hard_link, verbose=verbose, skip_frappe=skip_frappe)
def main(): parsed_args = frappe._dict(vars(setup_parser())) fn = get_function(parsed_args) if parsed_args.get("sites_path"): parsed_args["sites_path"] = parsed_args["sites_path"][0] else: parsed_args["sites_path"] = os.environ.get("SITES_PATH", ".") sites_path = parsed_args.get("sites_path") if not parsed_args.get("make_app"): if parsed_args.get("site")=="all": for site in get_sites(parsed_args["sites_path"]): args = parsed_args.copy() args["site"] = site frappe.init(site, sites_path=sites_path) run(fn, args) else: site = get_site(parsed_args) if fn not in site_arg_optional and not site: print 'site argument required' exit(1) elif site: frappe.init(site, sites_path=sites_path) else: # site argument optional frappe.init("", sites_path=sites_path) run(fn, parsed_args) else: run(fn, parsed_args)
def _drop_site(site, root_login='******', root_password=None, archived_sites_path=None, force=False): "Remove site from database and filesystem" from frappe.database import drop_user_and_database from frappe.utils.backups import scheduled_backup frappe.init(site=site) frappe.connect() try: scheduled_backup(ignore_files=False, force=True) except Exception as err: if force: pass else: click.echo("=" * 80) click.echo( "Error: The operation has stopped because backup of {s}'s database failed." .format(s=site)) click.echo("Reason: {reason}{sep}".format(reason=err[1], sep="\n")) click.echo("Fix the issue and try again.") click.echo( "Hint: Use 'bench drop-site {s} --force' to force the removal of {s}" .format(sep="\n", tab="\t", s=site)) sys.exit(1) drop_user_and_database(frappe.conf.db_name, root_login, root_password) if not archived_sites_path: archived_sites_path = os.path.join(frappe.get_app_path('frappe'), '..', '..', '..', 'archived_sites') if not os.path.exists(archived_sites_path): os.mkdir(archived_sites_path) move(archived_sites_path, site)
def _reinstall(site, admin_password=None, mariadb_root_username=None, mariadb_root_password=None, yes=False, verbose=False): from frappe.installer import _new_site if not yes: click.confirm('This will wipe your database. Are you sure you want to reinstall?', abort=True) try: frappe.init(site=site) frappe.connect() frappe.clear_cache() installed = frappe.get_installed_apps() frappe.clear_cache() except Exception: installed = [] finally: if frappe.db: frappe.db.close() frappe.destroy() frappe.init(site=site) _new_site(frappe.conf.db_name, site, verbose=verbose, force=True, reinstall=True, install_apps=installed, mariadb_root_username=mariadb_root_username, mariadb_root_password=mariadb_root_password, admin_password=admin_password)
def run_tests(context, app=None, module=None, doctype=None, test=(), driver=None): "Run tests" import frappe.test_runner from frappe.utils import sel tests = test site = get_single_site(context) frappe.init(site=site) if frappe.conf.run_selenium_tests and False: sel.start(context.verbose, driver) try: ret = frappe.test_runner.main(app, module, doctype, context.verbose, tests=tests, force=context.force) if len(ret.failures) == 0 and len(ret.errors) == 0: ret = 0 finally: pass if frappe.conf.run_selenium_tests: sel.close() sys.exit(ret)
def backup(context, with_files=False, backup_path_db=None, backup_path_files=None, quiet=False): "Backup" from frappe.utils.backups import scheduled_backup verbose = context.verbose for site in context.sites: frappe.init(site=site) frappe.connect() odb = scheduled_backup(ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files, force=True) if verbose: from frappe.utils import now print "database backup taken -", odb.backup_path_db, "- on", now() if with_files: print "files backup taken -", odb.backup_path_files, "- on", now( ) frappe.destroy()
def set_config(context, key, value, global_=False, as_dict=False): "Insert/Update a value in site_config.json" from frappe.installer import update_site_config import ast if as_dict: value = ast.literal_eval(value) if global_: sites_path = os.getcwd() # big assumption. common_site_config_path = os.path.join(sites_path, 'common_site_config.json') update_site_config(key, value, validate=False, site_config_path=common_site_config_path) else: for site in context.sites: frappe.init(site=site) update_site_config(key, value, validate=False) frappe.destroy() else: raise SiteNotSpecifiedError
def set_user_password(site, user, password, logout_all_sessions=False): import getpass from frappe.utils.password import update_password try: frappe.init(site=site) while not password: password = getpass.getpass(f"{user}'s password for {site}: ") frappe.connect() if not frappe.db.exists("User", user): print(f"User {user} does not exist") sys.exit(1) update_password(user=user, pwd=password, logout_all_sessions=logout_all_sessions) frappe.db.commit() password = None finally: frappe.destroy()
def run_ui_tests(context, app=None, test=False, test_list=False, profile=False): "Run UI tests" import frappe.test_runner site = get_site(context) frappe.init(site=site) frappe.connect() ret = frappe.test_runner.run_ui_tests(app=app, test=test, test_list=test_list, verbose=context.verbose, profile=profile) if len(ret.failures) == 0 and len(ret.errors) == 0: ret = 0 if os.environ.get('CI'): sys.exit(ret)
def console(context): "Start ipython console for a site" site = get_site(context) frappe.init(site=site) frappe.connect() frappe.local.lang = frappe.db.get_default("lang") import IPython all_apps = frappe.get_installed_apps() failed_to_import = [] for app in all_apps: try: locals()[app] = __import__(app) except ModuleNotFoundError: failed_to_import.append(app) print("Apps in this namespace:\n{}".format(", ".join(all_apps))) if failed_to_import: print("\nFailed to import:\n{}".format(", ".join(failed_to_import))) IPython.embed(display_banner="", header="", colors="neutral")
def ready_for_migration(context, site=None): from frappe.utils.doctor import get_pending_jobs if not site: site = get_site(context) try: frappe.init(site=site) pending_jobs = get_pending_jobs(site=site) if pending_jobs: print 'NOT READY for migration: site {0} has pending background jobs'.format( site) sys.exit(1) else: print 'READY for migration: site {0} does not have any background jobs'.format( site) return 0 finally: frappe.destroy()
def run_ui_tests(context, app=None, ci=False): "Run UI tests" import subprocess site = get_site(context) frappe.init(site=site) if app is None: app = ",".join(frappe.get_installed_apps()) cmd = [ './node_modules/.bin/nightwatch', '--config', './apps/frappe/frappe/nightwatch.js', '--app', app, '--site', site ] if ci: cmd.extend(['--env', 'ci_server']) bench_path = frappe.utils.get_bench_path() subprocess.call(cmd, cwd=bench_path)
def mariadb(context): """ Enter into mariadb console for a given site. """ import os site = get_site(context) if not site: raise SiteNotSpecifiedError frappe.init(site=site) # This is assuming you're within the bench instance. mysql = find_executable('mysql') os.execv(mysql, [ mysql, '-u', frappe.conf.db_name, '-p'+frappe.conf.db_password, frappe.conf.db_name, '-h', frappe.conf.db_host or "localhost", '--pager=less -SFX', '--safe-updates', "-A"])
def execute(context, method, args=None, kwargs=None, profile=False): "Execute a function" for site in context.sites: try: frappe.init(site=site) frappe.connect() if args: try: args = eval(args) except NameError: args = [args] else: args = () if kwargs: kwargs = eval(kwargs) else: kwargs = {} if profile: pr = cProfile.Profile() pr.enable() ret = frappe.get_attr(method)(*args, **kwargs) if profile: pr.disable() s = StringIO() pstats.Stats(pr, stream=s).sort_stats('cumulative').print_stats(.5) print(s.getvalue()) if frappe.db: frappe.db.commit() finally: frappe.destroy() if ret: print(json.dumps(ret, default=json_handler))
def extract_tar_files(site_name, file_path, folder_name): # Need to do frappe.init to maintain the site locals frappe.init(site=site_name) abs_site_path = os.path.abspath(frappe.get_site_path()) # While creating tar files during backup, a complete recursive structure is created. # For example, <site_name>/<private>/<files>/*.* # Shift to parent directory and make it as current directory and do the extraction. _parent_dir = os.path.dirname(abs_site_path) os.chdir(_parent_dir) # Copy the files to the parent directory and extract shutil.copy2(os.path.abspath(file_path), _parent_dir) # Get the file name splitting the file path on filename = file_path.split('/')[-1] filepath = os.path.join(_parent_dir, filename) try: error = subprocess.check_output(['tar', 'xvf', filepath]) except Exception as subprocess.CalledProcessError: print subprocess.CalledProcessError.output