コード例 #1
0
ファイル: __init__.py プロジェクト: 81552433qqcom/frappe
def create_folder(path, with_init=False):
	from frappe.utils import touch_file
	if not os.path.exists(path):
		os.makedirs(path)

		if with_init:
			touch_file(os.path.join(path, "__init__.py"))
コード例 #2
0
ファイル: __init__.py プロジェクト: yangfenxiangyocom/frappe
def create_folder(path, with_init=False):
    from frappe.utils import touch_file
    if not os.path.exists(path):
        os.makedirs(path)

        if with_init:
            touch_file(os.path.join(path, "__init__.py"))
コード例 #3
0
ファイル: __init__.py プロジェクト: zeetyproyectos/frappe
def create_folder(path, with_init=False):
	"""Create a folder in the given path and add an `__init__.py` file (optional).

	:param path: Folder path.
	:param with_init: Create `__init__.py` in the new folder."""
	from frappe.utils import touch_file
	if not os.path.exists(path):
		os.makedirs(path)

		if with_init:
			touch_file(os.path.join(path, "__init__.py"))
コード例 #4
0
ファイル: __init__.py プロジェクト: jsukrut-indic/frappe_v7
def create_folder(path, with_init=False):
	"""Create a folder in the given path and add an `__init__.py` file (optional).

	:param path: Folder path.
	:param with_init: Create `__init__.py` in the new folder."""
	from frappe.utils import touch_file
	if not os.path.exists(path):
		os.makedirs(path)

		if with_init:
			touch_file(os.path.join(path, "__init__.py"))
コード例 #5
0
ファイル: tasks.py プロジェクト: marchon/harware-frappe
def enqueue_scheduler_events():
	for site in get_sites():
		enqueue_lock = os.path.join(site, 'locks', 'enqueue.lock')
		try:
			if check_lock(enqueue_lock, timeout=1800):
				continue

			touch_file(enqueue_lock)

			enqueue_events_for_site.delay(site=site)

		except LockTimeoutError:
			os.remove(enqueue_lock)
コード例 #6
0
ファイル: file_lock.py プロジェクト: ESS-LLP/frappe
def create_lock(name):
	'''Creates a file in the /locks folder by the given name'''
	lock_path = get_lock_path(name)
	if not check_lock(lock_path):
		return touch_file(lock_path)
	else:
		return False
コード例 #7
0
ファイル: file_lock.py プロジェクト: Anju-P/moms-bench
def create_lock(name):
    '''Creates a file in the /locks folder by the given name'''
    lock_path = get_lock_path(name)
    if not check_lock(lock_path):
        return touch_file(lock_path)
    else:
        return False
コード例 #8
0
ファイル: site.py プロジェクト: nfattahi/frappe
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"""

    if not db_name:
        db_name = hashlib.sha1(site).hexdigest()[:16]

    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

    make_site_dirs()

    try:
        installing = touch_file(get_site_path('locks', 'installing.lock'))

        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)

        apps_to_install = ['frappe'] + (frappe.conf.get("install_apps")
                                        or []) + (list(install_apps) or [])
        for app in apps_to_install:
            _install_app(app, verbose=verbose, set_as_patched=not source_sql)

        frappe.utils.scheduler.toggle_scheduler(enable_scheduler)
        frappe.db.commit()

        scheduler_status = "disabled" if frappe.utils.scheduler.is_scheduler_disabled(
        ) else "enabled"
        print "*** Scheduler is", scheduler_status, "***"

    finally:
        if os.path.exists(installing):
            os.remove(installing)

        frappe.destroy()
コード例 #9
0
def make_boilerplate(dest):
	if not os.path.exists(dest):
		print "Destination directory does not exist"
		return

	hooks = frappe._dict()
	for key in ("App Name", "App Title", "App Description", "App Publisher",
		"App Icon", "App Color", "App Email", "App URL", "App License"):
		hook_key = key.lower().replace(" ", "_")
		hook_val = None
		while not hook_val:
			hook_val = raw_input(key + ": ")
			if hook_key=="app_name" and hook_val.lower().replace(" ", "_") != hook_val:
				print "App Name must be all lowercase and without spaces"
				hook_val = ""

		hooks[hook_key] = hook_val

	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)),
		with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"statics"))
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"pages"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"generators"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "config"), with_init=True)

	touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "__init__.py"))

	with open(os.path.join(dest, hooks.app_name, "MANIFEST.in"), "w") as f:
		f.write(manifest_template.format(**hooks))

	with open(os.path.join(dest, hooks.app_name, ".gitignore"), "w") as f:
		f.write(gitignore_template)

	with open(os.path.join(dest, hooks.app_name, "setup.py"), "w") as f:
		f.write(setup_template.format(**hooks))

	with open(os.path.join(dest, hooks.app_name, "requirements.txt"), "w") as f:
		f.write("frappe")

	touch_file(os.path.join(dest, hooks.app_name, "README.md"))

	with open(os.path.join(dest, hooks.app_name, "license.txt"), "w") as f:
		f.write("License: " + hooks.app_license)

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "modules.txt"), "w") as f:
		f.write(hooks.app_title)

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "hooks.py"), "w") as f:
		f.write(hooks_template.format(**hooks))

	touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "patches.txt"))

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "config", "desktop.py"), "w") as f:
		f.write(desktop_template.format(**hooks))
コード例 #10
0
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, source_db=False, reinstall=False,
			  db_user_allowed_host=None):
	"""Install a new Frappe site"""

	if not db_name:
		db_name = hashlib.sha1(site.encode()).hexdigest()[:16]

	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 Exception:
		enable_scheduler = False

	make_site_dirs()

	if source_db:
		source_sql = create_existing_db_backup(source_db, mariadb_root_password, mariadb_root_username)

	installing = None
	try:
		installing = touch_file(get_site_path('locks', 'installing.lock'))

		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, db_user_allowed_host=db_user_allowed_host)

		apps_to_install = ['frappe'] + (frappe.conf.get("install_apps") or []) + (list(install_apps) or [])
		for app in apps_to_install:
			_install_app(app, verbose=verbose, set_as_patched=not source_sql)

		frappe.utils.scheduler.toggle_scheduler(enable_scheduler)
		frappe.db.commit()

		scheduler_status = "disabled" if frappe.utils.scheduler.is_scheduler_disabled() else "enabled"
		print("*** Scheduler is", scheduler_status, "***")

	except frappe.exceptions.ImproperDBConfigurationError:
		_drop_site(site, mariadb_root_username, mariadb_root_password, force=True)

	finally:
		if installing and os.path.exists(installing):
			os.remove(installing)

		frappe.destroy()
コード例 #11
0
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,
			  no_mariadb_socket=False, reinstall=False,  db_password=None, db_type=None, db_host=None,
			  db_port=None, new_site=False):
	"""Install a new Frappe site"""

	if not force and os.path.exists(site):
		print('Site {0} already exists'.format(site))
		sys.exit(1)

	if no_mariadb_socket and not db_type == "mariadb":
		print('--no-mariadb-socket requires db_type to be set to mariadb.')
		sys.exit(1)

	if not db_name:
		db_name = '_' + hashlib.sha1(site.encode()).hexdigest()[:16]

	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 Exception:
		enable_scheduler = False

	make_site_dirs()

	installing = touch_file(get_site_path('locks', 'installing.lock'))

	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,
		db_password=db_password, db_type=db_type, db_host=db_host, db_port=db_port, no_mariadb_socket=no_mariadb_socket)
	apps_to_install = ['frappe'] + (frappe.conf.get("install_apps") or []) + (list(install_apps) or [])
	for app in apps_to_install:
		_install_app(app, verbose=verbose, set_as_patched=not source_sql)

	os.remove(installing)

	frappe.utils.scheduler.toggle_scheduler(enable_scheduler)
	frappe.db.commit()

	scheduler_status = "disabled" if frappe.utils.scheduler.is_scheduler_disabled() else "enabled"
	print("*** Scheduler is", scheduler_status, "***")
コード例 #12
0
ファイル: site.py プロジェクト: JiShangShiDai/frappe
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"""

	if not db_name:
		db_name = hashlib.sha1(site.encode()).hexdigest()[:16]

	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 Exception:
		enable_scheduler = False

	make_site_dirs()

	installing = None
	try:
		installing = touch_file(get_site_path('locks', 'installing.lock'))

		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)

		apps_to_install = ['frappe'] + (frappe.conf.get("install_apps") or []) + (list(install_apps) or [])
		for app in apps_to_install:
			_install_app(app, verbose=verbose, set_as_patched=not source_sql)

		frappe.utils.scheduler.toggle_scheduler(enable_scheduler)
		frappe.db.commit()

		scheduler_status = "disabled" if frappe.utils.scheduler.is_scheduler_disabled() else "enabled"
		print("*** Scheduler is", scheduler_status, "***")

	except frappe.exceptions.ImproperDBConfigurationError:
		_drop_site(site, mariadb_root_username, mariadb_root_password, force=True)

	finally:
		if installing and os.path.exists(installing):
			os.remove(installing)

		frappe.destroy()
コード例 #13
0
ファイル: site.py プロジェクト: Dattatech/frappetest
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

	make_site_dirs()

	try:
		installing = touch_file(get_site_path('locks', 'installing.lock'))

		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)

		apps_to_install = ['frappe'] + (frappe.conf.get("install_apps") or []) + (list(install_apps) or [])
		for app in apps_to_install:
			_install_app(app, verbose=verbose, set_as_patched=not source_sql)

		frappe.utils.scheduler.toggle_scheduler(enable_scheduler)
		frappe.db.commit()

		scheduler_status = "disabled" if frappe.utils.scheduler.is_scheduler_disabled() else "enabled"
		print "*** Scheduler is", scheduler_status, "***"

	finally:
		os.remove(installing)
		frappe.destroy()
コード例 #14
0
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,
    no_mariadb_socket=False,
    reinstall=False,
    db_password=None,
    db_type=None,
    db_host=None,
    db_port=None,
    new_site=False,
):
    """Install a new Frappe site"""

    from frappe.commands.scheduler import _is_scheduler_enabled
    from frappe.utils import get_site_path, scheduler, touch_file

    if not force and os.path.exists(site):
        print("Site {0} already exists".format(site))
        sys.exit(1)

    if no_mariadb_socket and not db_type == "mariadb":
        print("--no-mariadb-socket requires db_type to be set to mariadb.")
        sys.exit(1)

    frappe.init(site=site)

    if not db_name:
        import hashlib
        db_name = "_" + hashlib.sha1(
            os.path.realpath(frappe.get_site_path()).encode()).hexdigest()[:16]

    try:
        # enable scheduler post install?
        enable_scheduler = _is_scheduler_enabled()
    except Exception:
        enable_scheduler = False

    make_site_dirs()

    installing = touch_file(get_site_path("locks", "installing.lock"))

    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,
        db_password=db_password,
        db_type=db_type,
        db_host=db_host,
        db_port=db_port,
        no_mariadb_socket=no_mariadb_socket,
    )
    apps_to_install = (["frappe"] + (frappe.conf.get("install_apps") or []) +
                       (list(install_apps) or []))

    for app in apps_to_install:
        install_app(app, verbose=verbose, set_as_patched=not source_sql)

    os.remove(installing)

    scheduler.toggle_scheduler(enable_scheduler)
    frappe.db.commit()

    scheduler_status = ("disabled"
                        if frappe.utils.scheduler.is_scheduler_disabled() else
                        "enabled")
    print("*** Scheduler is", scheduler_status, "***")
コード例 #15
0
ファイル: boilerplate.py プロジェクト: omarhamdy49/frappe
def make_boilerplate(dest, app_name):
    if not os.path.exists(dest):
        print("Destination directory does not exist")
        return

    # app_name should be in snake_case
    app_name = frappe.scrub(app_name)

    hooks = frappe._dict()
    hooks.app_name = app_name
    app_title = hooks.app_name.replace("_", " ").title()
    for key in ("App Title (default: {0})".format(app_title),
                "App Description", "App Publisher", "App Email",
                "App Icon (default 'octicon octicon-file-directory')",
                "App Color (default 'grey')", "App License (default 'MIT')"):
        hook_key = key.split(" (")[0].lower().replace(" ", "_")
        hook_val = None
        while not hook_val:
            hook_val = cstr(input(key + ": "))

            if not hook_val:
                defaults = {
                    "app_title": app_title,
                    "app_icon": "octicon octicon-file-directory",
                    "app_color": "grey",
                    "app_license": "MIT"
                }
                if hook_key in defaults:
                    hook_val = defaults[hook_key]

            if hook_key == "app_name" and hook_val.lower().replace(
                    " ", "_") != hook_val:
                print("App Name must be all lowercase and without spaces")
                hook_val = ""
            elif hook_key == "app_title" and not re.match(
                    "^(?![\W])[^\d_\s][\w -]+$", hook_val, re.UNICODE):
                print(
                    "App Title should start with a letter and it can only consist of letters, numbers, spaces and underscores"
                )
                hook_val = ""

        hooks[hook_key] = hook_val

    frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name,
                                      frappe.scrub(hooks.app_title)),
                         with_init=True)
    frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name,
                                      "templates"),
                         with_init=True)
    frappe.create_folder(
        os.path.join(dest, hooks.app_name, hooks.app_name, "www"))
    frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name,
                                      "templates", "pages"),
                         with_init=True)
    frappe.create_folder(
        os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
                     "includes"))
    frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name,
                                      "config"),
                         with_init=True)
    frappe.create_folder(
        os.path.join(dest, hooks.app_name, hooks.app_name, "public", "css"))
    frappe.create_folder(
        os.path.join(dest, hooks.app_name, hooks.app_name, "public", "js"))

    with open(
            os.path.join(dest, hooks.app_name, hooks.app_name, "__init__.py"),
            "w") as f:
        f.write(frappe.as_unicode(init_template))

    with open(os.path.join(dest, hooks.app_name, "MANIFEST.in"), "w") as f:
        f.write(frappe.as_unicode(manifest_template.format(**hooks)))

    with open(os.path.join(dest, hooks.app_name, ".gitignore"), "w") as f:
        f.write(
            frappe.as_unicode(
                gitignore_template.format(app_name=hooks.app_name)))

    with open(os.path.join(dest, hooks.app_name, "setup.py"), "w") as f:
        f.write(frappe.as_unicode(setup_template.format(**hooks)))

    with open(os.path.join(dest, hooks.app_name, "requirements.txt"),
              "w") as f:
        f.write("frappe")

    with open(os.path.join(dest, hooks.app_name, "README.md"), "w") as f:
        f.write(
            frappe.as_unicode("## {0}\n\n{1}\n\n#### License\n\n{2}".format(
                hooks.app_title, hooks.app_description, hooks.app_license)))

    with open(os.path.join(dest, hooks.app_name, "license.txt"), "w") as f:
        f.write(frappe.as_unicode("License: " + hooks.app_license))

    with open(
            os.path.join(dest, hooks.app_name, hooks.app_name, "modules.txt"),
            "w") as f:
        f.write(frappe.as_unicode(hooks.app_title))

    with open(os.path.join(dest, hooks.app_name, hooks.app_name, "hooks.py"),
              "w") as f:
        f.write(frappe.as_unicode(hooks_template.format(**hooks)))

    touch_file(
        os.path.join(dest, hooks.app_name, hooks.app_name, "patches.txt"))

    with open(
            os.path.join(dest, hooks.app_name, hooks.app_name, "config",
                         "desktop.py"), "w") as f:
        f.write(frappe.as_unicode(desktop_template.format(**hooks)))

    with open(
            os.path.join(dest, hooks.app_name, hooks.app_name, "config",
                         "docs.py"), "w") as f:
        f.write(frappe.as_unicode(docs_template.format(**hooks)))

    print("'{app}' created at {path}".format(app=app_name,
                                             path=os.path.join(dest,
                                                               app_name)))
コード例 #16
0
def create_lock(name):
	lock_path = get_lock_path(name)
	if not check_lock(lock_path):
		return touch_file(lock_path)
	else:
		return False
コード例 #17
0
def make_boilerplate(dest, app_name):
	if not os.path.exists(dest):
		print "Destination directory does not exist"
		return

	hooks = frappe._dict()
	hooks.app_name = app_name
	app_title = hooks.app_name.replace("_", " ").title()
	for key in ("App Title (defaut: {0})".format(app_title),
		"App Description", "App Publisher", "App Email",
		"App Icon (default 'octicon octicon-file-directory')",
		"App Color (default 'grey')",
		"App License (default 'MIT')"):
		hook_key = key.split(" (")[0].lower().replace(" ", "_")
		hook_val = None
		while not hook_val:
			hook_val = raw_input(key + ": ")
			if hook_key=="app_name" and hook_val.lower().replace(" ", "_") != hook_val:
				print "App Name must be all lowercase and without spaces"
				hook_val = ""
			elif not hook_val:
				defaults = {
					"app_title": app_title,
					"app_icon": "octicon octicon-file-directory",
					"app_color": "grey",
					"app_license": "MIT"
				}
				if hook_key in defaults:
					hook_val = defaults[hook_key]

		hooks[hook_key] = hook_val

	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)),
		with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "www"))
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"pages"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"generators"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"includes"))
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "config"), with_init=True)

	touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "__init__.py"))

	with open(os.path.join(dest, hooks.app_name, "MANIFEST.in"), "w") as f:
		f.write(manifest_template.format(**hooks))

	with open(os.path.join(dest, hooks.app_name, ".gitignore"), "w") as f:
		f.write(gitignore_template)

	with open(os.path.join(dest, hooks.app_name, "setup.py"), "w") as f:
		f.write(setup_template.format(**hooks))

	with open(os.path.join(dest, hooks.app_name, "requirements.txt"), "w") as f:
		f.write("frappe")

	with open(os.path.join(dest, hooks.app_name, "README.md"), "w") as f:
		f.write("## {0}\n\n{1}\n\n#### License\n\n{2}".format(hooks.app_title,
			hooks.app_description, hooks.app_license))

	with open(os.path.join(dest, hooks.app_name, "license.txt"), "w") as f:
		f.write("License: " + hooks.app_license)

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "modules.txt"), "w") as f:
		f.write(hooks.app_title)

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "hooks.py"), "w") as f:
		f.write(hooks_template.format(**hooks))

	touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "patches.txt"))

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "config", "desktop.py"), "w") as f:
		f.write(desktop_template.format(**hooks))
コード例 #18
0
ファイル: file_lock.py プロジェクト: AhmedHamedTN/frappe
def create_lock(name):
	lock_path = get_lock_path(name)
	if not check_lock(lock_path):
		return touch_file(lock_path)
	else:
		return False
コード例 #19
0
def make_boilerplate(dest, app_name):
	if not os.path.exists(dest):
		print "Destination directory does not exist"
		return

	hooks = frappe._dict()
	hooks.app_name = app_name
	app_title = hooks.app_name.replace("_", " ").title()
	for key in ("App Title (defaut: {0})".format(app_title),
		"App Description", "App Publisher", "App Email",
		"App Icon (default 'octicon octicon-file-directory')",
		"App Color (default 'grey')",
		"App License (default 'MIT')"):
		hook_key = key.split(" (")[0].lower().replace(" ", "_")
		hook_val = None
		while not hook_val:
			hook_val = cstr(raw_input(key + ": "))
			if hook_key=="app_name" and hook_val.lower().replace(" ", "_") != hook_val:
				print "App Name must be all lowercase and without spaces"
				hook_val = ""
			elif not hook_val:
				defaults = {
					"app_title": app_title,
					"app_icon": "octicon octicon-file-directory",
					"app_color": "grey",
					"app_license": "MIT"
				}
				if hook_key in defaults:
					hook_val = defaults[hook_key]

		hooks[hook_key] = hook_val

	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)),
		with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "www"))
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"pages"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"generators"), with_init=True)
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
		"includes"))
	frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "config"), with_init=True)

	touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "__init__.py"))

	with open(os.path.join(dest, hooks.app_name, "MANIFEST.in"), "w") as f:
		f.write(encode(manifest_template.format(**hooks)))

	with open(os.path.join(dest, hooks.app_name, ".gitignore"), "w") as f:
		f.write(encode(gitignore_template))

	with open(os.path.join(dest, hooks.app_name, "setup.py"), "w") as f:
		f.write(encode(setup_template.format(**hooks)))

	with open(os.path.join(dest, hooks.app_name, "requirements.txt"), "w") as f:
		f.write("frappe")

	with open(os.path.join(dest, hooks.app_name, "README.md"), "w") as f:
		f.write(encode("## {0}\n\n{1}\n\n#### License\n\n{2}".format(hooks.app_title,
			hooks.app_description, hooks.app_license)))

	with open(os.path.join(dest, hooks.app_name, "license.txt"), "w") as f:
		f.write(encode("License: " + hooks.app_license))

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "modules.txt"), "w") as f:
		f.write(encode(hooks.app_title))

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "hooks.py"), "w") as f:
		f.write(encode(hooks_template.format(**hooks)))

	touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "patches.txt"))

	with open(os.path.join(dest, hooks.app_name, hooks.app_name, "config", "desktop.py"), "w") as f:
		f.write(encode(desktop_template.format(**hooks)))

	print "'{app}' created at {path}".format(app=app_name, path=os.path.join(dest, app_name))