Skip to content

Double parenthesis in activated venv generated by Python 3.12.10 #132361

Description

@IterableTrucks

Bug report

Bug description:

python3.12 -m venv venv
source venv/bin/activate

There will be double parenthesis displayed on the terminal. This bug may be related to this commit because Python 3.12.9 is normal.

CPython versions tested on:

3.12

Operating systems tested on:

Linux

Activity

  1. hugovk commented on Apr 10, 2025

    @hugovk
    Member

    Please could you paste the terminal output?

    This is what I get on macOS using iTerm:

    /private/tmp via  v3.1.3
    ❯ python3.12 -m venv venv
    source venv/bin/activate
    
    /private/tmp via  v3.12.10 (venv) via  v3.1.3 took 10s
    ❯ python3.12 --version
    Python 3.12.10
    
    /private/tmp via  v3.12.10 (venv) via  v3.1.3
  2. i9wa4 commented on Apr 10, 2025

    @i9wa4

    I encountered this too.

    [srv1] [2025-04-10 22:27:08] zsh [~]
    $ lsb_release -d
    No LSB modules are available.
    Description:    Ubuntu 24.04.2 LTS
    [srv1] [2025-04-10 22:27:26] zsh [~]
    $ pyenv global 3.12.10
    [srv1] [2025-04-10 22:27:27] zsh [~]
    $ which python
    /home/i9wa4/.pyenv/shims/python
    [srv1] [2025-04-10 22:27:35] zsh [~]
    $ python --version
    Python 3.12.10
    [srv1] [2025-04-10 22:27:58] zsh [~]
    $ python -m venv venv3.12.10
    [srv1] [2025-04-10 22:28:11] zsh [~]
    $ source venv3.12.10/bin/activate
    ((venv3.12.10) ) [srv1] [2025-04-10 22:28:11] zsh [~]
    $ 
  3. added
    stdlibStandard Library Python modules in the Lib/ directory
    topic-venvRelated to the venv module
    on Apr 10, 2025
  4. brianschubert commented on Apr 10, 2025

    @brianschubert
    Contributor

    I can reproduce this. I think this may be related to this diff, which was included in the 3.12 backport, but not in the main PR

     if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
         _OLD_VIRTUAL_PS1="${PS1:-}"
    -    PS1=__VENV_PROMPT__"${PS1:-}"
    +    PS1="("__VENV_PROMPT__") ${PS1:-}"
         export PS1
    -    VIRTUAL_ENV_PROMPT=__VENV_PROMPT__
    -    export VIRTUAL_ENV_PROMPT
     fi

    For context, the generated activate script looks like this:

    # [...]
    VIRTUAL_ENV_PROMPT='(venv) '
    export VIRTUAL_ENV_PROMPT
    
    # unset PYTHONHOME if set
    # this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
    # could use `if (set -u; : $PYTHONHOME) ;` in bash
    if [ -n "${PYTHONHOME:-}" ] ; then
        _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
        unset PYTHONHOME
    fi                                                                                                                                                   
    
    if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
        _OLD_VIRTUAL_PS1="${PS1:-}"
        PS1="("'(venv) '") ${PS1:-}"
        export PS1 
    fi
    # [...]

    cc @vsajip

  5. StanFromIreland commented on Apr 15, 2025

    @StanFromIreland
    Member

    This issue should be closed, it only affects 3.12 which no longer allows bugfixes.

  6. hugovk commented on Apr 16, 2025

    @hugovk
    Member

    Reproducible in 3.12:

    ❯ docker run --rm -it python:3.12 bash
    root@9131fb969a1b:/# python3 --version
    Python 3.12.10
    root@9131fb969a1b:/# python -m venv venv
    root@9131fb969a1b:/# source venv/bin/activate
    ((venv) ) root@9131fb969a1b:/#
    exit

    But not 3.13:

    ❯ docker run --rm -it python:3.13 bash
    root@05795675a6a3:/# python3 --version
    Python 3.13.3
    root@05795675a6a3:/# python -m venv venv
    root@05795675a6a3:/# source venv/bin/activate
    (venv) root@05795675a6a3:/#
    exit
  7. StanFromIreland commented on Apr 16, 2025

    @StanFromIreland
    Member

    Very unfortunate, introduced just days before the deadline, and very visible too :-(

  8. hugovk commented on Apr 16, 2025

    @hugovk
    Member

    All the more reason to upgrade to Python 3.13, and get all the other bugfixes too 👍

  9. gernophil commented on May 22, 2025

    @gernophil

    Came here pretty late. Is this only a cosmetic bug or does it have any consequences?

  10. hugovk commented on May 22, 2025

    @hugovk
    Member

    Likely only cosmetic.

  11. DellAnderson commented on Jul 13, 2025

    @DellAnderson

    In case anyone wants to fix it themselves in a fork, here's what I think is going on:

    The venv activate script generated by Python includes a redundant wrapping of parentheses and a trailing space in the PS1 prompt assignment.

    In current versions (3.11, 3.12, not sure about 3.13), eg when creating a ~/venv312 environment:

    the generated activate script includes the following:

    VIRTUAL_ENV_PROMPT='(venv312) ' # note parens & trailing space.
    ...
    Line 57
    PS1="("VENV_PROMPT") ${PS1:-}" # note additional parens & interval space

    This results in a prompt like: "((venv312) ) usersprompt$" prompt with double parentheses and an extra trailing space.

    apparently because the script adds more parens & spaces in line 70:

    https://github.com/python/cpython/blob/main/Lib/venv/scripts/common/activate
    line 57
    VIRTUAL_ENV_PROMPT=VENV_PROMPT
    ...
    line 70
    PS1="("VENV_PROMPT") ${PS1:-}" # Note added parens & trailing space around VENV_PROMPT

    Suggested Fix:

    Suggest use either inject the environment name itself (e.g., venv312) into the prompt string,
    and use only the shell script to format it, or if necessary (less optimal)
    Use the VENV_ENV_PROMPT as is without adding additional parens & spaces

    #https://github.com/python/cpython/blob/main/Lib/venv/scripts/common/activate
    line 57
    VIRTUAL_ENV_PROMPT="(VENV_NAME)" #use only venv name, not a preformatted prompt
    ...
    line 70
    PS1="${VIRTUAL_ENV_PROMPT} ${PS1:-}" #remove extra parens & space here if unable to use VENV_NAME

    This avoids duplication and makes the script easier to read, maintain or override.

    The change should apply to:

    Lib/venv/scripts/common/activate
    

    May also need to remove formatting from template injection code here:
    https://github.com/python/cpython/blob/main/Lib/venv/__init__.py (where

    line 483 def replace_variables(self, text, context):

    line 496 'VENV_NAME': context.env_name,
    line 497 'VENV_PROMPT': context.prompt,

  12. DellAnderson commented on Jul 14, 2025

    @DellAnderson

    I can confirm that 3.13.5 at least has fixed this bug. It's such a simple but annoying one it's too bad it won't be backported to 3.11 & 3.12. There was some mention in the 'blame' section about quotes for avoiding injection so perhaps there is a security risk?

  13. cdjameson commented on Sep 19, 2025

    @cdjameson

    Just a +1 to say this is what I'd call out-of-character for Python at this point in its life? Introducing a bug into the last bugfix release of a version is disappointing. To compliment sandwich it, I suppose it says a lot that Python has gotten to the maturity where we can expect that things like this won't happen. But then they do happen. I can see that this won't get fixed, but with 3.13 being effectively a major version bump (due to cython major version incompatibility) and needing long runway, this—admittedly cosmetic—unfixable bug isn't up to the standard of professionalism I've come to expect from the hardworking maintainers of Python. Keep working hard, and know that I still believe in you all now more than I ever did before!

  14. hugovk commented on Sep 20, 2025

    @hugovk
    Member

    We don't use SemVer and every Python feature release is effectively a "major" bump due to removed deprecations.

    If you'd like to help out, we have 2k open PRs that can benefit from review. Also the last ever 3.9 release is going out any day now before its EOL, so you're welcome to double check already merged PRs to that branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-venvRelated to the venv moduletype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions