how to run a script using pyproject.toml settings and poetry?

Question:

  1. I am using poetry to create .whl files.
  2. I have an ftp sever runing on a remote host.
  3. I wrote a python script (log_revision.py) which save in a database the git commit, few more parameters and in the end send the the .whl(that poetry created) to the remote server ( each .whl in a different path in the server, the path is save in the db) .

At the moment I run the script manually after each time I run the poetry build commend.
I know the pyproject.toml has the [tool.poetry.scripts] but i dont get how can i use it to run a python script.

I tried

[tool.poetry.scripts]
my-script = "my_package_name:log_revision.py

and then poetry run my-script but I allways get an error
AttributeError: module 'my_package_namen' has no attribute 'log_revision'

1. can some one please help me understand how to run to wish commend?

as a short term option(with out git and params) i tried to use the poetry publish -r http://192.168.1.xxx/home/whl -u hello -p world but i get the following error

[RuntimeError]                                 
Repository http://192.168.1.xxx/home/whl is not defined  

2. what am i doing wring and how can i fix it?

would appricate any help, thx!

Asked By: helpper

||

Answers:

At the moment the [tool.poetry.scripts] sections is equivalent to setuptools console_scripts.

So the argument must be a valid module and method name. Let’s imagine within your package my_package, you have log_revision.py, which has a method start(). Then you have to write:

[tool.poetry.scripts]
my-script = "my_package.log_revision:start"

Here’s a complete example:

You should have this folder structure:

my_package
├── my_package
│   ├── __init__.py
│   └── log_revision.py
└── pyproject.toml

The content of pyproject.toml is:

[tool.poetry]
name = "my_package"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.8"

[tool.poetry.scripts]
my-script = "my_package.log_revision:start"

[build-system]
requires = ["poetry_core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

and of log_revision.py:

def start():
    print("Hello")

After you have run poetry install once you should be able to do this:

$ poetry run my-script  
Hello

You cannot pass something to the start() method directly. Instead you can use command line arguments and parse them, e.g. with pythons argparse.

Answered By: finswimmer

Tinkering with such a problem for a couple of hours and found a solution

I had a task to start the django server via poetry script.

Here are the directories. manage.py is in test folder:

├── pyproject.toml
├── README.rst
├── runserver.py
├── test
│   ├── db.sqlite3
│   ├── manage.py
│   └── test
│       ├── asgi.py
│       ├── __init__.py
│       ├── __pycache__
│       │   ├── __init__.cpython-39.pyc
│       │   ├── settings.cpython-39.pyc
│       │   ├── urls.cpython-39.pyc
│       │   └── wsgi.cpython-39.pyc
│       ├── settings.py
│       ├── urls.py
│       └── wsgi.py
├── tests
│   ├── __init__.py
│   └── test_tmp.py
└── tmp
    └── __init__.py

I had to create a file runserver.py:

 import subprocess                                                               
                                                                                   
  def djtest():                                                                   
      cmd =['python', 'test/manage.py', 'runserver']                                                                 
      subprocess.run(cmd)                                                    

then write the script itself pyproject.toml:

[tool.poetry.scripts]                                                           
dj = "runserver:djtest"  

and still make changes to pyproject.toml:

[tool.poetry.scripts]                                                           
dj = "runserver:djtest"

only then command poetry run dj started working

Although the previous answers are correct, they are a bit complicated. The simplest way to run a python script with poetry is as follows:

poetry run python myscript.py

If you are using a dev framework like streamlit you can use

poetry run streamlit run myapp.py

Basically anything you put after poetry run will execute from the poetry virtual environment.

Answered By: DaveR

For future visitors, I think what OP is asking for (a post build hook?) isn’t directly supported. But you might find satisfaction from using a tool I wrote called poethepoet which integrates with poetry to run arbitrary tasks defined in the pyproject.toml in terms of shell commands or by referencing python functions.

For example you could define something like the following in your pyproject.toml

[tool.poe.tasks.log_revision]
script = "my_package.log_revision:main" # where main is the name of the python function in the log_revision module
help   = "Register this revision in the catalog db"

[tool.poe.tasks.build]
cmd  = "poetry build"
help = "Build the project"

[tool.poe.tasks.shipit]
sequence = ["build", "log_revision"]
help     = "Build and deploy"

And then execute and of the tasks with the poe CLI like the following which will run the other two tasks in sequence, thus building your project and running the deployment script in one go!

poe shipit

By default tasks are executed inside the poetry managed virtualenv (like using poetry run) so the python script can use dev dependencies.

If you need to define CLI arguments or load values into a task from a dotenv file (such as credentials) then this is also supported.


Update: poetry plugin support

poethepoet can now support post build hooks when used as a poetry plugin. For example when using poetry >=1.2.0b1 you can configure the following to run your log_revision task automatically after poetry build is run:

[tool.poe.poetry_hooks]
post_build = "log-revision"

[tool.poe.tasks.log-revision]
script = "scripts:log_revision"
Answered By: Nat
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.