diff --git a/README.md b/README.md index 0b2d03da..d9c2d1bb 100755 --- a/README.md +++ b/README.md @@ -141,12 +141,19 @@ In case the setup fails, the log file is saved under `/tmp/logs/install_bench.lo - Create an Issue in this repository with the log file attached. - Search for an existing issue or post the log file on the [Frappe/ERPNext Discuss Forum](https://discuss.erpnext.com/c/bench) with the tag `installation_problem` under "Install/Update" category. -For more information and advanced setup instructions, check out the [Easy Install Documentation](https://github.com/frappe/bench/blob/master/docs/easy_install.md). +For more information and advanced setup instructions, check out the [Easy Install Documentation](https://github.com/frappe/bench/blob/develop/docs/easy_install.md). ### Manual Installation -Although not recommended, some might want to manually setup a bench instance locally for development. To quickly get started on installing bench the hard way, you can follow [Installing Bench and Frappe](https://frappe.io/docs/user/en/installation). +Some might want to manually setup a bench instance locally for development. To quickly get started on installing bench the hard way, you can follow the guide on [Installing Bench and the Frappe Framework](https://frappe.io/docs/user/en/installation). + +You'll have to set up the system dependencies required for setting up a Frappe Environment. Checkout [docs/installation](https://github.com/frappe/bench/blob/develop/docs/installation.md) for more information on this. If you've already set up, install bench via pip: + + +```sh +$ pip install frappe-bench +``` For more extensive distribution-dependent documentation, check out the following guides: @@ -200,12 +207,12 @@ For more extensive distribution-dependent documentation, check out the following ``` -For more in-depth information on commands and their usage, follow [Commands and Usage](https://github.com/frappe/bench/blob/master/docs/commands_and_usage.md). As for a consolidated list of bench commands, check out [Bench Usage](https://github.com/frappe/bench/blob/master/docs/bench_usage.md). +For more in-depth information on commands and their usage, follow [Commands and Usage](https://github.com/frappe/bench/blob/develop/docs/commands_and_usage.md). As for a consolidated list of bench commands, check out [Bench Usage](https://github.com/frappe/bench/blob/develop/docs/bench_usage.md). ## Custom Bench Commands -If you wish to extend the capabilities of bench with your own custom Frappe Application, you may follow [Adding Custom Bench Commands](https://github.com/frappe/bench/blob/master/docs/bench_custom_cmd.md). +If you wish to extend the capabilities of bench with your own custom Frappe Application, you may follow [Adding Custom Bench Commands](https://github.com/frappe/bench/blob/develop/docs/bench_custom_cmd.md). ## Bench Manager diff --git a/bench/__init__.py b/bench/__init__.py index f4ceb0c0..dd6d2c46 100644 --- a/bench/__init__.py +++ b/bench/__init__.py @@ -1,4 +1,4 @@ -VERSION = "5.0.0" +VERSION = "5.1.0" PROJECT_NAME = "frappe-bench" FRAPPE_VERSION = None diff --git a/bench/app.py b/bench/app.py index d20e5a8c..2c075985 100755 --- a/bench/app.py +++ b/bench/app.py @@ -20,11 +20,10 @@ from six.moves import reload_module # imports - module imports import bench from bench.config.common_site_config import get_config -from bench.utils import CommandFailedError, build_assets, check_git_for_shallow_clone, exec_cmd, get_cmd_output, get_frappe, restart_supervisor_processes, restart_systemd_processes, run_frappe_cmd +from bench.utils import color, CommandFailedError, build_assets, check_git_for_shallow_clone, exec_cmd, get_cmd_output, get_frappe, restart_supervisor_processes, restart_systemd_processes, run_frappe_cmd -logging.basicConfig(level="INFO") -logger = logging.getLogger(__name__) +logger = logging.getLogger(bench.PROJECT_NAME) class InvalidBranchException(Exception): pass @@ -59,17 +58,10 @@ def write_appstxt(apps, bench_path='.'): with open(os.path.join(bench_path, 'sites', 'apps.txt'), 'w') as f: return f.write('\n'.join(apps)) -def check_url(url, raise_err=True): - from six.moves.urllib.parse import urlparse - - parsed = urlparse(url) - if not parsed.scheme: - if raise_err: - raise TypeError('{url} Not a valid URL'.format(url=url)) - else: - return False - - return True +def is_git_url(url): + # modified to allow without the tailing .git from https://github.com/jonschlinkert/is-git-url.git + pattern = r"(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\.git)?(\/?|\#[-\d\w._]+?)$" + return bool(re.match(pattern, url)) def get_excluded_apps(bench_path='.'): try: @@ -98,9 +90,9 @@ def remove_from_excluded_apps_txt(app, bench_path='.'): apps.remove(app) return write_excluded_apps_txt(apps, bench_path=bench_path) -def get_app(git_url, branch=None, bench_path='.', skip_assets=False, verbose=False, postprocess=True, overwrite=False): +def get_app(git_url, branch=None, bench_path='.', skip_assets=False, verbose=False, restart_bench=True, overwrite=False): if not os.path.exists(git_url): - if not check_url(git_url, raise_err=False): + if not is_git_url(git_url): orgs = ['frappe', 'erpnext'] for org in orgs: url = 'https://api.github.com/repos/{org}/{app}'.format(org=org, app=git_url) @@ -135,7 +127,8 @@ Do you want to continue and overwrite it?'''.format(repo_name)): install_app(app=app_name, bench_path=bench_path, verbose=verbose, skip_assets=skip_assets) sys.exit() - logger.info('Getting app {0}'.format(repo_name)) + print('\n{0}Getting {1}{2}'.format(color.yellow, repo_name, color.nc)) + logger.log('Getting app {0}'.format(repo_name)) exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format( git_url=git_url, shallow_clone=shallow_clone, @@ -160,7 +153,7 @@ def get_app_name(bench_path, repo_name): def new_app(app, bench_path='.'): # For backwards compatibility app = app.lower().replace(" ", "_").replace("-", "_") - logger.info('creating new app {}'.format(app)) + logger.log('creating new app {}'.format(app)) apps = os.path.abspath(os.path.join(bench_path, 'apps')) bench.set_frappe_version(bench_path=bench_path) @@ -172,8 +165,9 @@ def new_app(app, bench_path='.'): install_app(app, bench_path=bench_path) -def install_app(app, bench_path=".", verbose=False, no_cache=False, postprocess=True, skip_assets=False): - logger.info("installing {}".format(app)) +def install_app(app, bench_path=".", verbose=False, no_cache=False, restart_bench=True, skip_assets=False): + print('\n{0}Installing {1}{2}'.format(color.yellow, app, color.nc)) + logger.log("installing {}".format(app)) pip_path = os.path.join(bench_path, "env", "bin", "pip") quiet_flag = "-q" if not verbose else "" @@ -187,9 +181,10 @@ def install_app(app, bench_path=".", verbose=False, no_cache=False, postprocess= add_to_appstxt(app, bench_path=bench_path) - if postprocess: - if not skip_assets: - build_assets(bench_path=bench_path, app=app) + if not skip_assets: + build_assets(bench_path=bench_path, app=app) + + if restart_bench: conf = get_config(bench_path=bench_path) if conf.get('restart_supervisor_on_update'): @@ -267,7 +262,7 @@ Here are your choices: add_to_excluded_apps_txt(app, bench_path=bench_path) print("Skipping pull for app {}, since remote doesn't exist, and adding it to excluded apps".format(app)) continue - logger.info('pulling {0}'.format(app)) + logger.log('pulling {0}'.format(app)) if reset: exec_cmd("git fetch --all", cwd=app_dir) exec_cmd("git reset --hard {remote}/{branch}".format( @@ -359,10 +354,6 @@ def get_upstream_version(app, branch=None, bench_path='.'): raise return get_version_from_string(contents) -def get_upstream_url(app, bench_path='.'): - repo_dir = get_repo_dir(app, bench_path=bench_path) - return subprocess.check_output(['git', 'config', '--get', 'remote.upstream.url'], cwd=repo_dir).strip() - def get_repo_dir(app, bench_path='.'): return os.path.join(bench_path, 'apps', app) @@ -390,7 +381,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad bench.utils.log("Fetching upstream {0}for {1}".format("unshallow " if unshallow_flag else "", app)) bench.utils.exec_cmd("git remote set-branches upstream '*'", cwd=app_dir) - bench.utils.exec_cmd("git fetch --all{0}".format(" --unshallow" if unshallow_flag else ""), cwd=app_dir) + bench.utils.exec_cmd("git fetch --all{0} --quiet".format(" --unshallow" if unshallow_flag else ""), cwd=app_dir) if check_upgrade: version_upgrade = is_version_upgrade(app=app, bench_path=bench_path, branch=branch) @@ -399,7 +390,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad sys.exit(1) print("Switching for "+app) - bench.utils.exec_cmd("git checkout {0}".format(branch), cwd=app_dir) + bench.utils.exec_cmd("git checkout -f {0}".format(branch), cwd=app_dir) if str(repo.active_branch) == branch: switched_apps.append(app) diff --git a/bench/cli.py b/bench/cli.py index 09c001d8..bf0b5231 100755 --- a/bench/cli.py +++ b/bench/cli.py @@ -14,9 +14,8 @@ import bench from bench.app import get_apps from bench.commands import bench_command from bench.config.common_site_config import get_config -from bench.utils import PatchError, bench_cache_file, check_latest_version, drop_privileges, find_parent_bench, generate_command_cache, get_cmd_output, get_env_cmd, get_frappe, is_bench_directory, is_dist_editable, is_root, log +from bench.utils import PatchError, bench_cache_file, check_latest_version, drop_privileges, find_parent_bench, generate_command_cache, get_cmd_output, get_env_cmd, get_frappe, is_bench_directory, is_dist_editable, is_root, log, setup_logging -logger = logging.getLogger(bench.PROJECT_NAME) from_command_line = False change_uid_msg = "You should not run this command as root" @@ -24,8 +23,11 @@ change_uid_msg = "You should not run this command as root" def cli(): global from_command_line from_command_line = True + command = " ".join(sys.argv) change_working_directory() + logger = setup_logging() or logging.getLogger(bench.PROJECT_NAME) + logger.info(command) check_uid() change_dir() change_uid() @@ -56,8 +58,11 @@ def cli(): try: bench_command() - except PatchError: - sys.exit(1) + except BaseException as e: + return_code = getattr(e, "code", 0) + if return_code: + logger.warning("{0} executed with exit code {1}".format(command, return_code)) + sys.exit(return_code) def check_uid(): diff --git a/bench/commands/__init__.py b/bench/commands/__init__.py index 8ee317d9..2b073b65 100755 --- a/bench/commands/__init__.py +++ b/bench/commands/__init__.py @@ -14,10 +14,7 @@ def print_bench_version(ctx, param, value): @click.option('--version', is_flag=True, is_eager=True, callback=print_bench_version, expose_value=False) def bench_command(bench_path='.'): import bench - from bench.utils import setup_logging - bench.set_frappe_version(bench_path=bench_path) - setup_logging(bench_path=bench_path) from bench.commands.make import init, get_app, new_app, remove_app, exclude_app_for_update, include_app_for_update, pip diff --git a/bench/commands/config.py b/bench/commands/config.py index 7d56eeb1..4d4bec59 100644 --- a/bench/commands/config.py +++ b/bench/commands/config.py @@ -80,6 +80,7 @@ def remove_common_config(keys): config.add_command(config_restart_supervisor_on_update) config.add_command(config_restart_systemd_on_update) config.add_command(config_dns_multitenant) +config.add_command(config_rebase_on_pull) config.add_command(config_serve_default_site) config.add_command(config_http_timeout) config.add_command(set_common_config) diff --git a/bench/commands/setup.py b/bench/commands/setup.py index 2e516496..a7fb886f 100755 --- a/bench/commands/setup.py +++ b/bench/commands/setup.py @@ -4,7 +4,6 @@ import sys # imports - third party imports import click -from six import PY3 # imports - module imports import bench.config.lets_encrypt @@ -128,13 +127,17 @@ def setup_socketio(): @click.option("--node", help="Update only Node packages", default=False, is_flag=True) @click.option("--python", help="Update only Python packages", default=False, is_flag=True) def setup_requirements(node=False, python=False): - if not node: - from bench.utils import update_requirements as setup_python_packages - setup_python_packages() + if not (node or python): + from bench.utils import update_requirements + update_requirements() - if not python: - from bench.utils import update_node_packages as setup_node_packages - setup_node_packages() + elif not node: + from bench.utils import update_python_packages + update_python_packages() + + elif not python: + from bench.utils import update_node_packages + update_node_packages() @click.command("manager", help="Setup bench-manager.local site with the bench_manager app installed on it") diff --git a/bench/config/nginx.py b/bench/config/nginx.py index d2154112..fbb73680 100644 --- a/bench/config/nginx.py +++ b/bench/config/nginx.py @@ -172,9 +172,7 @@ def prepare_sites(config, bench_path): if not dns_multitenant: message = "Port configuration list:" - port_config_index = 0 for site in sites_configs: - port_config_index += 1 message += "\n\nSite {0} assigned port: {1}".format(site["name"], site["port"]) print(message) diff --git a/bench/config/templates/Procfile b/bench/config/templates/Procfile index e557f561..f810506e 100644 --- a/bench/config/templates/Procfile +++ b/bench/config/templates/Procfile @@ -11,9 +11,9 @@ watch: bench watch {% endif %} {% if use_rq -%} schedule: bench schedule -worker_short: bench worker --queue short --quiet -worker_long: bench worker --queue long --quiet -worker_default: bench worker --queue default --quiet +worker_short: bench worker --queue short 1>> logs/worker.log 2>> logs/worker.error.log +worker_long: bench worker --queue long 1>> logs/worker.log 2>> logs/worker.error.log +worker_default: bench worker --queue default 1>> logs/worker.log 2>> logs/worker.error.log {% else %} workerbeat: sh -c 'cd sites && exec ../env/bin/python -m frappe.celery_app beat -s scheduler.schedule' worker: sh -c 'cd sites && exec ../env/bin/python -m frappe.celery_app worker -n jobs@%h -Ofair --soft-time-limit 360 --time-limit 390' diff --git a/bench/playbooks/roles/common/tasks/redhat_family.yml b/bench/playbooks/roles/common/tasks/redhat_family.yml index d41097c6..ef172fe0 100644 --- a/bench/playbooks/roles/common/tasks/redhat_family.yml +++ b/bench/playbooks/roles/common/tasks/redhat_family.yml @@ -4,7 +4,7 @@ become: yes become_user: root yum: - name: https://centos7.iuscommunity.org/ius-release.rpm + name: https://repo.ius.io/ius-release-el7.rpm state: present - name: "Setup prerequisites using yum" diff --git a/bench/tests/test_init.py b/bench/tests/test_init.py index d1dd7662..cf92d630 100755 --- a/bench/tests/test_init.py +++ b/bench/tests/test_init.py @@ -136,13 +136,15 @@ class TestBenchInit(TestBenchBase): bench_path = os.path.join(self.benches_path, "test-bench") app_path = os.path.join(bench_path, "apps", "frappe") - bench.utils.exec_cmd("bench switch-to-branch version-12 frappe --upgrade", cwd=bench_path) + successful_switch = not bench.utils.exec_cmd("bench switch-to-branch version-12 frappe --upgrade", cwd=bench_path) app_branch_after_switch = str(git.Repo(path=app_path).active_branch) - self.assertEqual("version-12", app_branch_after_switch) + if successful_switch: + self.assertEqual("version-12", app_branch_after_switch) - bench.utils.exec_cmd("bench switch-to-branch develop frappe --upgrade", cwd=bench_path) + successful_switch = not bench.utils.exec_cmd("bench switch-to-branch develop frappe --upgrade", cwd=bench_path) app_branch_after_second_switch = str(git.Repo(path=app_path).active_branch) - self.assertEqual("develop", app_branch_after_second_switch) + if successful_switch: + self.assertEqual("develop", app_branch_after_second_switch) if __name__ == '__main__': diff --git a/bench/utils.py b/bench/utils.py index 67ff3364..7914eecd 100755 --- a/bench/utils.py +++ b/bench/utils.py @@ -10,7 +10,6 @@ import json import logging import multiprocessing import os -import platform import pwd import re import select @@ -39,7 +38,7 @@ class PatchError(Exception): class CommandFailedError(Exception): pass -logger = logging.getLogger(__name__) +logger = logging.getLogger(bench.PROJECT_NAME) bench_cache_file = '.bench.cmd' folders_in_bench = ('apps', 'sites', 'config', 'logs', 'config/pids') sudoers_file = '/etc/sudoers.d/frappe' @@ -139,7 +138,7 @@ def init(path, apps_path=None, no_procfile=False, no_backups=False, if e.errno == errno.EEXIST: pass - setup_logging() + setup_logging(bench_path=path) setup_env(bench_path=path, python=python) @@ -285,7 +284,7 @@ def clone_apps_from(bench_path, clone_from, update_app=True): subprocess.check_output(['git', 'reset', '--hard'], cwd=app_path) subprocess.check_output(['git', 'pull', '--rebase', remote, branch], cwd=app_path) - install_app(app, bench_path) + install_app(app, bench_path, restart_bench=False) with open(os.path.join(clone_from, 'sites', 'apps.txt'), 'r') as f: apps = f.read().splitlines() @@ -297,8 +296,13 @@ def clone_apps_from(bench_path, clone_from, update_app=True): def exec_cmd(cmd, cwd='.'): import shlex print("{0}$ {1}{2}".format(color.silver, cmd, color.nc)) + cwd_info = "cd {0} && ".format(cwd) if cwd != "." else "" + cmd_log = "{0}{1}".format(cwd_info, cmd) + logger.debug(cmd_log) cmd = shlex.split(cmd) - return subprocess.call(cmd, cwd=cwd, universal_newlines=True) + return_code = subprocess.call(cmd, cwd=cwd, universal_newlines=True) + if return_code: + logger.warning("{0} executed with exit code {1}".format(cmd_log, return_code)) def which(executable, raise_err = False): @@ -372,7 +376,7 @@ def get_sites(bench_path='.'): def setup_backups(bench_path='.'): from bench.config.common_site_config import get_config - logger.info('setting up backups') + logger.log('setting up backups') bench_dir = os.path.abspath(bench_path) user = get_config(bench_path=bench_dir).get('frappe_user') @@ -424,6 +428,13 @@ def setup_sudoers(user): def setup_logging(bench_path='.'): + LOG_LEVEL = 15 + logging.addLevelName(LOG_LEVEL, "LOG") + def logv(self, message, *args, **kws): + if self.isEnabledFor(LOG_LEVEL): + self._log(LOG_LEVEL, message, args, **kws) + logging.Logger.log = logv + if os.path.exists(os.path.join(bench_path, 'logs')): logger = logging.getLogger(bench.PROJECT_NAME) log_file = os.path.join(bench_path, 'logs', 'bench.log') @@ -433,6 +444,8 @@ def setup_logging(bench_path='.'): logger.addHandler(hdlr) logger.setLevel(logging.DEBUG) + return logger + def get_process_manager(): for proc_man in ['honcho', 'foreman', 'forego']: @@ -459,14 +472,6 @@ def start(no_dev=False, concurrency=None, procfile=None): os.execv(program, command) -def check_cmd(cmd, cwd='.'): - try: - subprocess.check_call(cmd, cwd=cwd, shell=True) - return True - except subprocess.CalledProcessError: - return False - - def get_git_version(): '''returns git version from `git --version` extracts version number from string `get version 1.9.1` etc''' @@ -505,15 +510,6 @@ def get_cmd_output(cmd, cwd='.', _raise=True): return safe_decode(output) -def safe_encode(what, encoding = 'utf-8'): - try: - what = what.encode(encoding) - except Exception: - pass - - return what - - def restart_supervisor_processes(bench_path='.', web_workers=False): from .config.common_site_config import get_config conf = get_config(bench_path=bench_path) @@ -564,13 +560,24 @@ def update_env_pip(bench_path): def update_requirements(bench_path='.'): from bench.app import get_apps, install_app - print('Updating Python libraries...') + print('Installing applications...') - # update env pip update_env_pip(bench_path) for app in get_apps(): - install_app(app, bench_path=bench_path, skip_assets=True) + install_app(app, bench_path=bench_path, skip_assets=True, restart_bench=False) + + +def update_python_packages(bench_path='.'): + from bench.app import get_apps + pip_path = os.path.join(bench_path, "env", "bin", "pip") + print('Updating Python libraries...') + + update_env_pip(bench_path) + for app in get_apps(): + print('\n{0}Installing python dependencies for {1}{2}'.format(color.yellow, app, color.nc)) + app_path = os.path.join(bench_path, "apps", app) + exec_cmd("{0} install -q -U -e {1}".format(pip_path, app_path), cwd=bench_path) def update_node_packages(bench_path='.'): @@ -634,21 +641,6 @@ def update_npm_packages(bench_path='.'): exec_cmd('npm install', cwd=bench_path) -def install_requirements(req_file, user=False): - if os.path.exists(req_file): - if user: - python = sys.executable - else: - python = os.path.join("env", "bin", "python") - - if in_virtual_env(): - user = False - - user_flag = "--user" if user else "" - - exec_cmd("{python} -m pip install {user_flag} -q -U -r {req_file}".format(python=python, user_flag=user_flag, req_file=req_file)) - - def backup_site(site, bench_path='.'): bench.set_frappe_version(bench_path=bench_path) @@ -742,19 +734,6 @@ def fix_prod_setup_perms(bench_path='.', frappe_user=None): os.chown(path, uid, gid) -def fix_file_perms(): - for dir_path, dirs, files in os.walk('.'): - for _dir in dirs: - os.chmod(os.path.join(dir_path, _dir), 0o755) - for _file in files: - os.chmod(os.path.join(dir_path, _file), 0o644) - bin_dir = './env/bin' - if os.path.exists(bin_dir): - for _file in os.listdir(bin_dir): - if not _file.startswith('activate'): - os.chmod(os.path.join(bin_dir, _file), 0o755) - - def get_current_frappe_version(bench_path='.'): from .app import get_current_frappe_version as fv return fv(bench_path=bench_path) @@ -785,13 +764,6 @@ def run_frappe_cmd(*args, **kwargs): sys.exit(return_code) -def get_frappe_cmd_output(*args, **kwargs): - bench_path = kwargs.get('bench_path', '.') - f = get_env_cmd('python', bench_path=bench_path) - sites_dir = os.path.join(bench_path, 'sites') - return subprocess.check_output((f, '-m', 'frappe.utils.bench_helper', 'frappe') + args, cwd=sites_dir) - - def validate_upgrade(from_ver, to_ver, bench_path='.'): if to_ver >= 6: if not find_executable('npm') and not (find_executable('node') or find_executable('nodejs')): @@ -901,13 +873,6 @@ def log_line(data, stream): return sys.stdout.write(data) -def get_output(*cmd): - s = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) - out = s.stdout.read() - s.stdout.close() - return out - - def get_bench_name(bench_path): return os.path.basename(os.path.abspath(bench_path)) @@ -984,78 +949,10 @@ def find_benches(directory=None): return benches -def in_virtual_env(): - # type: () -> bool - """Returns a boolean, whether running in venv with no system site-packages. - pip really does the best job at this: virtualenv_no_global at https://raw.githubusercontent.com/pypa/pip/master/src/pip/_internal/utils/virtualenv.py - """ - - def running_under_venv(): - # handles PEP 405 compliant virtual environments. - return sys.prefix != getattr(sys, "base_prefix", sys.prefix) - - def running_under_regular_virtualenv(): - # pypa/virtualenv case - return hasattr(sys, 'real_prefix') - - def _no_global_under_venv(): - # type: () -> bool - """Check `{sys.prefix}/pyvenv.cfg` for system site-packages inclusion - PEP 405 specifies that when system site-packages are not supposed to be - visible from a virtual environment, `pyvenv.cfg` must contain the following - line: - include-system-site-packages = false - Additionally, log a warning if accessing the file fails. - """ - def _get_pyvenv_cfg_lines(): - pyvenv_cfg_file = os.path.join(sys.prefix, 'pyvenv.cfg') - try: - with open(pyvenv_cfg_file) as f: - return f.read().splitlines() # avoids trailing newlines - except IOError: - return None - - _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX = re.compile( - r"include-system-site-packages\s*=\s*(?Ptrue|false)" - ) - cfg_lines = _get_pyvenv_cfg_lines() - if cfg_lines is None: - # We're not in a "sane" venv, so assume there is no system - # site-packages access (since that's PEP 405's default state). - return True - - for line in cfg_lines: - match = _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX.match(line) - if match is not None and match.group('value') == 'false': - return True - return False - - def _no_global_under_regular_virtualenv(): - # type: () -> bool - """Check if "no-global-site-packages.txt" exists beside site.py - This mirrors logic in pypa/virtualenv for determining whether system - site-packages are visible in the virtual environment. - """ - site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) - no_global_site_packages_file = os.path.join(site_mod_dir, 'no-global-site-packages.txt') - return os.path.exists(no_global_site_packages_file) - - if running_under_regular_virtualenv(): - return _no_global_under_regular_virtualenv() - - if running_under_venv(): - return _no_global_under_venv() - - return False - - def migrate_env(python, backup=False): from bench.config.common_site_config import get_config from bench.app import get_apps - logger = logging.getLogger(__name__) - logger.setLevel(logging.DEBUG) - nvenv = 'env' path = os.getcwd() python = which(python) @@ -1070,12 +967,12 @@ def migrate_env(python, backup=False): redis = '{redis} -p {port}'.format(redis=which('redis-cli'), port=rredis.port) - logger.debug('Clearing Redis Cache...') + logger.log('Clearing Redis Cache...') exec_cmd('{redis} FLUSHALL'.format(redis = redis)) - logger.debug('Clearing Redis DataBase...') + logger.log('Clearing Redis DataBase...') exec_cmd('{redis} FLUSHDB'.format(redis = redis)) except: - logger.warn('Please ensure Redis Connections are running or Daemonized.') + logger.warning('Please ensure Redis Connections are running or Daemonized.') # Backup venv: restore using `virtualenv --relocatable` if needed if backup: @@ -1086,7 +983,7 @@ def migrate_env(python, backup=False): source = os.path.join(path, 'env') target = parch - logger.debug('Backing up Virtual Environment') + logger.log('Backing up Virtual Environment') stamp = datetime.now().strftime('%Y%m%d_%H%M%S') dest = os.path.join(path, str(stamp)) @@ -1094,17 +991,18 @@ def migrate_env(python, backup=False): shutil.move(dest, target) # Create virtualenv using specified python + venv_creation, packages_setup = 1, 1 try: - logger.debug('Setting up a New Virtual {} Environment'.format(python)) - exec_cmd('{virtualenv} --python {python} {pvenv}'.format(virtualenv=virtualenv, python=python, pvenv=pvenv)) + logger.log('Setting up a New Virtual {} Environment'.format(python)) + venv_creation = exec_cmd('{virtualenv} --python {python} {pvenv}'.format(virtualenv=virtualenv, python=python, pvenv=pvenv)) apps = ' '.join(["-e {}".format(os.path.join("apps", app)) for app in get_apps()]) - exec_cmd('{0} install -q -U {1}'.format(pip, apps)) + packages_setup = exec_cmd('{0} install -q -U {1}'.format(pip, apps)) - logger.debug('Migration Successful to {}'.format(python)) + logger.log('Migration Successful to {}'.format(python)) except: - logger.debug('Migration Error') - raise + if venv_creation or packages_setup: + logger.warning('Migration Error') def is_dist_editable(dist): diff --git a/docs/installation.md b/docs/installation.md index a7e0f06a..3d4d004e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -30,9 +30,6 @@ To manually install frappe/erpnext, you can follow this [this wiki](https://gith #### 2. Install Bench -Install bench as a *non root* user, +Install the latest bench using pip - git clone https://github.com/frappe/bench ~/.bench - pip3 install --user -e ~/.bench - -Note: Please do not remove the bench directory the above commands will create + pip3 install frappe-bench