pypa / pipenv

Python Development Workflow for Humans.
https://pipenv.pypa.io
MIT License
24.72k stars 1.86k forks source link

pipenv powershell shell should label prompt when inside pipenv shell (similar to venv) #3505

Open jtmoon79 opened 5 years ago

jtmoon79 commented 5 years ago

tl;dr pipenv shell should label the powershell prompt when inside a shell. This is what venv currently does. Something like
(pipenv: project1-LQTIN6Io) PS C:\Users\user1\Projects\project1>


venv module

When using the venv module and then entering the virtual environment shell, the shell prompt becomes labeled. Here's an example in powershell:


     PS C:\Users\user1\Projects\project1> C:\Python\Python37\python.exe -m venv .venv
     PS C:\Users\user1\Projects\project1> .\.venv\Scripts\activate
     (.venv) PS C:\Users\user1\Projects\project1>

I find the prepended label "(.venv)" tremendously helpful. That prepended label is also colored green which is different than the remainder of the powershell prompt "PS C:\Users\user1\Projects>" in light-gray. It's easy to visually distinguish the green string "(.venv)" was prepended to the default powershell prompt. I often have several powershell windows open. That prepended label helps me remember which powershell window is currently in a python virtual environment.

this pipenv enhancement follows venv module

This Enhancement is to recommend pipenv implement the same feature. I imagine this would look like


    PS C:\Users\user1\Projects\project1> C:\Python\Python37\Scripts\pipenv.exe --python 3
    Creating a virtualenv for this project…
    Pipfile: C:\Users\user1\Projects\project1\Pipfile
    Using C:/Python/Python37/python.exe (3.7.1) to create virtualenv…
    [=== ] Creating virtual environment...Using base prefix 'C:\\Python\\Python37'
    New python executable in C:\Users\user1\.virtualenvs\project1-LQTIN6Io\Scripts\python.exe
    Installing setuptools, pip, wheel...
    done.
    Running virtualenv with interpreter C:/Python/Python37/python.exe

    Successfully created virtual environment!
    Virtualenv location: C:\Users\user1\.virtualenvs\project1-LQTIN6Io

    PS C:\Users\user1\Downloads\deleteme> C:\Python\Python37\Scripts\pipenv.exe shell
    (pipenv: project1-LQTIN6Io) PS C:\Users\user1\Projects\project1>

Notice the prepended prompt string "(pipenv: project1-LQTIN6Io)". Ideally, it would also be colorized different than the remaining prompt string.


This Issue is similar to pipenv Issue #40 (which addressed bash shell).

btw, after reading Pipenv: A Guide to the New Python Packaging Tool (realpython.com), I really want more pipenv!


Additional context

$ pipenv --support Pipenv version: `'2018.11.26'` Pipenv location: `'c:\\python\\python37\\lib\\site-packages\\pipenv'` Python location: `'c:\\python\\python37\\python.exe'` Python installations found: - `3.7.1`: `C:\Python\Python37\python.exe` - `3.6.7`: `C:\Python\Python36\python.exe` - `3.4`: `C:\Python\Python34\python.exe` PEP 508 Information: ``` {'implementation_name': 'cpython', 'implementation_version': '3.7.1', 'os_name': 'nt', 'platform_machine': 'AMD64', 'platform_python_implementation': 'CPython', 'platform_release': '10', 'platform_system': 'Windows', 'python_full_version': '3.7.1', 'python_version': '3.7', 'sys_platform': 'win32'} ``` Powershell version: ``` PS C:\Users\user1 > $PSVersionTable.PSVersion Major Minor ----- ----- 5 1 ``` System environment variables: - ... - `PIPENV_ACTIVE` - `PIP_DISABLE_PIP_VERSION_CHECK` - `PIP_PYTHON_PATH` - ... - `PROMPT` - `PSMODULEPATH` - ... - `PYTHONDONTWRITEBYTECODE` - ... - `VIRTUAL_ENV` - ... - `PIP_SHIMS_BASE_MODULE` - `PYTHONFINDER_IGNORE_UNSUPPORTED` Pipenv?specific environment variables: - `PIPENV_ACTIVE`: `1` Debug?specific environment variables: - `PATH`: `...` - `VIRTUAL_ENV`: `C:\Users\user1\.virtualenvs\foo-3kR5jZ-L`
techalchemy commented 5 years ago

sounds like a good idea, but doesn't it already prepend something? or is the suggestion to specifically add that it is a pipenv environment?

jtmoon79 commented 5 years ago

doesn't it already prepend something?

It does not appear to do so. Not in the powershell window title nor in the powershell prompt. Nor in the MinGW bash prompt.

the suggestion to specifically add that it is a pipenv environment?

Yes. With many powershell windows open, which powershell belongs to which environment (or no environment) becomes confusing.

I created a reasonable wrapper script to set the powershell window title. It appends a string like "pipenv: C:\Users\user1\.virtualenvs\project1-abcd (Python 3.7)".

techalchemy commented 5 years ago

I like the idea of (pipenv: projectname<-optional python version>) since I’m sure users don’t care about the hash fragment and I like the pipenv aspect being clear. The python version would only come from PIPENV_PYTHON unless we want to always include it. /cc @uranusjr

jtmoon79 commented 5 years ago

I’m sure users don’t care about the hash fragment

As a user, I really care about the actual path in use. It gives me a better sense of which pipenv is in use and where it lives and operates from. Without a tangible system location, it feels like pipenv is floating in space. This is especially confusing to new users of python virtual environments.

My two ¢

uranusjr commented 5 years ago

The actual path is indeed useful, but what @techalchemy referred to was the hash of the path (which Pipenv uses to identify projects).

Anyway, the prompt information is already there, it only needs to be implemented for Powershell. The only reason this is not already done is because it’s more difficult to do in Powershell than other common shells :)

jtmoon79 commented 5 years ago

what @techalchemy referred to was the hash of the path (which Pipenv uses to identify projects).

Ah, pardon me.

I’m sure users don’t care about the hash fragment

In my case, I still do care. Sometimes I'm removing and remaking pipenv environments because something gets fouled up (newbie mistakes) so I just start over (remove the pipenv environment). And I might have a few open powershell windows laying around. At other times, I'm reviewing why pycharm is behaving oddly. I will often check the project is using the correct pipenv-created virtual environment. Glancing at the matching hash fragment that pycharm is using and the hash fragment in a powershell window gives me some assurance the different processes are using the same pipenv environment (or not).

I'm not certain if the hash fragment is actually meaningful assurance in those two scenarios but it feels like it is.

I know the hash fragment is simply a hash of the path. However, I'm not entirely certain some other subtle mechanism changes between creating -> destroying -> creating a pipenv environment at the same path. Also, if I decide move/rename the project directory or a parent directory ... well, I'm not sure what occurs to already-established pipenv environments in that case. Either way, the hash fragment seems like a good thing to make readily visible for users like me.

jaepil-choi commented 4 years ago

Cannot agree more. I was linked to this issue page after I asked this on SO. I moved from Pycharm to VSCode and I found that the prepended (pipenv) is missing. Turned out Pycharm guys cleverly made their own configuration to better show that the user is in pipenv. It is a default feature in Pycharm if you make virtualenv with pipenv in the option. In VSCode, pipenv is inidicated in the dropbox at the right corner of the terminal that shows which shell you're using.

One way to tell whether you're on pipenv virtualenv is to type $ pip -V and see where the pip is located.

vbrh-immalle commented 4 years ago

I've hacked this together and put it in $profile but it is slow (EDIT: updated with a question every time you start Powershell):


$pip_answer = $Host.UI.PromptForChoice('pipenv', 'Do you want to add pipenv in this shells prompt?', @('&Yes'; '&No'), 1)

if ($pip_answer -eq 0) {
    function prompt {
        $pip_prompt = ""
        if (($(pip -V) -split ' ')[3].toLower().startsWith("$HOME\.virtualenvs".toLower()))
        { 
            $pip_prompt = " [pip] ";
        }
        "PS $pip_prompt$($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";    
    }
}```

(The original contents of the prompt can be seen with `cat Function:prompt`)
DraugurHundur commented 4 years ago

Here is what I use to get a specific prompt for each environment (faster than above as it does not run a command every time the prompt is evaluated):

function prompt{
  if ($env:PIPENV_ACTIVE -eq 1) {
    # @TODO: works only on Windows
    $venv = (($env:VIRTUAL_ENV -split "\\")[-1] -split "-")[0]
    "[pipenv:$venv] $(Get-Location)> ";
  } else {
    "$(Get-Location)$('>' * ($nestedPromptLevel + 1))";
  }
}

See https://ss64.com/ps/syntax-prompt.html on how to update your configuration to include this.

jakovlev-fedor commented 3 years ago

Here is some refactoring of code above I used original 'Activate.ps1' file from venv package for reference

if ($env:PIPENV_ACTIVE -eq 1) {

    function _OLD_PROMPT { "" }
    Copy-Item -Path function:prompt -Destination function:_OLD_PROMPT

    $_PROMPT_PREFIX = (($env:VIRTUAL_ENV -split "\\")[-1] -split "-")[0]

    function prompt {
        Write-Host -NoNewline -ForegroundColor Green "($_PROMPT_PREFIX) " 
        _OLD_PROMPT

    }
}

Here is what I use to get a specific prompt for each environment (faster than above as it does not run a command every time the prompt is evaluated):

function prompt{
  if ($env:PIPENV_ACTIVE -eq 1) {
    # @TODO: works only on Windows
    $venv = (($env:VIRTUAL_ENV -split "\\")[-1] -split "-")[0]
    "[pipenv:$venv] $(Get-Location)> ";
  } else {
    "$(Get-Location)$('>' * ($nestedPromptLevel + 1))";
  }
}

See https://ss64.com/ps/syntax-prompt.html on how to update your configuration to include this.

image

jakovlev-fedor commented 3 years ago

PS: It seems the method below have no practical use because this script doesn't run pipenv shell command, thus subshell not activated. The method above recommended.

I found out there is already exists properly made PowerShell Script out of the box. The issue then is why this script doesn't run when pipenv shell executed The only way to achieve desired behavior is to explicitly run script file from the folder

image

jakovlev-fedor commented 3 years ago

If you want to highlight prompt prefix with pretty green color you need manually change your project specific Activate.ps1 script from: image to: image

    if ("(mb) " -ne "") {
        function global:prompt {
            # Add the custom prefix to the existing prompt
            $previous_prompt_value = & $function:_old_virtual_prompt
            Write-Host -NoNewline -ForegroundColor Green "(mb) " 
            $previous_prompt_value
        }
    }

image

minalike commented 2 years ago

PS: It seems the method below have no practical use because this script doesn't run pipenv shell command, thus subshell not activated. The method above recommended.

I found out there is already exists properly made PowerShell Script out of the box. The issue then is why this script doesn't run when pipenv shell executed The only way to achieve desired behavior is to explicitly run script file from the folder

  • C:/Users/user_name/.virtualenvs/proj_name-ESQIrO6X/Scripts/Activate.ps1

image

thanks for this.

is there any update on whether we'll be able to get this functionality when using pipenv shell as well?

matteius commented 2 years ago

This still appears to be an issue with not showing the virtualenv or anything prepended when the shell is active on the windows side. same for git shell, cmd and power shell.

vkelk commented 2 years ago

For me this worked https://github.com/pypa/pipenv/issues/4264#issuecomment-845445399

Powershell is supported and you can enable it using the environment variable PIPENV_SHELL. So you can specify it via Windows settings or run

$Env:PIPENV_SHELL = "powershell"

before running pipenv shell.