2
0
mirror of https://github.com/frappe/bench.git synced 2024-11-18 11:05:12 +00:00

Merge branch 'develop' into fix-delete

This commit is contained in:
gavin 2020-06-10 14:46:29 +05:30 committed by GitHub
commit 70cb41fa0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 109 additions and 210 deletions

View File

@ -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. - 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. - 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 ### 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: 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 ## 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 ## Bench Manager

View File

@ -1,4 +1,4 @@
VERSION = "5.0.0" VERSION = "5.1.0"
PROJECT_NAME = "frappe-bench" PROJECT_NAME = "frappe-bench"
FRAPPE_VERSION = None FRAPPE_VERSION = None

View File

@ -20,11 +20,10 @@ from six.moves import reload_module
# imports - module imports # imports - module imports
import bench import bench
from bench.config.common_site_config import get_config 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(bench.PROJECT_NAME)
logger = logging.getLogger(__name__)
class InvalidBranchException(Exception): pass 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: with open(os.path.join(bench_path, 'sites', 'apps.txt'), 'w') as f:
return f.write('\n'.join(apps)) return f.write('\n'.join(apps))
def check_url(url, raise_err=True): def is_git_url(url):
from six.moves.urllib.parse import urlparse # 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._]+?)$"
parsed = urlparse(url) return bool(re.match(pattern, url))
if not parsed.scheme:
if raise_err:
raise TypeError('{url} Not a valid URL'.format(url=url))
else:
return False
return True
def get_excluded_apps(bench_path='.'): def get_excluded_apps(bench_path='.'):
try: try:
@ -98,9 +90,9 @@ def remove_from_excluded_apps_txt(app, bench_path='.'):
apps.remove(app) apps.remove(app)
return write_excluded_apps_txt(apps, bench_path=bench_path) 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 os.path.exists(git_url):
if not check_url(git_url, raise_err=False): if not is_git_url(git_url):
orgs = ['frappe', 'erpnext'] orgs = ['frappe', 'erpnext']
for org in orgs: for org in orgs:
url = 'https://api.github.com/repos/{org}/{app}'.format(org=org, app=git_url) 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) install_app(app=app_name, bench_path=bench_path, verbose=verbose, skip_assets=skip_assets)
sys.exit() 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( exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format(
git_url=git_url, git_url=git_url,
shallow_clone=shallow_clone, shallow_clone=shallow_clone,
@ -160,7 +153,7 @@ def get_app_name(bench_path, repo_name):
def new_app(app, bench_path='.'): def new_app(app, bench_path='.'):
# For backwards compatibility # For backwards compatibility
app = app.lower().replace(" ", "_").replace("-", "_") 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')) apps = os.path.abspath(os.path.join(bench_path, 'apps'))
bench.set_frappe_version(bench_path=bench_path) 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) install_app(app, bench_path=bench_path)
def install_app(app, bench_path=".", verbose=False, no_cache=False, postprocess=True, skip_assets=False): def install_app(app, bench_path=".", verbose=False, no_cache=False, restart_bench=True, skip_assets=False):
logger.info("installing {}".format(app)) 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") pip_path = os.path.join(bench_path, "env", "bin", "pip")
quiet_flag = "-q" if not verbose else "" 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) add_to_appstxt(app, bench_path=bench_path)
if postprocess:
if not skip_assets: if not skip_assets:
build_assets(bench_path=bench_path, app=app) build_assets(bench_path=bench_path, app=app)
if restart_bench:
conf = get_config(bench_path=bench_path) conf = get_config(bench_path=bench_path)
if conf.get('restart_supervisor_on_update'): 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) 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)) print("Skipping pull for app {}, since remote doesn't exist, and adding it to excluded apps".format(app))
continue continue
logger.info('pulling {0}'.format(app)) logger.log('pulling {0}'.format(app))
if reset: if reset:
exec_cmd("git fetch --all", cwd=app_dir) exec_cmd("git fetch --all", cwd=app_dir)
exec_cmd("git reset --hard {remote}/{branch}".format( exec_cmd("git reset --hard {remote}/{branch}".format(
@ -359,10 +354,6 @@ def get_upstream_version(app, branch=None, bench_path='.'):
raise raise
return get_version_from_string(contents) 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='.'): def get_repo_dir(app, bench_path='.'):
return os.path.join(bench_path, 'apps', app) 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.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 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: if check_upgrade:
version_upgrade = is_version_upgrade(app=app, bench_path=bench_path, branch=branch) 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) sys.exit(1)
print("Switching for "+app) 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: if str(repo.active_branch) == branch:
switched_apps.append(app) switched_apps.append(app)

View File

@ -14,9 +14,8 @@ import bench
from bench.app import get_apps from bench.app import get_apps
from bench.commands import bench_command from bench.commands import bench_command
from bench.config.common_site_config import get_config 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 from_command_line = False
change_uid_msg = "You should not run this command as root" 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(): def cli():
global from_command_line global from_command_line
from_command_line = True from_command_line = True
command = " ".join(sys.argv)
change_working_directory() change_working_directory()
logger = setup_logging() or logging.getLogger(bench.PROJECT_NAME)
logger.info(command)
check_uid() check_uid()
change_dir() change_dir()
change_uid() change_uid()
@ -56,8 +58,11 @@ def cli():
try: try:
bench_command() bench_command()
except PatchError: except BaseException as e:
sys.exit(1) 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(): def check_uid():

View File

@ -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) @click.option('--version', is_flag=True, is_eager=True, callback=print_bench_version, expose_value=False)
def bench_command(bench_path='.'): def bench_command(bench_path='.'):
import bench import bench
from bench.utils import setup_logging
bench.set_frappe_version(bench_path=bench_path) 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 from bench.commands.make import init, get_app, new_app, remove_app, exclude_app_for_update, include_app_for_update, pip

View File

@ -80,6 +80,7 @@ def remove_common_config(keys):
config.add_command(config_restart_supervisor_on_update) config.add_command(config_restart_supervisor_on_update)
config.add_command(config_restart_systemd_on_update) config.add_command(config_restart_systemd_on_update)
config.add_command(config_dns_multitenant) config.add_command(config_dns_multitenant)
config.add_command(config_rebase_on_pull)
config.add_command(config_serve_default_site) config.add_command(config_serve_default_site)
config.add_command(config_http_timeout) config.add_command(config_http_timeout)
config.add_command(set_common_config) config.add_command(set_common_config)

View File

@ -4,7 +4,6 @@ import sys
# imports - third party imports # imports - third party imports
import click import click
from six import PY3
# imports - module imports # imports - module imports
import bench.config.lets_encrypt 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("--node", help="Update only Node packages", default=False, is_flag=True)
@click.option("--python", help="Update only Python 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): def setup_requirements(node=False, python=False):
if not node: if not (node or python):
from bench.utils import update_requirements as setup_python_packages from bench.utils import update_requirements
setup_python_packages() update_requirements()
if not python: elif not node:
from bench.utils import update_node_packages as setup_node_packages from bench.utils import update_python_packages
setup_node_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") @click.command("manager", help="Setup bench-manager.local site with the bench_manager app installed on it")

View File

@ -172,9 +172,7 @@ def prepare_sites(config, bench_path):
if not dns_multitenant: if not dns_multitenant:
message = "Port configuration list:" message = "Port configuration list:"
port_config_index = 0
for site in sites_configs: for site in sites_configs:
port_config_index += 1
message += "\n\nSite {0} assigned port: {1}".format(site["name"], site["port"]) message += "\n\nSite {0} assigned port: {1}".format(site["name"], site["port"])
print(message) print(message)

View File

@ -11,9 +11,9 @@ watch: bench watch
{% endif %} {% endif %}
{% if use_rq -%} {% if use_rq -%}
schedule: bench schedule schedule: bench schedule
worker_short: bench worker --queue short --quiet worker_short: bench worker --queue short 1>> logs/worker.log 2>> logs/worker.error.log
worker_long: bench worker --queue long --quiet worker_long: bench worker --queue long 1>> logs/worker.log 2>> logs/worker.error.log
worker_default: bench worker --queue default --quiet worker_default: bench worker --queue default 1>> logs/worker.log 2>> logs/worker.error.log
{% else %} {% else %}
workerbeat: sh -c 'cd sites && exec ../env/bin/python -m frappe.celery_app beat -s scheduler.schedule' 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' 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'

View File

@ -4,7 +4,7 @@
become: yes become: yes
become_user: root become_user: root
yum: yum:
name: https://centos7.iuscommunity.org/ius-release.rpm name: https://repo.ius.io/ius-release-el7.rpm
state: present state: present
- name: "Setup prerequisites using yum" - name: "Setup prerequisites using yum"

View File

@ -136,12 +136,14 @@ class TestBenchInit(TestBenchBase):
bench_path = os.path.join(self.benches_path, "test-bench") bench_path = os.path.join(self.benches_path, "test-bench")
app_path = os.path.join(bench_path, "apps", "frappe") 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) app_branch_after_switch = str(git.Repo(path=app_path).active_branch)
if successful_switch:
self.assertEqual("version-12", app_branch_after_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) app_branch_after_second_switch = str(git.Repo(path=app_path).active_branch)
if successful_switch:
self.assertEqual("develop", app_branch_after_second_switch) self.assertEqual("develop", app_branch_after_second_switch)

View File

@ -10,7 +10,6 @@ import json
import logging import logging
import multiprocessing import multiprocessing
import os import os
import platform
import pwd import pwd
import re import re
import select import select
@ -39,7 +38,7 @@ class PatchError(Exception):
class CommandFailedError(Exception): class CommandFailedError(Exception):
pass pass
logger = logging.getLogger(__name__) logger = logging.getLogger(bench.PROJECT_NAME)
bench_cache_file = '.bench.cmd' bench_cache_file = '.bench.cmd'
folders_in_bench = ('apps', 'sites', 'config', 'logs', 'config/pids') folders_in_bench = ('apps', 'sites', 'config', 'logs', 'config/pids')
sudoers_file = '/etc/sudoers.d/frappe' 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: if e.errno == errno.EEXIST:
pass pass
setup_logging() setup_logging(bench_path=path)
setup_env(bench_path=path, python=python) 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', 'reset', '--hard'], cwd=app_path)
subprocess.check_output(['git', 'pull', '--rebase', remote, branch], 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: with open(os.path.join(clone_from, 'sites', 'apps.txt'), 'r') as f:
apps = f.read().splitlines() apps = f.read().splitlines()
@ -297,8 +296,13 @@ def clone_apps_from(bench_path, clone_from, update_app=True):
def exec_cmd(cmd, cwd='.'): def exec_cmd(cmd, cwd='.'):
import shlex import shlex
print("{0}$ {1}{2}".format(color.silver, cmd, color.nc)) 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) 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): def which(executable, raise_err = False):
@ -372,7 +376,7 @@ def get_sites(bench_path='.'):
def setup_backups(bench_path='.'): def setup_backups(bench_path='.'):
from bench.config.common_site_config import get_config 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) bench_dir = os.path.abspath(bench_path)
user = get_config(bench_path=bench_dir).get('frappe_user') user = get_config(bench_path=bench_dir).get('frappe_user')
@ -424,6 +428,13 @@ def setup_sudoers(user):
def setup_logging(bench_path='.'): 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')): if os.path.exists(os.path.join(bench_path, 'logs')):
logger = logging.getLogger(bench.PROJECT_NAME) logger = logging.getLogger(bench.PROJECT_NAME)
log_file = os.path.join(bench_path, 'logs', 'bench.log') log_file = os.path.join(bench_path, 'logs', 'bench.log')
@ -433,6 +444,8 @@ def setup_logging(bench_path='.'):
logger.addHandler(hdlr) logger.addHandler(hdlr)
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
return logger
def get_process_manager(): def get_process_manager():
for proc_man in ['honcho', 'foreman', 'forego']: for proc_man in ['honcho', 'foreman', 'forego']:
@ -459,14 +472,6 @@ def start(no_dev=False, concurrency=None, procfile=None):
os.execv(program, command) 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(): def get_git_version():
'''returns git version from `git --version` '''returns git version from `git --version`
extracts version number from string `get version 1.9.1` etc''' 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) 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): def restart_supervisor_processes(bench_path='.', web_workers=False):
from .config.common_site_config import get_config from .config.common_site_config import get_config
conf = get_config(bench_path=bench_path) conf = get_config(bench_path=bench_path)
@ -564,13 +560,24 @@ def update_env_pip(bench_path):
def update_requirements(bench_path='.'): def update_requirements(bench_path='.'):
from bench.app import get_apps, install_app from bench.app import get_apps, install_app
print('Updating Python libraries...') print('Installing applications...')
# update env pip
update_env_pip(bench_path) update_env_pip(bench_path)
for app in get_apps(): 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='.'): def update_node_packages(bench_path='.'):
@ -634,21 +641,6 @@ def update_npm_packages(bench_path='.'):
exec_cmd('npm install', cwd=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='.'): def backup_site(site, bench_path='.'):
bench.set_frappe_version(bench_path=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) 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='.'): def get_current_frappe_version(bench_path='.'):
from .app import get_current_frappe_version as fv from .app import get_current_frappe_version as fv
return fv(bench_path=bench_path) return fv(bench_path=bench_path)
@ -785,13 +764,6 @@ def run_frappe_cmd(*args, **kwargs):
sys.exit(return_code) 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='.'): def validate_upgrade(from_ver, to_ver, bench_path='.'):
if to_ver >= 6: if to_ver >= 6:
if not find_executable('npm') and not (find_executable('node') or find_executable('nodejs')): 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) 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): def get_bench_name(bench_path):
return os.path.basename(os.path.abspath(bench_path)) return os.path.basename(os.path.abspath(bench_path))
@ -984,78 +949,10 @@ def find_benches(directory=None):
return benches 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*(?P<value>true|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): def migrate_env(python, backup=False):
from bench.config.common_site_config import get_config from bench.config.common_site_config import get_config
from bench.app import get_apps from bench.app import get_apps
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
nvenv = 'env' nvenv = 'env'
path = os.getcwd() path = os.getcwd()
python = which(python) 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) 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)) exec_cmd('{redis} FLUSHALL'.format(redis = redis))
logger.debug('Clearing Redis DataBase...') logger.log('Clearing Redis DataBase...')
exec_cmd('{redis} FLUSHDB'.format(redis = redis)) exec_cmd('{redis} FLUSHDB'.format(redis = redis))
except: 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 # Backup venv: restore using `virtualenv --relocatable` if needed
if backup: if backup:
@ -1086,7 +983,7 @@ def migrate_env(python, backup=False):
source = os.path.join(path, 'env') source = os.path.join(path, 'env')
target = parch target = parch
logger.debug('Backing up Virtual Environment') logger.log('Backing up Virtual Environment')
stamp = datetime.now().strftime('%Y%m%d_%H%M%S') stamp = datetime.now().strftime('%Y%m%d_%H%M%S')
dest = os.path.join(path, str(stamp)) dest = os.path.join(path, str(stamp))
@ -1094,17 +991,18 @@ def migrate_env(python, backup=False):
shutil.move(dest, target) shutil.move(dest, target)
# Create virtualenv using specified python # Create virtualenv using specified python
venv_creation, packages_setup = 1, 1
try: try:
logger.debug('Setting up a New Virtual {} Environment'.format(python)) logger.log('Setting up a New Virtual {} Environment'.format(python))
exec_cmd('{virtualenv} --python {python} {pvenv}'.format(virtualenv=virtualenv, python=python, pvenv=pvenv)) 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()]) 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: except:
logger.debug('Migration Error') if venv_creation or packages_setup:
raise logger.warning('Migration Error')
def is_dist_editable(dist): def is_dist_editable(dist):

View File

@ -30,9 +30,6 @@ To manually install frappe/erpnext, you can follow this [this wiki](https://gith
#### 2. Install Bench #### 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 frappe-bench
pip3 install --user -e ~/.bench
Note: Please do not remove the bench directory the above commands will create