-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tasks #591
Add tasks #591
Conversation
Placing these in
|
@jacebrowning Personally, I'd rather have |
On another note, if I understood it correctly this is also some direction the @tox-dev team wants to go, i.e., general automation. Is it really necessary for poetry to also include this functionality, then? |
@ZeeD26 even though @tox-dev is working on similar features does not mean we should not implement it for Poetry, indeed not everyone uses Tox and adding it ot a project for the sake of tasks sounds overkill to me. @jacebrowning I would also prefer such syntax but I am very worried about the aliasing it could involve, maybe it would not be that bad though (@ZeeD26 you may still run the One other "issue" with [tool.poetry.dev-scripts]
foo = 'foo:main'
test = { task = "pytest tests/" } This might get pretty cumbersome 🤔 |
I'm really looking forward to see this feature merged. Most of the time adding a Makefile to a small project feels like too much, but I still want to have the commands documented, and it's much easier to keep it up to date if I use them constantly instead of writing them once in the README and forgetting. It would be awesome if I could just remember I really like the way E.g: {
"scripts": {
"build": "node build.js"
}
} and then This could be really useful. If I redefine |
I would really like this feature. Having this built in makes it easier to share knowledge amongst developers when adopting poetry as a tool of choice for dependency management on a project. Do not mind if it's Thank you @michaeldel |
What's the status of this? Do you need any help on getting this done? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are conflicts in the PR that need to be resolved
I was able to merge the current master in this branch without any conflicts (the particular part in @michaeldel I opened a pull request on your tasks branch with the updates. |
Codebase has been updated, also resolved conflicts. |
Is there any documentation available on this implementation yet? So far it's not clear if we ended up using |
It would be nice to have this instead: [tool.poetry.dev-scripts]
foo = 'foo:main'
test = { task = "pytest tests/" } Makes it easy to remember being able to reuse I think |
@Kamforka there is minimal documentation in cli.md. At the moment the section used is still The subcommand name (currently
Implementing tasks that way (using the @woile of course |
@michaeldel do you mind update |
I'd rather direct people to use Makefiles, which are cross-language compatible, than to build yet another language-specific task runner. Unless poetry is managing python versions as well (with pyenv) then I'll still have to have a Makefile anyway. But yeah I don't know about windows support. |
What's with the holy crusade of trying to teach everyone about Makefiles? We get it, they've been around since early 1970s. They solve some problems, most of those problems have been solved again by many other tools many more times since then. If you want to use Makefiles they will give you a gun and enough rope to shoot / hang yourself with, whichever you prefer. |
@erksch I am taking care of it as soon as I got time, in some days probably. @brycedrennan |
@michaeldel yeah good points. I’ve got no answer for windows support so I must admit this will be helpful for a lot of projects. |
Unfortunately I'm also doomed to develop under Windows and deploy to Linux and I know a lot others who have to deal with this. Having |
@hangtwenty Important is the difference between something like a make, invoke or shovel task and the proposed tasks we (or I) would like to have in poetry. I would write a shovel task for something like seeding my database or setting up constraints or whatever but I would not want to write a shovel task for executing my tests or linting my code. The difference is that the first ones are tasks and the second ones are convenience aliases for executing a tiny bit of code. And why would adding scripts to the toml result in a mess? Making task runner tasks for everything would be the greater mess. |
I'm not sure if everyone is actually scared of a result that would look like this. And even if that is the case you'd just move that mess from the pyproject.toml to another file depending on what task runner you use. I do agree with @erksch on the fact that these scripts/tasks are mostly aliases. As soon as the scripts/tasks become complicated they are moved to different files (see the npm example). I think the dream of yarn and npm is that you can start developing simply after running If I want to test I need to know the testing library that the repository uses, if it is pytest I run Now the same steps happen when i want to lint. Does the project use prospector? or simply pylint? Now the alternative solutions that are suggested are:
|
@erksch You mention aliases - I understand what you mean but then let’s compare to aliases in shell scripting. In bash for example aliases can still have further arguments added to them. Would pyproject.toml aliases support that? Or do people have to create redundant aliases with slight variations? Or start using environment variables a bunch? Would pyproject.toml tasks be able to call each other? Do we want to deal with pyproject.toml tasks calling multiple layers of “poetry run” subshells (and does that have any weirdness to consider?) These questions are answerable but the point I’m trying to make is that aliases are not as simple as you are implying. They only seem simple to you because they are your personal preference. To others of us, this kind of hardcoding of shell invocations into text is not simple. Instead it proliferates custom work. It does not have less cognitive overhead than the alternative(s), it’s just less consistent. Contrast with the case where the tasks are executed by a well-defined task runner or sure you can do your own custom approach visible right there. Either way people don't start digging into poetry when they need to debug. The dig into the thing they chose. It's more explicit, and explicit is better than implicit in Pythonic code. Also I’m not trying to get tit for tat, my higher-level point here is that any approach to this should probably be considered slowly and carefully. |
The issue #940 could be widely useful regardless of whether there is something like pyproject.toml in-line classes. So then why not do that first, and see how it goes, and let this incubate - instead of immediately adding more semantics to the pyproject.toml? |
@Askir It looks like something needs clarifying. You said
What do you mean? I mentioned the example of Per #940 this would be a general concept for running entrypoints. It could be implemented almost trivially, i.e. if So you may have thought I was suggesting a way to glue a specific task runner to poetry. There is no magic and there is no 'behind-the-scenes' to understand. Literally the only difference from current behavior is that you could save typing three characters. To further illustrate the point,
Those examples so far are Python entrypoints. it'd probably make sense if it just worked for anything
and so on. |
I only used http://docs.pyinvoke.org/en/1.2/concepts/configuration.html#setup It's just Using http://pydoit.org/usecases.html#simplify-cumbersome-command-line-calls lint = "black --check ." 👇 # dodo.py
def task_lint():
return {'actions': ['black --check .']}
Here is another example, implementing all of the OP's tasks with aliases = dict(
lint = ["black --check **/*.py"],
test = ["pytest tests/"],
dev = ["FLASK_APP=app.py flask run"],
start = ["gunicorn app.wsgi --log-file -"],
clean = ["poetry run manage.py flush", "rm -rf media"]
)
# small bit of boilerplate, this is a way that doit lets us generate task functions.
# http://pydoit.org/task_creation.html#custom-task-definition
class Aliases(object):
@staticmethod
def create_doit_tasks():
return (({'actions': actions, 'basename': name, 'targets': [name]}) for name, actions in aliases.items()) Even though there is that bit of boilerplate, don't lose sight of the important part: once any one of your tasks outgrows hardcoded-string-aliases, you can use the full features of your chosen task-runner. Personally I don't care about 'one-liners' so I'd make them all "real" tasks from the start. But that's the thing ... I can make the choices for my project, and you can make your choices. In both examples given, Yes Poetry can, and should be, opinionated about some things. This is an opinionated stance too, and it encourages users of poetry to keep their dev tasks cohesive. That means you don't have a split between your stringy tasks and your "real" tasks when your needs get complicated. TLDR ... modular / separation of concerns / tools doing their primary things well. Poetry doesn't have to reinvent any wheels for this -- or at least we can address #940 now (simple) and consider doing other things later. |
it seems the people who proposing alternative solutions (make, pyinvoke, pydoit, etc) not following the main motivation behind this idea -- to avoid having extra dependencies or extra files in project for this more than trivial purpose |
i don't see any value in this proposal for poetry, but only maintenance cost. |
Can we merge this code please? This feature is a big part of why I fell in love with NPM/Yarn, and I really need it to help onboard my team with a minimum of cognitive burden. No, I will not be teaching them to use make. Ever. Anyone saying to use other tools please ask yourself whether you've actually made a PR on this project, and if the answer is no, go ahead and defer to and support the folks who have contributed code or have a genuine vision for what this project can do if it defies the pythonic status quo. The old pythonic ways lead to stagnant, schizophrenic designs, high cognitive loads, and incredibly slow progress. To wit, we have been flogging this issue for over half a year using meaningless and counterproductive rationale such as pythonicity and "do one thing and do it well", when in fact this feature and a complementary cluster of others were already solved and integrated into a coherent whole with resounding success in another community over 5 years ago. If you'd like a more genuine opportunity to contribute, stop pulling the handbrake on this project and go triage issues on the tools you're recommending. I assure you they exist. And are miserable, if you dare face them. To conclude my screed, @sdispater are there any gaps preventing the integration of the current PR? If so, what are they? Can we move forward here? I'd really like to show this feature to the team :) |
@maxsu Regardless of the issue at hand, reserving this sort of toxicity for your self, or, if that is not possible, to communities that may welcome such behaviour would be a great first step towards contributing. |
It would be nice to have a single tool that could “do it all”, I’m not opposed to that in principle but I am opposed to adding features when core functionality isn’t complete. Last I checked (admittedly a few months ago) there were several blockers to rolling poetry out in my corporate environment. (#524 #697 #800). NPM is a great example. It tried to do a lot and was so bad at its core functionality that it had to be replaced by a Yarn. Not the kind of “success” I’d hope for poetry. I also think some people here are underestimating the complexity of task runners. It’s easy to get the simple cases working but we will inevitably also want the more complex cases working. That’s why there are whole libraries to deal with solving that problem. As with any open source software of decent size, there are lots of competing visions for what the software “should” be. It’s generally valuable to have respectful debates about the merits of new features. It’s up to the maintainers, as informed by the input of everyone, to decide what fits the vision. I don’t think it’s productive to tell people with differing opinions they aren’t “genuinely” contributing. I’m hesitant to post my contact info here but it’s pretty easy to find. Id be happy to learn more about your python pain points (outside of this thread) and see if we can find ways to make things easier for your team (for free). I do have a bit of experience with this sort of thing. Let me know! |
Poetry is a package and dependency manager, not a task manager. This feature is beyond the scope and the original purpose of Poetry and will likely never be integrated into it. I want to keep Poetry simple and intuitive so I carefully think before adding new features to the core codebase since the weight of maintaining it will fall on the shoulders of the maintainers. That being said, when the planned plugin system is fully implemented (which will be after the release of the @maxsu I am grateful of anyone willing to take some of their free time to make a PR for Poetry. I really do. However, that does not mean I will blindly accept any PR, especially when they add new features, if they do not align with the purpose of the project. I know this can be sometime disappointing to see your PR rejected after spending time on it but as a project maintainer it's my responsibility to determine what's best for the project. And that means, sometimes, to turn down good and thorough suggestions like this one. @michaeldel Thanks a lot for taking the time to make this PR! I really appreciate it. However, for the reasons mentioned above, I don't think this align with the purpose of Poetry. Nonetheless, like I said this would be a perfect fit for a plugin once the plugin system is ready. So keep an eye on the project for when this will be announced. |
Since this PR probably still get some google traffic I'd like to share a solution I'm working on that solves more or less that same problem as this PR. Poe the Poet a task runner that works well with poetry.Basic usage is quite similar to proposal in this PR, but it also supports defining tasks using shell syntax, as references to python functions similar to scripts, as well as composing tasks into sequences. Besides lightweight configuration contained in the pyproject.toml, one key advantage over alternatives like make is that you can easily pass extra arguments to tasks without extra configuration. Example configuration with different task types: [tool.poe.tasks]
test = "pytest --cov=poethepoet" # simple command based task
mksandwich = { script = "my_package.sandwich:build" } # python script based task
tunnel = { shell = "ssh -N -L 0.0.0.0:8080:$PROD:8080 $PROD &" } # shell script based task Example invocation: # extra argument is passed to the underlying pytest command
poe test -v
# If poethepoet is added as a dev-dependency
poetry run poe tunnel The intention is to eventually have comparable functionality to make wrt task composition, conditional execution, and command line completion. EDIT: also I intend to support poe as a poetry plugin in addition to a standalone tool, once that API is available. |
@nat-n I assume you will turn this into a plugin as soon as that system is ready, correct? 🚀 |
I know a lot have others have already expressed similar sentiments, but I'll just throw in my two cents:
|
This missing feature is honestly the only thing holding me back from moving my team over from pipenv. The fact that this tool doesn't have a simple I honestly don't care if its I know this is already closed, but please add this feature... 😄 |
Poe the poet can now be used as a plugin, including support for enhancing poetry's own commands with hooks! @paulcruse-syn I can understanding the preference for an "all in one" solution, but the plugin workflow is pretty smooth. Though it's still only supported in the beta release of poetry. |
This is an issue with Homebrew, and not with Poetry itself. We do not provide support for downstream repackaging, and indeed, they appear to not install Poetry in a way where This closed PR is not a good place to discuss this or request support -- I'd suggest getting support through Discord/Discussions, and #2496 as the correct place to express support for this proposed feature. Please refrain from any 👍/me too spam -- reacts suffice for that, but please do chime in if you have something novel to add that has not been said already. |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Task
I find it pretty useful for Poetry to be able to run tasks in development, similarly to NPM's scripts (that can be launched with
npm run
).These tasks will not be available in end-user package installation.They are defined in a
tool.poetry.tasks
section, pretty similar totool.poetry.scripts
:And may be run like so
They are automatically run within the project's virtualenv (the same way
poetry run
runs scripts).This new feature should also address some concerns expressed here in #241.
make
is already suited to take care of tasks running but:tool.poetry.tasks
feature will be consistent with the newpyproject.toml
project files.make
still has to be called throughpoetry run
in order to be integrated within the current virtualenv, hence missing the "shorter command" initial benefitCurrent
tool.poetry.scripts
are currently not that well suited for such operations as well, indeed:Use cases
Here are some common use cases where such feature may come in handy.
Lint and test code
Run development or production server
Clean environment
Improvements
I have first chosen
tasks
as name in order not to mismatch tasks with scripts (which can be run from an end-user perspective). It may feel a bit of a duplication among some so these might be renamed to "development scripts" (tool.poetry.dev-scripts
) in order to be consistent (alsopoetry run
probably remains a better command name thanpoetry task
for that sort of thing).It does also currently not support passing arguments to tasks, maybe adding an option for this might be an interesting idea (similarly to
npm run task -- args
).Some other options might also be considered such as
--silent
or--pwd
.Current implementation is of course very rudimentary and will probably be further developed later if merged.
Checklist