tutor icon indicating copy to clipboard operation
tutor copied to clipboard

Tutor "dev launch" not compatible with latest click v8.3.0

Open odemakov opened this issue 3 months ago • 5 comments

Bug description

Click 8.3.0 introduced a breaking change where optional parameters without defaults now receive a Sentinel object instead of None: https://github.com/pallets/click/commit/b64ea07128a6368b5f6f93035c75d5693c7ba572

This causes tutor dev launch to fail with a TypeError when building dev Docker images because the Sentinel object is passed to shlex.join(), which expects only string arguments.

/home/pupkin/tutor-19.0.5/. $ TUTOR_ROOT=$(pwd) tutor dev launch 
⚠️  Failed to enable plugin 'indigo': plugin 'indigo' is not installed.
⚠️  Failed to enable plugin 'mfe': plugin 'mfe' is not installed.
==================================================
        Interactive platform configuration
==================================================
As you are not running this platform in production, we automatically set the following configuration values:
    LMS_HOST = local.openedx.io
    CMS_HOST = studio.local.openedx.io
    ENABLE_HTTPS = False
Your platform name/title [My Open edX] 
Your public contact email address [[email protected]] 
The default language code for the platform [en] 
Configuration saved to /home/pupkin/tutor-19.0.5/config.yml
Environment generated in /home/pupkin/tutor-19.0.5/env
======================================
        Building Docker images
======================================
Building image openedx-dev:19.0.5
Traceback (most recent call last):
  File "/home/pupkin/tutor-19.0.5/.venv/bin/tutor", line 7, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/tutor/commands/cli.py", line 27, in main
    cli()  # pylint: disable=no-value-for-parameter
    ^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 1462, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 1383, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 1850, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 1850, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 1246, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 814, in invoke
    return callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/decorators.py", line 34, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/tutor/commands/compose.py", line 138, in launch
    context.invoke(images.build, image_names=images_to_build)
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/core.py", line 814, in invoke
    return callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/click/decorators.py", line 46, in new_func
    return f(get_current_context().obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/tutor/commands/images.py", line 241, in build
    images.build(
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/tutor/images.py", line 11, in build
    utils.docker(*command)
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/tutor/utils.py", line 193, in docker
    return execute("docker", *command)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/tutor-19.0.5/.venv/lib/python3.11/site-packages/tutor/utils.py", line 217, in execute
    click.echo(fmt.command(shlex.join(command)))
                           ^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/.pyenv/versions/3.11.8/lib/python3.11/shlex.py", line 320, in join
    return ' '.join(quote(arg) for arg in split_command)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pupkin/.pyenv/versions/3.11.8/lib/python3.11/shlex.py", line 320, in <genexpr>
    return ' '.join(quote(arg) for arg in split_command)
                    ^^^^^^^^^^
  File "/home/pupkin/.pyenv/versions/3.11.8/lib/python3.11/shlex.py", line 329, in quote
    if _find_unsafe(s) is None:
       ^^^^^^^^^^^^^^^
TypeError: expected string or bytes-like object, got 'Sentinel'

How to reproduce

  1. Set up Python environment:
    echo 3.11.8 > .python-version
    uv venv --python 3.11.8 .venv
    source .venv/bin/activate
    
  2. Install tutor:
    uv pip install "tutor==19.0.5"
    
  3. Run the failing command tutor dev launch

Environment

  • OS: MacOS Sequoia (also reproduced on Ubuntu)
  • Python: 3.11.8
  • Tutor: 19.0.5 and 20.0.1
  • Click: 8.3.0 (works fine with click <8.3.0)

Temporary fix

Install older version of click: uv pip install "click<8.3"

odemakov avatar Sep 19 '25 18:09 odemakov

Tutor is currently on click 8.1.8 version. Unless explicitly installed, the latest version of click won't install. That said, this will require changes if it is causing the launch to break.

DawoudSheraz avatar Sep 22 '25 06:09 DawoudSheraz

@DawoudSheraz note however that the most recent version of click will be installed when we run pip install tutor because click is not pinned in base.in:

https://github.com/overhangio/tutor/blob/c031d2473a65b5413784bbcc7dcbcc50865a57e4/pyproject.toml#L52 https://github.com/overhangio/tutor/blob/release/requirements/base.in

regisb avatar Sep 22 '25 07:09 regisb

Created a PR to temporarily pin click https://github.com/overhangio/tutor/pull/1277

DawoudSheraz avatar Sep 23 '25 06:09 DawoudSheraz

In case anyone is facing this issue pip install click==8.1.8 did the job for me

junedkhatri31 avatar Sep 30 '25 10:09 junedkhatri31

I had a similar issue where tutor local launch was not always out of sync and was not available for the LMS and CMS workers to connect to. This was on a completely fresh install of Python 3.15 and running on an M3 if it helps.

The pip install click==8.1.8 fix of @junedkhatri31 resolved this issue.

petrepatrasc avatar Oct 08 '25 07:10 petrepatrasc