Skip to content

Commit 487f511

Browse files
authored
Deprecate implicit setup.py support (#1897)
Currently if an app has only a `setup.py` file and no Python package manager files (such as `requirements.txt`, `Pipfile.lock`, `Poetry.lock` or `uv.lock`), the buildpack will install the project using `pip install --editable .` However, there is nothing pip-specific about `setup.py` - the file is not a package manager dependency file but instead a setuptools package file, and could easily be installed by any package manager. In addition, some projects may want to install this file in standard rather than editable mode. As such, it's best that the buildpack doesn't guess which package manager and mode to use, and instead we require explicit configuration from the user. For example in the form of a `requirements.txt` file that references the package definition, via this single line in the requirements file: ``` --editable . ``` That said, in general we recommend people don't use `setup.py` to declare their dependencies, since: (a) the file is deprecated in favour of `pyproject.toml` (b) it's intended more for libraries rather than applications, and it's much less common (and practical) to list all transitive dependencies in a `setup.py`, meaning apps using the file typically have unpinned dependencies, which is a production reliability risk. (Apps should either be using a package manager that supports lockfiles, or else using one of the pip requirements files substitutes like pip-tools or `pip freeze` etc). The existing metrics for this fallback show usage to be very low, so we'll likely not wait long before converting this warning to an error (particularly since fixing the error is a case of adding a single line requirements file, so fairly simple). GUS-W-19275438.
1 parent 5dcc5c4 commit 487f511

8 files changed

Lines changed: 47 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Deprecated support for falling back to installing dependencies from a `setup.py` file if no Python package manager files were found. ([#1897](https://github.com/heroku/heroku-buildpack-python/pull/1897))
56

67
## [v306] - 2025-09-09
78

lib/package_manager.sh

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,32 @@ function package_manager::determine_package_manager() {
5757
package_managers_found_display_text+=("uv.lock (uv)")
5858
fi
5959

60-
# TODO: Deprecate/sunset this fallback, since using setup.py declared dependencies is
61-
# not a best practice, and we can only guess as to which package manager to use.
6260
if ((${#package_managers_found[@]} == 0)) && [[ -f "${build_dir}/setup.py" ]]; then
6361
package_managers_found+=(pip)
6462
package_managers_found_display_text+=("setup.py (pip)")
63+
output::warning <<-EOF
64+
Warning: Implicit setup.py file support is deprecated.
65+
66+
Your app currently only has a setup.py file and no Python
67+
package manager files. This means that the buildpack has
68+
to guess which package manager you want to use and also
69+
whether to install your project in editable mode or not.
70+
71+
For now, we will use pip to install your dependencies in
72+
editable mode, however, this fallback is deprecated and
73+
will be removed in the future.
74+
75+
Please add an explicit package manager file to your app.
76+
77+
To continue using pip in editable mode, create a new file
78+
in the root directory of your app named 'requirements.txt'
79+
containing the requirement '--editable .' (without quotes).
80+
81+
Alternatively, if you wish to switch to another package
82+
manager, we highly recommend uv:
83+
https://docs.astral.sh/uv/
84+
EOF
6585
build_data::set_raw "setup_py_only" "true"
66-
else
67-
build_data::set_raw "setup_py_only" "false"
6886
fi
6987

7088
local num_package_managers_found=${#package_managers_found[@]}

lib/pip.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function pip::install_dependencies() {
9090
install
9191
)
9292

93-
# TODO: Deprecate/sunset this missing requirements file fallback.
93+
# Support for the setup.py fallback is deprecated and will be removed in the future.
9494
if [[ -f setup.py && ! -f requirements.txt ]]; then
9595
pip_install_command+=(--editable .)
9696
else

spec/hatchet/package_manager_spec.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,36 @@
4949
end
5050
end
5151

52-
# TODO: Deprecate/sunset the setup.py file fallback.
52+
# This case will be turned into an error in the future.
5353
context 'when there is only a setup.py' do
5454
let(:app) { Hatchet::Runner.new('spec/fixtures/setup_py_only') }
5555

5656
it 'installs packages from setup.py using pip' do
5757
app.deploy do |app|
5858
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
5959
remote: -----> Python app detected
60+
remote:
61+
remote: ! Warning: Implicit setup.py file support is deprecated.
62+
remote: !
63+
remote: ! Your app currently only has a setup.py file and no Python
64+
remote: ! package manager files. This means that the buildpack has
65+
remote: ! to guess which package manager you want to use and also
66+
remote: ! whether to install your project in editable mode or not.
67+
remote: !
68+
remote: ! For now, we will use pip to install your dependencies in
69+
remote: ! editable mode, however, this fallback is deprecated and
70+
remote: ! will be removed in the future.
71+
remote: !
72+
remote: ! Please add an explicit package manager file to your app.
73+
remote: !
74+
remote: ! To continue using pip in editable mode, create a new file
75+
remote: ! in the root directory of your app named 'requirements.txt'
76+
remote: ! containing the requirement '--editable .' \\(without quotes\\).
77+
remote: !
78+
remote: ! Alternatively, if you wish to switch to another package
79+
remote: ! manager, we highly recommend uv:
80+
remote: ! https://docs.astral.sh/uv/
81+
remote:
6082
remote: -----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
6183
remote: -----> Installing Python #{DEFAULT_PYTHON_FULL_VERSION}
6284
remote: -----> Installing pip #{PIP_VERSION}

spec/hatchet/pip_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
remote: "python_version_outdated": false,
7878
remote: "python_version_pinned": false,
7979
remote: "python_version_requested": "3.13",
80-
remote: "setup_py_only": false,
8180
remote: "total_duration": [0-9.]+
8281
remote: \\}
8382
REGEX

spec/hatchet/pipenv_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
remote: "python_version_outdated": false,
8080
remote: "python_version_pinned": false,
8181
remote: "python_version_requested": "3.13",
82-
remote: "setup_py_only": false,
8382
remote: "total_duration": [0-9.]+
8483
remote: \\}
8584
REGEX

spec/hatchet/poetry_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
remote: "python_version_outdated": false,
8080
remote: "python_version_pinned": false,
8181
remote: "python_version_requested": "3.13",
82-
remote: "setup_py_only": false,
8382
remote: "total_duration": [0-9.]+
8483
remote: \\}
8584
REGEX

spec/hatchet/uv_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
remote: "python_version_outdated": false,
8585
remote: "python_version_pinned": false,
8686
remote: "python_version_requested": "3.13",
87-
remote: "setup_py_only": false,
8887
remote: "total_duration": [0-9.]+,
8988
remote: "uv_version": "#{UV_VERSION}"
9089
remote: \\}

0 commit comments

Comments
 (0)