Skip to content

The PATH variable is not set properly for Gui Git clients #1465

Closed

Description

@stevenxxiu

For Gui Git clients like SmartGit, the PATH variable isn't set correctly to locate the current virtualenv, and when it runs the Git hook it will give errors as it locates the wrong Python executable.

To make it work, I need to modify my .git/hooks/pre-commit and add the following line:

os.environ['PATH'] += os.pathsep + os.path.expanduser('~/.virtualenvs/myproject/bin/')

Is there some way to make this less manual and automatically add this when I install pre-commit for a new project?

Activity

  1. asottile commented on May 21, 2020

    @asottile
    Member

    can you show an example and what's happening and what you expect?

  2. asottile commented on May 21, 2020

    @asottile
    Member

    I suspect you're talking about a local + system hook which is the escape hatch and not the supported golden path -- local + system is "I promise I'll be responsible for making these tools available, trust me pre-commit and will not be receiving features like virtualenv activation, etc.

    if you depend on project-specific virtualenvs being on the PATH, you should write your hook entries as such (utilizing tools like tox or poetry or even just a script which knows how to modify the PATH and/or set up your environment)

    which on second read it sounds exactly like #1412 / #950

  3. stevenxxiu commented on May 22, 2020

    @stevenxxiu
    Author

    Ok I added an .env.sh and included:

    # Setup environment variables for using `pre-commit` in SmartGit
    source ~/.virtualenvs/$(<.venv)/bin/activate
    

    with the .pre-commit-config.yaml entries of:

    entry : sh -c 'source ./.env.sh && isort "$0"'
    language: system
    

    This appeared to work. Is it the recommended approach?

  4. asottile commented on May 22, 2020

    @asottile
    Member

    no, you should use https://github.com/asottile/seed-isort-config or an import sorter which doesn't need everything installed such as https://github.com/asottile/reorder_python_imports

    please next time describe your actual problem instead of some vague solution to your problem -- this is what's called an XY problem and is a very easy trap to fall into (especially when you're not 100% familiar with the space you're working in)

  5. stevenxxiu commented on May 22, 2020

    @stevenxxiu
    Author

    @asottile It's not just isort, but also prospector, black. I would like to install these into the local virtualenv instead of system-wide. This is my actual problem.

  6. asottile commented on May 22, 2020

    @asottile
    Member

    the whole point of pre-commit is it manages your tools, if you're using language: system you're escaping the supported path and things will be rocky (language: system is "I will provide the tools" instead of "pre-commit will provide the tools"). kinda the whole point of the framework is that it installs stuff for you

    pre-commit will install your tools in isolated environments and not globally if configured according to the documentation and examples

    and again, I can't see what you have because you still haven't shown your configuration or versions or logs or output

  7. KRunchPL commented on Nov 20, 2021

    @KRunchPL

    Maybe I can add one thing to this discussion because I was dealing with the same thing. I read few issues on it and I fully understand @asottile position not to modify the behavior of system language that is supposed to be unmanaged, system environment. The issue is that with current implementation the pre-commit run and git commit is actually behaving differently.

    I decided to not open another issue with the whole description above, because there is already too many of them, I believe that we can discuss it here and if you decide that we have a problem just reopen. I am also glad to help you implementing changes if we agree that some can be done.

    Problem

    In my opinion problem is that Python system language hooks do not run in the same environment as pre-commit when git commit is executed. Which causes pre-commit run and git commit to behave differently.

    Reproduction

    ## Pre-test configuration
    # create new poetry project
    poetry new temp_repo; cd temp_repo
    # initialize its git repository
    git init
    # add flake8 as dependency
    poetry add -D flake8
    # commit what you have
    git add .; git commit -m "initial commit"
    
    ## Test steps
    # (step 1) add pre-commit as developer dependency and install it to venv
    poetry add -D pre-commit
    # (step 2) create got hooks
    poetry run pre-commit install
    # (step 3) configure the hook
    # The example is simplified and runs flake8, but is actually important when running things that requires
    # all project dependencies, which as documentation states is one of the reasons to use local hooks with system language
    Set-Content .\.pre-commit-config.yaml -Value "repos: `
    -   repo: local `
        hooks: `
        -   id: flake8 `
            name: flake8 `
            entry: python -mflake8 `
            language: system `
            types: [python] `
            require_serial: true `
    "
    # (step 4) introduce flake error to the code
    Set-Content .\temp_repo\__init__.py -Value "__version__='0.1.0'"
    # (step 5) stage the changes
    git add .
    # (step 6) run pre-commit manually
    pre-commit run --all-files
    # (step 7) commit changes
    git commit
    

    Expected result

    The last two commands behave the same, they both fail, because pre-commit is not installed when venv is not activated.

    Actual result

    The pre-commit run (step 6) fails to find pre-commit command as expected.

    The git commit (step 7) runs pre-commit properly, but the hook itself fails, because of non-existing module.

    If there were non-local hooks, the first command would not run them of course, but the second would and they could even pass.

    Additional explanation

    I understand that the question is "Why the hell are you running commands outside of virtualenv if you need it?". The answer is that a lot of tools is doing it for me. For example VS Code SCM is running git commands as its own subprocess which usually does not have venv activated (the venv is activated by extension in integrated terminal).

    Cause

    The .git/hooks/pre-commit script runs the pre-commit application in hardcoded python virtualenv, but the application itself is executing system hooks outside of it.

    Workarounds that can be applied locally

    1. As stated in this issue already, one can modify the .git/hooks/pre-commit to append the virtualenv path to PATH env var, before running pre-commit application.

    2. As stated in this issue already, one can modify the entry of the hook, to first run a script that will actually activate the venv and then run the command.

    Proposed solution no. 1 (not good one, but proposed above and worth pointing why it is not good)

    Since the .git/hooks/pre-commit is bound to run the pre-commit in virtualenv, the system language hooks that are run, should also be run there.

    It can be achieved either by modifying the system language implementation or by just implementing workaround number one.

    Why not

    I understand the we are reluctant to do it, because pre-commit is not a Python-only tool and the system language is supposed (as the name states) to run in default system environment. The whole responsibility on providing proper system environment is on a user (and it is great).

    Proposed solution no. 2

    Since the issue with virtualenv is a Python problem, we can implement another language called for example python-local-env that would prepend the PATH env var with the absolute path to a folder holding python interpreter that is executing pre-commit code.

    os.environ['PATH'] = os.path.dirname(sys.executable) + os.pathsep + os.getenv('PATH', '')
    

    Of course we need to consider reverting the change made to PATH env var after the hook finishes.

  8. asottile commented on Nov 20, 2021

    @asottile
    Member

    the answer is still no, language: system is "I will make sure things are set up properly" and is the unsupported path

  9. locked as off topic and limited conversation to collaborators on Nov 20, 2021
  10. asottile commented on Nov 20, 2021

    @asottile
    Member

    and in the future, please do not bump year-old threads with off topic comments

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions