utkarshgupta137 / atom-formatters-python

Python Formatters for Atom Editor

Home Page:https://atom.io/packages/formatters-python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support pyenv?

futursolo opened this issue · comments

Currently formatters-python supports setting a global binary path or relative to project dir.

However, I am using pyenv and pyenv puts all virtualenvs inside ~/.pyenv/versions/.

I have tried to set the global binary to ~/.pyenv/shims/isort and end up getting:

formatters-python: /Users/futursolo/.pyenv/shims/isort,--quiet,--settings-path,/path-to-my-project/pyproject.toml,"/path-to-my-project/test.py"

pyenv: isort: command not found
formatters-python: /Users/futursolo/.pyenv/shims/isort,--quiet,--settings-path,/path-to-my-project/pyproject.toml,"/path-to-my-project/test.py"

The `isort' command exists in these Python versions:

I tried to invoke this from within shell and it gets me the expected result.

I saw some other projects uses the %PROJECT_NAME to help on deciding the binary path.

Technically shims should work as-is if current working directory of the command is set to the root directory of the project.

It would be nice if formatters-python could support %PROJECT_NAME in binary path or invoke command inside project root.

Hey, are you sure this is not related to PATH issues? I haven't used pyenv so I don't know much about it.

Yes. It does not have anything to do with PATH. pyenv determines which virtualenv to activate by current working directory.

In the meantime, I was able to put together a shim to workaround the issue in a fairly stupid way by attempting to look for a project dir in args and pass it to pyenv as environment variables.

Hope this helps.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from typing import Optional
import sys
import subprocess
import pathlib
import os

exec_name = pathlib.Path(sys.argv[0]).name. # either save as the binary name or ln -s

shim_dir = pathlib.Path("~/.pyenv/shims/").expanduser()

projects_dir = pathlib.Path("/path-to-my-projects/")


def find_project_dir() -> Optional[str]:
    for arg in sys.argv[1:]:
        if arg.find("/") == -1:  # unlikely to be a path
            continue

        path = pathlib.Path(arg).resolve()
        try:
            rel_path = path.relative_to(projects_dir)

        except ValueError:
            continue

        try:
            proj_name = rel_path.parts[0]

        except IndexError:
            continue

        return str(projects_dir / proj_name)

    return None


def main() -> None:
    bin_path = shim_dir / exec_name
    env = dict(**os.environ)
    project_dir = find_project_dir() or "/"

    env["PWD"] = project_dir
    env["PYENV_DIR"] = project_dir # shouldn't need this if no-shell were spawned before Python shim is called.
    del env["PYENV_VERSION"] # shouldn't need this if no-shell were spawned before Python shim is called.

    proc = subprocess.run(
        [str(bin_path), *sys.argv[1:]],
        cwd=project_dir,
        env=env,
        stdin=None,
        stdout=None,
        stderr=None,
        check=False,
    )

    sys.exit(proc.returncode)


if __name__ == "__main__":
    main()

Hey, I've pushed a commit to pass cwd to the atom BufferedProcess,
Can you test it to see if it is working?

Steps:

  • clone this repo
  • cd into it
  • npm i
  • apm link
  • restart atom

Yes, it works perfectly.

Thank you for the fast fix!

Nice. Are you aware of any other environments which will need the same change?

No, I am not aware of other environment that has the same behaviour. Sorry about that.

Fixed with v1.2.1