cookiecutter / cookiecutter-django

Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.
https://cookiecutter-django.readthedocs.io
BSD 3-Clause "New" or "Revised" License
12.01k stars 2.88k forks source link

Poetry support #3371

Open caniko opened 2 years ago

caniko commented 2 years ago

Description

The requirements.txt + pip is, IMHO, outdated. Instead, Poetry should be used, for proper package management.

Implementation

No poetry project

Automated poetry init when running cookiecutter https://github.com/cookiecutter/cookiecutter-django.

Existing poetry project

Base:

cat base.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add

Local:

cat local.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add -D

Production:

cat production.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs -n1 poetry add -E production

Rationale

Why should this feature be implemented? Random article that I found.

browniebroke commented 2 years ago

This is quite similar to #1988 except this is restricting the problem (lock your dependencies) to a specific solution (Poetry). I really like Poetry and use it in my personal project, so that would be really nice to have, but since there are at least 2 other strong alternatives (pip-tools/pipenv), I suggest to keep the discussion there.

One thing that would really help in adopting Poetry is the dependency group feature coming up in version 1.2 (currently in alpha).

A challenge in adopting more advanced package mangers like this is keeping the cookiecutter template up to date. Currently, we use PyUp but we would need to confirm whether it works with Poetry and if we can use templated pyproject.toml.

If it's not supported, we could run the commands you suggest in post-generation hook to generate the pyproject.toml from the existing requirements files... A similar approach could be used for other package managers.

Andrew-Chen-Wang commented 2 years ago

Has anyone tried using poetry with large projects? Or just the base cookiecutter-django template? As much as a lock file is useful, poetry's super slow, especially larger projects. I wouldn't be opposed to offering multiple package managers (ie an option to use pip, poetry, etc).

caniko commented 2 years ago

Has anyone tried using poetry with large projects

I don't see how this is relevant, as the packages required by cookiecutter aren't that many. Making it not so large, imho. If it was relevant, I'd say poetry is more than capable, as I have had projects with 70+ packages run just fine with poetry.

poetry's super slow

What do you need speed for in a development scenario? Not that it matters, but poetry is not slow.

package managers (ie an option to use pip, poetry, etc).

Poetry uses pip, but yes, there are other package managers that try to compete with poetry. I don't use them, but they should be supported. I don't see how this is relevant, as adding support should be simple.

Furthermore, I have already moved all my dependency management in my cookiecutter project to Poetry. Even if support is never added, it is incredibly easy to port a project with requirement.txt to poetry; annoying, but easy.

Andrew-Chen-Wang commented 2 years ago

Has anyone tried using poetry with large projects

I don't see how this is relevant, as the packages required by cookiecutter aren't that many. Making it not so large, imho. If it was relevant, I'd say poetry is more than capable, as I have had projects with 70+ packages run just fine with poetry.

It's a precursor to the speed issue. Also, regardless of the number of packages, when working in a large team that constantly changes the toml file and we're all using docker, caching becomes an issue as well. But I digress; poetry should be an option anyway.

poetry's super slow

What do you need speed for in a development scenario? Not that it matters, but poetry is not slow.

So I don't have to wait several minutes to add a package? Apologies, but not everyone has better-than-McDonalds wifi (and personally when I want to get a new feature in but it requires a new package, I don't want to shift focus temporarily to a bug for 5 minutes before shifting my focus back to working on the new feature). Poetry's dependency resolver is the slowest portion, and there are several GitHub issues in the poetry repo of arguments on how to fix it. I enjoy poetry update as it removes the need for something like dependabot, but having to wait 3-5 minutes to add a package, 7 minutes to upgrade a crucial package that's core to several others like PyJWT, and 10 minutes to update (on average across multiple repos) is a deal breaker for me at the moment.

package managers (ie an option to use pip, poetry, etc).

Poetry uses pip, but yes, there are other package managers that try to compete with poetry. I don't use them, but they should be supported. I don't see how this is relevant, as adding support should be simple.

Furthermore, I have already moved all my dependency management in my cookiecutter project to Poetry. Even if support is never added, it is incredibly easy to port a project with requirement.txt to poetry; annoying, but easy.

Yea, it's annoying, and that's why I'm not objecting to adding an option since poetry is like the python3 in the python 2->3 transition. And it's relevant since I'm assuming an issue like this would sprout a PR that more than likely would ignore the other package managers. cookiecutter-django is kinda opinionated and only mainly supported by one maintainer, but more options is nice and usually forgotten.

caniko commented 2 years ago

This seems to be a very passionate subject for you, I really didn't mean to hit a nerve. I wanted to keep the discussion limited to ways to implement support, and not discuss Poetry's limitations in terms of speed. Those that use Poetry are already familiar with its speed.

Opinion:

Hope we can move on. Thank you

luzfcb commented 2 years ago

I don't use poetry. I've tried it a few times, but I haven't studied it deeply to the point that my employer and I have adopted it, so I don't have an opinion on how good or not the use of poetry is in the real world. I don't know where the corn hurts.

I have two concerns:

Question: Would a step-by-step tutorial teaching how to migrate to poetry a project generated via cookiecutter-django help alleviate the problem?

caniko commented 2 years ago

These concerns are legitimate indeed. I will try my best to alleviate the two mentioned here.

  1. The questionnaire during the initialization of a cookiecutter django project should stay mostly the same. Moreover, the arguments from the existing CLI can be passed directly into poetry init, docs here. I would say it puts close to no extra load on maintenance, since the poetry init integration is ad-hoc to the rest of the code.
  2. Auto update is very easy with poetry: poetry update. You can revert using your VCS followed by poetry install. You can even do poetry update --dry-run to see what would be updated. Not sure how this would be implemented on the cookiecutter stack, considering PyUp has no pyproject.toml support, maybe wait for this to be solved. Seems like Pydantic had the same issue back in 2018.

To answer the final question, I think it will be a rubber band, the auto update seems to be problematic. A method to go from requirement.txt files to pyproject.toml; I would refer you to the first post in the issue.

Andrew-Chen-Wang commented 2 years ago

hit a nerve

Sorry, I just don't write very professionally or respectfully so excuse me 😅 Will work to improve plus thanks for suggestions!

I'm just concerned we're fully replacing the requirements files with poetry. I'd rather make it an option than fully replace if that makes what I previously said clearer.

auto update

We can work around this. Anytime an update occurs with PyUp, we can push a commit to the pyup branch that changes the TOML file's Python requirements. It should be trivial as we just read line by line in the TOML file (hopefully there are no differences in package naming syntax that I'm unaware of). Especially since it's our template, we'll know beforehand what "sections" are included in the TOML file so there's no chance to screw up over arbitrary section names.

Edit: actually you're right, poetry update package is prob better. We just need to know the package name in its exact format.

browniebroke commented 2 years ago

I think we should not underestimate that the template has a number of combinations with which one may use poetry, pip (or something else): non-docker vs docker, Heroku vs other. We need to integrate each package manager with the various places, which means to have the appropriate branches everywhere is needed:

 {% if cookiecutter.package_manager == "poetry" %}
 poetry install
 {% else %}
 pip install -r requirements/local.txt
 {% endif %}

Then, when the template needs to be updated (package/python version, Docker version, Poetry version....) or added (new package), maintainers will sometimes have to test each separate package manager to deploy to prod, this takes time, which I wouldn't call "close to no extra load on maintenance".

To make maintenance easier, we'll definitely to add an extra job in the CI workflow dedicated to that (what happens if dependencies can no longer be resolved after an update?).

Auto update is very easy with poetry: poetry update

Again, this might work great with the generated project, but it doubt that it'll work in the context of the template (Jinja tags all over the place might make the toml invalid, I think).

Andrew-Chen-Wang commented 2 years ago

I think for the template, it might be easier if we run a post-gen hook that runs poetry install rather than save a huge lock file for the template. All that's left is the TOML file itself. Again, we can do some parsing to identify the package that we want to change in the TOML file based on the package that changed in the requirements file.

Andrew-Chen-Wang commented 2 years ago

I'd like to make a quick test script. If anyone can make a quick pyproject.toml and a lock file where there are multiple groups/envs (ie local and prod), that'd be great. Thanks! It doesn't need to have everything, but stuff like psycopg2 in all it's forms for prod and local would be helpful.

Gkaster commented 1 year ago

I'd like to make a quick test script. If anyone can make a quick pyproject.toml and a lock file where there are multiple groups/envs (ie local and prod), that'd be great. Thanks! It doesn't need to have everything, but stuff like psycopg2 in all it's forms for prod and local would be helpful.

as example cool cookiecutter django project with poetry (with docker/+compose) pyproject.toml

starascendin commented 1 year ago

can someone pls make this poetry version. Its such a pain in the ass to migrate this to poetry

Andrew-Chen-Wang commented 1 year ago

Thanks @Gkaster I simply haven't worked with poetry that much. In my opinion, a simple solution would be the post-gen hook idea where we first generate the necessary requirements, paste them into a pyproject.toml file, and generate a lock file if use_poetry=True.

is there anything I'm missing here? I don't think it's a good idea to be making jinja template comments in the lock file itself due to huge numbers of dependencies.

@starascendin any explanation for why this is a pain? Could you make a PR or provide the usual steps it takes?

dqunbp commented 1 year ago

Description

The requirements.txt + pip is, IMHO, outdated. Instead, Poetry should be used, for proper package management.

Implementation

No poetry project

Automated poetry init when running cookiecutter https://github.com/cookiecutter/cookiecutter-django.

Existing poetry project

Base:

cat base.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add

Local:

cat local.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add -D

Production:

cat production.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs -n1 poetry add -E production

Rationale

Why should this feature be implemented? Random article that I found.

For local and production need to grep to exclude -r options

cat local.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs poetry add -D
cat production.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs -n1 poetry add -E production
manavm1990 commented 1 year ago

Description

The requirements.txt + pip is, IMHO, outdated. Instead, Poetry should be used, for proper package management.

Implementation

No poetry project

Automated poetry init when running cookiecutter https://github.com/cookiecutter/cookiecutter-django.

Existing poetry project

Base:

cat base.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add

Local:

cat local.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add -D

Production:

cat production.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs -n1 poetry add -E production

Rationale

Why should this feature be implemented? Random article that I found.

For local and production need to grep to exclude -r options

cat local.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs poetry add -D
cat production.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs -n1 poetry add -E production

cat requirements/base.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add

cat requirements/local.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs poetry add --group dev

cat requirements/production.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs -n1 poetry add -E production

I have updated above to include requirements directory 📁 in the command for ease of copy/paste.

I also changed -D to be --group dev to avoid the warning the pops up. That is all.

triat commented 7 months ago

cat requirements/base.txt | grep -E '^[^# ]' | cut -d= -f1 | xargs poetry add

cat requirements/local.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs poetry add --group dev

cat requirements/production.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d= -f1 | xargs -n1 poetry add -E production

I have updated above to include requirements directory 📁 in the command for ease of copy/paste.

I also changed -D to be --group dev to avoid the warning the pops up. That is all.

Regarding this, here is a version that takes the version into account (changing the cut -d= -f1 part):

cat requirements/base.txt | grep -E '^[^# ]' | cut -d ' ' -f1 | xargs poetry add
cat requirements/local.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d ' ' -f1 | xargs poetry add --group dev
cat requirements/production.txt | grep -E '^[^# ]' | grep -vE "^\-r" | cut -d ' ' -f1 | xargs -n1 poetry add -E production
Eraldo commented 5 months ago

I wrote my own script to do the reverse and then realized that poetry already has an export command: Source: https://python-poetry.org/docs/cli/#export 🙈 Example: poetry export -f requirements.txt --output requirements.txt This can be used to automatically generate the requirements files for backwards compatibility. :)

Eraldo commented 5 months ago

I also want to mention the relevant PyUp issue: https://github.com/pyupio/pyup/issues/332