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?
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.
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
.bashrc.alias foo=/path/to/project/.venv/bin/foo
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
--projectoption is that this does not seem, atleast not obviously, useful for commands other thanrun. But even then the better solution might be to installscriptsto 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).
- 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/activateYou can then do something like this.
$ poetry shell (.venv) $ cd ~/ (.venv) $ foo --help
- Using an alias (you can add this to your
.bashrc.alias foo=/path/to/project/.venv/bin/foo
- Install as an editable install (YMMV). This is not officially supported by
pipsince editable installs via PEP 517 is not supported. For this you need to add asetup.pyshim.$ echo "import setuptools; setuptools.setup()" > /path/to/project/setup.py $ pip install --user /path/to/projectThis
source $(poetry env info --path)/bin/activateis broken if you usepython 3.5orpython 2, because of the warning about those versions of python being deprecated.
This also fails ifpythondefaults topython2and you installed poetry withget-poetry.py, since the executable haspythonin 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.
Most helpful comment
@noamraph something like this will also work.
And then execute the follwoing within the project context (any sub directory):
Is the requirement here for you to be able to run
fooin a directory outside the project context? Something like this? (Possible proposal.)