Julia language: skip startup.jl file by ericphanson · Pull Request #3496 · pre-commit/pre-commit
Adds --startup-file=no to both invocations of Julia (install & run). The startup file is a Julia script that users can configure to run commands before the start of their Julia session. It is typically used to load developer packages like Revise and not used "in-production". Here when we run our pre-commit hooks we do not want to run the user's startup file which could have dependencies the current environment does not have.
pytest tests -sk test_julia_hook_with_startup =========================================== test session starts =========================================== platform darwin -- Python 3.13.4, pytest-8.4.1, pluggy-1.6.0 rootdir: /Users/eph/pre-commit configfile: tox.ini plugins: env-1.1.5 collected 802 items / 801 deselected / 1 selected tests/languages/julia_test.py F ================================================ FAILURES ================================================= ______________________________________ test_julia_hook_with_startup _______________________________________ tmp_path = PosixPath('/private/var/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/pytest-of-eph/pytest-21/test_julia_hook_with_startup0') def test_julia_hook_with_startup(tmp_path): # We will temporarily use a new Julia depot so we can freely write a # startup.jl file existing_depot = os.getenv('JULIA_DEPOT_PATH') try: with tempfile.TemporaryDirectory() as depot_tempdir: os.environ['JULIA_DEPOT_PATH'] = depot_tempdir depot_path = Path(depot_tempdir) depot_path.joinpath('config').mkdir(exist_ok=True) startup = depot_path.joinpath('config', 'startup.jl') # write a startup.jl file that throws an error so # we know it's not used startup.write_text('error("Startup file used!")\n') # check that the test still succeeds even with a bad startup file > test_julia_hook(tmp_path) tests/languages/julia_test.py:49: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/languages/julia_test.py:32: in test_julia_hook assert run_language(tmp_path, julia, 'src/main.jl') == expected ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ testing/language_helpers.py:26: in run_language language.install_environment(prefix, version, deps) pre_commit/languages/julia.py:129: in install_environment cmd_output_b( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ check = True cmd = ('/Users/eph/.juliaup/bin/julia', '-e', '\n @assert length(ARGS) > 0\n hook_env = ARGS[1]\n deps ...ar/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/pytest-of-eph/pytest-21/test_julia_hook_with_startup0/juliaenv-default') kwargs = {'cwd': '/private/var/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/pytest-of-eph/pytest-21/test_julia_hook_with_startup0', 'stderr': -1, 'stdin': -1, 'stdout': -1} proc = <Popen: returncode: 1 args: ('/Users/eph/.juliaup/bin/julia', '-e', '\n ...>, stdout_b = b'' stderr_b = b'ERROR: LoadError: Startup file used!\nStacktrace:\n [1] error(s::String)\n @ Base ./error.jl:35\n [2] top-level sc...tup.jl:1\nin expression starting at /var/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/tmplwwx2crp/config/startup.jl:1\n' returncode = 1 def cmd_output_b( *cmd: str, check: bool = True, **kwargs: Any, ) -> tuple[int, bytes, bytes | None]: _setdefault_kwargs(kwargs) try: cmd = parse_shebang.normalize_cmd(cmd, env=kwargs.get('env')) except parse_shebang.ExecutableNotFoundError as e: returncode, stdout_b, stderr_b = e.to_output() else: try: proc = subprocess.Popen(cmd, **kwargs) except OSError as e: returncode, stdout_b, stderr_b = _oserror_to_output(e) else: stdout_b, stderr_b = proc.communicate() returncode = proc.returncode if check and returncode: > raise CalledProcessError(returncode, cmd, stdout_b, stderr_b) E pre_commit.util.CalledProcessError: command: ('/Users/eph/.juliaup/bin/julia', '-e', '\n @assert length(ARGS) > 0\n hook_env = ARGS[1]\n deps = join(ARGS[2:end], " ")\n\n # We prepend @stdlib here so that we can load the package manager even\n # though `get_env_patch` limits `JULIA_LOAD_PATH` to just the hook env.\n pushfirst!(LOAD_PATH, "@stdlib")\n using Pkg\n popfirst!(LOAD_PATH)\n\n # Instantiate the environment shipped with the hook repo. If we have\n # additional dependencies we disable precompilation in this step to\n # avoid double work.\n precompile = isempty(deps) ? "1" : "0"\n withenv("JULIA_PKG_PRECOMPILE_AUTO" => precompile) do\n Pkg.instantiate()\n end\n\n # Add additional dependencies (with precompilation)\n if !isempty(deps)\n withenv("JULIA_PKG_PRECOMPILE_AUTO" => "1") do\n Pkg.REPLMode.pkgstr("add " * deps)\n end\n end\n ', '--', '/private/var/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/pytest-of-eph/pytest-21/test_julia_hook_with_startup0/juliaenv-default') E return code: 1 E stdout: (none) E stderr: E ERROR: LoadError: Startup file used! E Stacktrace: E [1] error(s::String) E @ Base ./error.jl:35 E [2] top-level scope E @ /var/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/tmplwwx2crp/config/startup.jl:1 E in expression starting at /var/folders/jb/plyyfc_d2bz195_0rc0n_zcw0000gp/T/tmplwwx2crp/config/startup.jl:1 pre_commit/util.py:111: CalledProcessError ========================================= short test summary info ========================================= FAILED tests/languages/julia_test.py::test_julia_hook_with_startup - pre_commit.util.CalledProcessError: command: ('/Users/eph/.juliaup/bin/julia', '-e', '\n @asser... ==================================== 1 failed, 801 deselected in 1.30s ====================================
The second commit is the implementation change which shows that the the fix is effective:
❯ pytest tests -sk test_julia_hook_with_startup =========================================== test session starts =========================================== platform darwin -- Python 3.13.4, pytest-8.4.1, pluggy-1.6.0 rootdir: /Users/eph/pre-commit configfile: tox.ini plugins: env-1.1.5 collected 802 items / 801 deselected / 1 selected tests/languages/julia_test.py . ============================== 1 passed, 801 deselected in 64.48s (0:01:04) ===============================