diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c9dac499..17c3d9ef9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.8', '3.9', '3.10' ] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] name: Base (${{ matrix.python-version }}) diff --git a/bench/app.py b/bench/app.py index e99eca95c..b86ba8fc8 100755 --- a/bench/app.py +++ b/bench/app.py @@ -23,7 +23,6 @@ # imports - module imports import bench -from bench.exceptions import NotInBenchDirectoryError from bench.utils import ( UNSET_ARG, fetch_details_from_tag, @@ -706,10 +705,12 @@ def get_app( if not is_bench_directory(bench_path): if not init_bench: - raise NotInBenchDirectoryError( + click.secho( f"{os.path.realpath(bench_path)} is not a valid bench directory. " - "Run with --init-bench if you'd like to create a Bench too." + "Run with --init-bench if you'd like to create a Bench too.", + fg="red", ) + sys.exit(1) from bench.utils.system import init @@ -851,9 +852,11 @@ def install_resolved_deps( def new_app(app, no_git=None, bench_path="."): if bench.FRAPPE_VERSION in (0, None): - raise NotInBenchDirectoryError( - f"{os.path.realpath(bench_path)} is not a valid bench directory." + click.secho( + f"{os.path.realpath(bench_path)} is not a valid bench directory.", + fg="red", ) + sys.exit(1) # For backwards compatibility app = app.lower().replace(" ", "_").replace("-", "_") diff --git a/bench/bench.py b/bench/bench.py index dd2afc982..1b2ca261e 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -283,7 +283,7 @@ def initialize_apps(self): ] self.apps.remove("frappe") self.apps.insert(0, "frappe") - except FileNotFoundError: + except (FileNotFoundError, ValueError): self.apps = [] def __getitem__(self, key): diff --git a/bench/config/procfile.py b/bench/config/procfile.py index 7feaab722..5b881a3e4 100755 --- a/bench/config/procfile.py +++ b/bench/config/procfile.py @@ -4,12 +4,14 @@ import click import bench -from bench.app import use_rq from bench.bench import Bench from bench.utils import which -def setup_procfile(bench_path, yes=False, skip_redis=False): +def setup_procfile(bench_path, yes=False, skip_redis=False, skip_web=False, skip_watch=None, skip_socketio=False, skip_schedule=False, with_coverage=False): + if skip_watch is None: + # backwards compatibilty; may be eventually removed + skip_watch = os.environ.get("CI") config = Bench(bench_path).conf procfile_path = os.path.join(bench_path, "Procfile") @@ -25,10 +27,13 @@ def setup_procfile(bench_path, yes=False, skip_redis=False): .get_template("Procfile") .render( node=which("node") or which("nodejs"), - use_rq=use_rq(bench_path), webserver_port=config.get("webserver_port"), - CI=os.environ.get("CI"), skip_redis=skip_redis, + skip_web=skip_web, + skip_watch=skip_watch, + skip_socketio=skip_socketio, + skip_schedule=skip_schedule, + with_coverage=with_coverage, workers=config.get("workers", {}), is_mac=is_mac, ) diff --git a/bench/config/templates/Procfile b/bench/config/templates/Procfile index 1f2440fb5..199b8b2bd 100644 --- a/bench/config/templates/Procfile +++ b/bench/config/templates/Procfile @@ -2,15 +2,18 @@ redis_cache: redis-server config/redis_cache.conf redis_queue: redis-server config/redis_queue.conf {% endif %} -web: bench serve {% if webserver_port -%} --port {{ webserver_port }} {%- endif %} - +{% if not skip_web %} +web: bench serve {% if with_coverage -%} --with-coverage {%- endif %} {% if webserver_port -%} --port {{ webserver_port }} {%- endif %} +{% endif %} +{% if not skip_socketio %} socketio: {{ node }} apps/frappe/socketio.js - -{% if not CI %} +{% endif %} +{% if not skip_watch %} watch: bench watch {% endif %} - +{% if not skip_schedule %} schedule: bench schedule +{% endif %} worker: {{ 'OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES NO_PROXY=*' if is_mac else '' }} bench worker 1>> logs/worker.log 2>> logs/worker.error.log {% for worker_name, worker_details in workers.items() %} worker_{{ worker_name }}: {{ 'OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES NO_PROXY=*' if is_mac else '' }} bench worker --queue {{ worker_name }} 1>> logs/worker.log 2>> logs/worker.error.log diff --git a/bench/exceptions.py b/bench/exceptions.py index 0465167c2..ad8d7f3ea 100644 --- a/bench/exceptions.py +++ b/bench/exceptions.py @@ -33,10 +33,5 @@ class CannotUpdateReleaseBench(ValidationError): class FeatureDoesNotExistError(CommandFailedError): pass - -class NotInBenchDirectoryError(Exception): - pass - - class VersionNotFound(Exception): pass diff --git a/bench/utils/__init__.py b/bench/utils/__init__.py index aee8f4e89..595db9942 100644 --- a/bench/utils/__init__.py +++ b/bench/utils/__init__.py @@ -43,6 +43,9 @@ def is_bench_directory(directory=os.path.curdir): for folder in paths_in_bench: path = os.path.abspath(os.path.join(directory, folder)) is_bench = is_bench and os.path.exists(path) + # Once is_bench becomes false, it will always be false, even if other path exists. + if not is_bench: + break return is_bench diff --git a/bench/utils/bench.py b/bench/utils/bench.py index 8a455d5fb..b96417f88 100644 --- a/bench/utils/bench.py +++ b/bench/utils/bench.py @@ -114,10 +114,11 @@ def _generate_dev_deps_pattern(pyproject_path): from tomllib import loads requirements_pattern = "" - pyroject_config = loads(open(pyproject_path).read()) + with open(pyproject_path) as f: + pyproject_config = loads(f.read()) with contextlib.suppress(KeyError): - for pkg, version in pyroject_config["tool"]["bench"]["dev-dependencies"].items(): + for pkg, version in pyproject_config["tool"]["bench"]["dev-dependencies"].items(): op = "==" if "=" not in version else "" requirements_pattern += f"{pkg}{op}{version} " return requirements_pattern