Poetry: Ability to specify the directory to run poetry in instead of always using current directory

Created on 13 Mar 2020  ยท  17Comments  ยท  Source: python-poetry/poetry

  • [x ] I have searched the issues of this repo and believe that this is not a duplicate.
  • [ x] I have searched the documentation and believe that my question is not covered.

Feature Request

I'd like to be able to run poetry run X while also setting the current directory to whatever I want. Right now, this appears to be impossible, since I have to set the current directory to wherever my pyproject.toml file is located instead. Can there be a command line option to override this default?

Feature

Most helpful comment

@noamraph something like this will also work.

[tool.poetry.scripts]
foo = "foo.bar.main:main"

And then execute the follwoing within the project context (any sub directory):

poetry run foo

Is the requirement here for you to be able to run foo in a directory outside the project context? Something like this? (Possible proposal.)

poetry --project=/path/to/project-foo run foo

All 17 comments

I did find a workaround though. I created the following helper script:

#!/bin/sh
STARTDIR=`pwd`
cd TOML_DIR
poetry run bash -c "cd $STARTDIR && python -m foo $*"

Where TOML_DIR is the path to the directory with your pyproject.toml

This works well if your module has an if __name__ == '__main__', which isn't precisely what will get created with a [tool.poetry.scripts] specification.

Just in case it helps someone, here's the script I used. It finds TOML_DIR from the location of the executable, so it doesn't need to be hardcoded. It also uses a function, like [tool.poetry.scripts].

#!/bin/sh
STARTDIR=$(pwd)
TOML_DIR=$(dirname "$0")
cd "$TOML_DIR" || exit
poetry run bash -c "cd $STARTDIR && python -c 'from foo.foo import main; main()' $*"

I am a bit unclear on the issue here. Poetry, similar to git, will detect the pyproject.toml as long as the current directory is a child directory.

Here is an example where poetry run is executed within the src directory in the project.

$ tree .
.
โ”œโ”€โ”€ poetry.lock
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ README.rst
โ”œโ”€โ”€ src
โ”‚ย ย  โ”œโ”€โ”€ poetry
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ run
โ”‚ย ย  โ”‚ย ย      โ””โ”€โ”€ context
โ”‚ย ย  โ”‚ย ย          โ””โ”€โ”€ __init__.py
โ”‚ย ย  โ””โ”€โ”€ poetry_run_context.egg-info
โ”‚ย ย      โ”œโ”€โ”€ dependency_links.txt
โ”‚ย ย      โ”œโ”€โ”€ PKG-INFO
โ”‚ย ย      โ”œโ”€โ”€ SOURCES.txt
โ”‚ย ย      โ””โ”€โ”€ top_level.txt
โ””โ”€โ”€ tests
    โ””โ”€โ”€ __init__.py

6 directories, 9 files

$ type pytest
bash: type: pytest: not found

$ cd src/

$ poetry run type pytest
pytest is /tmp/poetry-run-context/.venv/bin/pytest

@noamraph something like this will also work.

[tool.poetry.scripts]
foo = "foo.bar.main:main"

And then execute the follwoing within the project context (any sub directory):

poetry run foo

Is the requirement here for you to be able to run foo in a directory outside the project context? Something like this? (Possible proposal.)

poetry --project=/path/to/project-foo run foo

@abn yes, a --project argument would make our lives much easier in these cases

Yes, exactly. It would be like git's -C option, that allows you to run commands on a repository regardless of your working directory.

@abn I want to describe my use case a bit more. I'm developing a command line script that depends on the working directory. It's actually a tool for working with git repositories, so it detects the repository using the working directory (and it also has a -C option for specifying the repository directory manually). So in order to test the script, I have to be able to run it from different working directories.

@abn I have the same sort of requirement, I am developing a CLI tool for which one of the functionalities is to build docker images. so for that, my working directory should be dir which I want to build my image and I want to remotely run my cli(managed by poetry). --project argument makes things much easier.

The reason why I am not a 100% sold on the --project option is that this does not seem, atleast not obviously, useful for commands other than run. But even then the better solution might be to install scripts to alternative location (user/system site) judging by the above use cases.

This might not be the exact solution for the CLI development case, but here are a few options that might help till a better solution exists. All examples assume snippet from https://github.com/python-poetry/poetry/issues/2179#issuecomment-668825895.

  1. Using the poetry managed virtual environment using one of the following.
poetry shell
source /path/to/project/.venv/bin/activate
source $(poetry env info --path)/bin/activate

You can then do something like this.

$ poetry shell
(.venv) $ cd ~/
(.venv) $ foo --help
  1. Using an alias (you can add this to your .bashrc.
alias foo=/path/to/project/.venv/bin/foo
  1. Install as an editable install (YMMV). This is not officially supported by pip since editable installs via PEP 517 is not supported. For this you need to add a setup.py shim.
$ echo "import setuptools; setuptools.setup()" > /path/to/project/setup.py
$ pip install --user /path/to/project

@abn The issue I will have with the 'poetry shell' method is that my command-line script needs other environment variables outside of poetry's control to launch the tools that my script will use. As soon as I switch to poetry's virtual env, those will get cleared out.

However, running 'poetry install' and then using @noamraph 's solution is ideal.

@bphunter1972 option 1 (using source) or option 2 (usimg alias) above should work in your case, ie. not clear existing variables.

@abn You're right! I don't know how I missed it before, but after 'poetry install' running '/path/to/project/.venv/bin/foo' just works from any directory!

I feel like this should be more clearly documented, but I'm not complaining. Just happy to have resolved this.

Pipenv allows you to do this by exporting PIPENV_PIPFILE=path-to-pipfile before running pipenv run. I would lovo to have the same functionality on poetry.

Having the ability to point to the path of the pyproject provides many advantages.

One example would be to be able to run your scripts from outside the project folder. Lets say we have something like
~/projects/poetryproject which contains script.py and all the poetry files.
I would love to do poetry run ~/projects/poetryproject/script.py, but I cant since I have no way to tell poetry where to find the files it needs.
And this would allow us to have something like pipenv-shebang which is a game changer if you ask me. You can simply add a shebang to your scripts and forget about it being called from and virtual environment.
https://github.com/laktak/pipenv-shebang/blob/master/bash/pipenv-shebang

The reason why I am not a 100% sold on the --project option is that this does not seem, atleast not obviously, useful for commands other than run. But even then the better solution might be to install scripts to alternative location (user/system site) judging by the above use cases.

This might not be the exact solution for the CLI development case, but here are a few options that might help till a better solution exists. All examples assume snippet from #2179 (comment).

  1. Using the poetry managed virtual environment using one of the following.
poetry shell
source /path/to/project/.venv/bin/activate
source $(poetry env info --path)/bin/activate

You can then do something like this.

$ poetry shell
(.venv) $ cd ~/
(.venv) $ foo --help
  1. Using an alias (you can add this to your .bashrc.
alias foo=/path/to/project/.venv/bin/foo
  1. Install as an editable install (YMMV). This is not officially supported by pip since editable installs via PEP 517 is not supported. For this you need to add a setup.py shim.
$ echo "import setuptools; setuptools.setup()" > /path/to/project/setup.py
$ pip install --user /path/to/project

This source $(poetry env info --path)/bin/activate is broken if you use python 3.5 or python 2, because of the warning about those versions of python being deprecated.
This also fails if python defaults to python2 and you installed poetry with get-poetry.py, since the executable has python in its shebang.

Even cd project/path && $(poetry env info -p)/bin/python foo.py works but changing directories all the time is not convenient.
Also imagine such use case: you work in a monorepo and you need to start multiple projects from the same shell script.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  ยท  3Comments

Euphorbium picture Euphorbium  ยท  3Comments

nikaro picture nikaro  ยท  3Comments

AWegnerGitHub picture AWegnerGitHub  ยท  3Comments

sobolevn picture sobolevn  ยท  3Comments