I recently built a Python library for the first time in a while, and to make it available in PyPI I followed the official Python packaging guide. But it turns out there’s some rough edges in the suggested tools.
Namely, the build backend hatch puts all the files in the project directory into the built sdist, except from some files it chooses to exclude, which led to a gitignored file as well as VCS metadata getting packaged and uploaded to PyPI. This really surprised me, and I think most Python users new to packaging would be better served by choosing a conservative build backend like uv_build, which puts only the Python source modules and some specific project-level files into the sdist.
This doesn’t explain that hatch will package everything in the project directory by default. As a new user making a package, why would you think to look for hatch configuration options?
I mentioned in the article (maybe you don’t read that carefully?) that hatch can be configured to do what you need, but if you’re just following the packaging guide, which doesn’t mention this behavior or provide any kind of heads up to new users, you won’t be aware that it is going to even try to look at a directory like
.jj. And why would it? I wouldn’t expect a compiler or a tool like Maven to look at files that aren’t needed to build the project. Why does hatch?Your demonstration just shows if you’re already aware of the problem and you know the cause of the problem, you can find a solution. I say as much in the article and agree with the point. The point of my article is this is surprising default behavior and it’s better to just use a tool that has sensible defaults.
I wouldn’t try to follow hunches on how tool that has extensive and accessible documentation works, your novice is a strawman that has expectations but unable to do anything for some reason. So he should completely change the workflow.
Nothing personal, I liked your article in general, but pretending that default is all there is isn’t great way to frame it, you could have linked relevant documentation and provided a snippet on how it should be done instead of dismissing it entirely, because default doesn’t meet your expectations