-
Notifications
You must be signed in to change notification settings - Fork 147
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
The difference between setup.py (pyproject.toml) and requirements.txt (Pipfile) #27
Comments
Indeed, they don't have to, since for building/installation |
In contrast to PHP and JS Ruby/Bundler has
For libraries that are consumed by others and published on the repository you would use Cargo has both package and binary specifications in the same file similar to JS with
CocoaPods also uses a this split with
I'm not involved with this project, but I suspect this is roughly what the aim is |
@iamale - The difference is explained here: https://caremad.io/posts/2013/07/setup-vs-requirement/ |
@nchammas Yes, I've read that. It doesn't explain why we need two separate formats, though. |
So you're saying you understand the different roles these two files play but you don't see why they can't be captured in the same file? I thought @dstufft's post explained why clearly:
A project can only have 1 set of abstract dependencies ( So if project You can't merge these two types of dependencies together into one file without hampering people's ability to choose where to get their dependencies from. Does that clarify why |
To provide a really practical example, I have a project at work where we do a few things.
This project is for some integration so its requirements might be complicated than others, but generally, keeping app requirements you need in setup.py and runtime or deployment requirements in requirements.txt ends up helpful for the simple reason you can use pip flags in requirements.txt. |
@nchammas Thanks for the clarification! So basically, the workflow now is:
Did I get it right? What happens if # Car's Pipfile
with source("https://super-secret-cheeseshop.pythonlabs.com/", verify_ssl=True):
package("Engine", ">=1.0.0") # Engine's setup.py
setup(
name="Engine",
version="1.0.0",
packages=["engine"],
) At some point Engine's author decides to update it: # Engine's new setup.py
setup(
name="Engine",
version="1.1.0",
packages=["engine"],
install_requires=["Cylinder >= 1.1"],
) Now we do |
That's a good question. I'm not sure what the answer is, but we could probably find out by testing this scenario with @dstufft / @ncoghlan: If I instruct pip to install a package from a specific source (e.g. a private index), does it automatically try to install all that package's dependencies from the same source? Or would it grab just the specifically mentioned package from the private index, and everything else. including dependencies of that package, from the default source (PyPI)? |
I'm confused by this too, but I understand things a bit differently: Old world:
New world:
I wish abstract dependencies could be in the same place, in the same (non-Turing-complete) format for both libraries and applications. |
@nchammas pip (requirements.txts) does not currently support specifying where a specific package comes from. It just lets you specify globally your set of indexes. |
May be I am missing something but this discussion doesn't answer the question "what can go wrong if you'll put your app's concrete dependencies in setup.py and you don't have abstact ones". Not a good practice. Abstract matters. It is still not enough for data duplication in my opinion.
Why do we need "abstract" deps if app is not supposed to be imported in other projects and to be uploaded to public PyPI (because it is private app)? It is not a problem to deploy it from private PyPI as well.
Different sets of dependencies (dev/ops) can be resolved with I agree that setup.py is a bad place for index url. Index is more related to infrastructure than to code. So it could be provided externally with Ansible / SALT etc. May be someone has real use case where just setup.py was a problem. Please share it. |
@askabelin If a project isn't meant to be importable, you don't need a setup.py at all, and can just use requirements.txt or a Pipfile. Yes, a setup.py can be used for the application-or-service use case, but the extra complexity isn't typically needed in such cases, and may give folks the misleading impression that the component is intended to be usable as a library. |
Unless OP (or someone else) has any more questions regarding why there's a proposal to have 3 separate files in the Python Packaging System to manage dependencies, let's close this issue. |
I'm going to go ahead and close this. There doesn't seem to be anything actionable here. If I'm wrong please speak up or open another issue, thanks. |
@k0nserv : You mentioned there being a Can you help clear up my confusion? If it's true that there's no equivalent to those files in Cargo, that seems like a signal that we may wish to analyze. Cargo's constraints are different enough from ours that there might be some reason that we need the distinction, but if the designers of Cargo, having already lived with the design of This article on the gem files, as well as this comment from @dstufft about the utility of the split, makes sense to me. I just wonder if there's something that the folks that made Cargo know that we don't, and what they'd recommend to us. http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/ |
@ryanhiebert Yes you are correct. Rust and Cargo uses |
One of the folks that made Cargo is the person who wrote that article :) One of the main differences though is that there isn't really a runtime declaration with Cargo. Everything is build time and Cargo produces a static binary. That changes the math a bit. |
Yeah, I knew that he was involved with Cargo, which seems like it may be evidence that we need to consider that choice, since Cargo was made well after that post was written. Since he knew the benefits and pitfalls of using it in Ruby at the time, his choice to not replicate it for Rust means something to me. It makes sense to me that the compilation nature of Rust could change the math, but I haven't come up with how it changes it. It seems like virtually all of the reasoning that we have behind doing the three-file approach still applies, even to Rust. My own reasoning at the moment really wonders if having Thus, my own thinking makes me think that the split is a good thing. I wonder if we could get @wycats to comment on the factors that lead to the decision that Cargo made. Perhaps for Cargo several of the things that are constraints for us were deemed unnecessary. If enough of our reasons for keeping them separate were deemed of enough less utility for Cargo, then the overhead of an extra file may have been enough to decide to take the bad with the good, and skip the added file. |
Since it's much easier to add features than it is to remove them, I'd advise any new packaging system to start with a single file the way Rust has, and then use experience-driven-pain to decide whether or not they need anything more complex than that. For the specific case you gave, it seems that Rust has first class "example application" support built (http://doc.crates.io/manifest.html#examples) and otherwise requires that applications and libraries by laid out differently (http://doc.crates.io/manifest.html#the-project-layout). It also has workspaces to more explicitly manage scenarios where projects are developed and published as multiple crates in a single repository: http://doc.crates.io/manifest.html#the-workspace-section The big difference in Python is that we have two rather distinct problems to solve:
As a new ecosystem, Rust had the luxury of imposing |
I think that's the motivation I was looking for. Makes perfect sense to try a more limited approach first, then expand if necessary. Thank you. Clearly, Python is way past that already. |
I followed up with a concrete proposal in #98 that I believe gives us something actionable and pragmatic that could improve DX for maintaining Python libraries. |
Why there even needs to be one? In PHP (Composer) and JS (npm, yarn), there is only one file type and libraries and applications work OK with these — libraries just don't need to commit their lockfile.
There is a difference between an application and a library, but on the pip's end, it's just a bunch of dependencies with versions specified.
The text was updated successfully, but these errors were encountered: