From db15b1b40ddde31596e061553f5e1d1198a83087 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 13:58:31 +0800 Subject: [PATCH 01/10] python@3.9: use `altinstall` target This makes sure that Python does not install major-versioned files (e.g. `python3`, `python3-config`) and instead only installs files with both a major and minor version (e.g. `python3.9`, `python3.9-config`). This will allow us to have multiple versions of Python linked into `HOMEBREW_PREFIX` without conflicts. If users want to call `python3.9` as `python3`, then they can add `libexec/"bin"` to their `PATH`. Going forward, this will help simplify migrating to newer versions of Python, since we will not need to make the newer version keg-only while dependent formulae are migrated. See discussion at Homebrew/discussions#2776, and documentation at https://github.com/python/cpython#installing-multiple-versions Closes #87075. --- Formula/python@3.9.rb | 74 +++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/Formula/python@3.9.rb b/Formula/python@3.9.rb index 2b70af92b145..02aa8be2811e 100644 --- a/Formula/python@3.9.rb +++ b/Formula/python@3.9.rb @@ -44,21 +44,6 @@ class PythonAT39 < Formula skip_clean "bin/easy_install3", "bin/easy_install-3.4", "bin/easy_install-3.5", "bin/easy_install-3.6", "bin/easy_install-3.7", "bin/easy_install-3.8" - link_overwrite "bin/2to3" - link_overwrite "bin/idle3" - link_overwrite "bin/pip3" - link_overwrite "bin/pydoc3" - link_overwrite "bin/python3" - link_overwrite "bin/python3-config" - link_overwrite "bin/wheel3" - link_overwrite "share/man/man1/python3.1" - link_overwrite "lib/pkgconfig/python3.pc" - link_overwrite "lib/pkgconfig/python3-embed.pc" - link_overwrite "Frameworks/Python.framework/Headers" - link_overwrite "Frameworks/Python.framework/Python" - link_overwrite "Frameworks/Python.framework/Resources" - link_overwrite "Frameworks/Python.framework/Versions/Current" - # Always update to latest release resource "setuptools" do url "https://files.pythonhosted.org/packages/a8/d9/28490a9ef6592c3471bd1bcacaf5bd0dee2bb05c8a8bcf901e673b2f1732/setuptools-63.3.0.tar.gz" @@ -203,8 +188,12 @@ def install system "make" ENV.deparallelize do + # The `altinstall` target prevents the installation of files with only Python's major + # version in its name. This allows us to link multiple versioned Python formulae. + # https://github.com/python/cpython#installing-multiple-versions + # # Tell Python not to install into /Applications (default for framework builds) - system "make", "install", "PYTHONAPPSDIR=#{prefix}" + system "make", "altinstall", "PYTHONAPPSDIR=#{prefix}" system "make", "frameworkinstallextras", "PYTHONAPPSDIR=#{pkgshare}" if OS.mac? end @@ -227,6 +216,9 @@ def install inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py"], %r{('LINKFORSHARED': .*?)'(Python.framework/Versions/3.\d+/Python)'}m, "\\1'#{opt_prefix}/Frameworks/\\2'" + + # Remove symlinks that conflict with the main Python formula. + rm %w[Headers Python Resources Versions/Current].map { |subdir| frameworks/"Python.framework"/subdir } else # Prevent third-party packages from building against fragile Cellar paths inreplace Dir[lib_cellar/"**/_sysconfigdata_*linux_x86_64-*.py", @@ -238,6 +230,9 @@ def install inreplace bin/"python#{version.major_minor}-config", 'prefix_real=$(installed_prefix "$0")', "prefix_real=#{opt_prefix}" + + # Remove symlinks that conflict with the main Python formula. + rm lib/"libpython3.so" end # Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible. @@ -255,7 +250,7 @@ def install --no-build-isolation ] whl_build = buildpath/"whl_build" - system bin/"python3", "-m", "venv", whl_build + system bin/"python#{version.major_minor}", "-m", "venv", whl_build resource("wheel").stage do system whl_build/"bin/pip3", "install", *common_pip_args, "." system whl_build/"bin/pip3", "wheel", *common_pip_args, @@ -282,12 +277,16 @@ def install # Write out sitecustomize.py (lib_cellar/"sitecustomize.py").atomic_write(sitecustomize) - # Install unversioned symlinks in libexec/bin. + # Install unversioned and major-versioned symlinks in libexec/bin. { - "idle" => "idle3", - "pydoc" => "pydoc3", - "python" => "python3", - "python-config" => "python3-config", + "idle" => "idle#{version.major_minor}", + "idle3" => "idle#{version.major_minor}", + "pydoc" => "pydoc#{version.major_minor}", + "pydoc3" => "pydoc#{version.major_minor}", + "python" => "python#{version.major_minor}", + "python3" => "python#{version.major_minor}", + "python-config" => "python#{version.major_minor}-config", + "python3-config" => "python#{version.major_minor}-config", }.each do |unversioned_name, versioned_name| (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name end @@ -318,7 +317,7 @@ def post_install rm_rf Dir["#{site_packages}/pip[-_.][0-9]*", "#{site_packages}/pip"] rm_rf Dir["#{site_packages}/wheel[-_.][0-9]*", "#{site_packages}/wheel"] - system bin/"python3", "-m", "ensurepip" + system bin/"python#{version.major_minor}", "-m", "ensurepip" # Install desired versions of setuptools, pip, wheel using the version of # pip bootstrapped by ensurepip. @@ -326,7 +325,7 @@ def post_install # ensurepip actually used them, since other existing installations could # have been picked up (and we can't pass --ignore-installed). bundled = lib_cellar/"ensurepip/_bundled" - system bin/"python3", "-m", "pip", "install", "-v", + system bin/"python#{version.major_minor}", "-m", "pip", "install", "-v", "--no-deps", "--no-index", "--upgrade", @@ -341,19 +340,21 @@ def post_install mv (site_packages/"bin").children, bin rmdir site_packages/"bin" - rm_rf bin/"pip" - mv bin/"wheel", bin/"wheel3" + rm_rf bin.glob("pip{,3}") + mv bin/"wheel", bin/"wheel#{version.major_minor}" - # Install unversioned symlinks in libexec/bin. + # Install unversioned and major-versioned symlinks in libexec/bin. { - "pip" => "pip3", - "wheel" => "wheel3", + "pip" => "pip#{version.major_minor}", + "pip3" => "pip#{version.major_minor}", + "wheel" => "wheel#{version.major_minor}", + "wheel3" => "wheel#{version.major_minor}", }.each do |unversioned_name, versioned_name| (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name end # post_install happens after link - %W[pip3 wheel3 pip#{version.major_minor}].each do |e| + %W[wheel#{version.major_minor} pip#{version.major_minor}].each do |e| (HOMEBREW_PREFIX/"bin").install_symlink bin/e end @@ -436,20 +437,23 @@ def sitecustomize def caveats <<~EOS Python has been installed as - #{HOMEBREW_PREFIX}/bin/python3 + #{HOMEBREW_PREFIX}/bin/python#{version.major_minor} - Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to - `python3`, `python3-config`, `pip3` etc., respectively, have been installed into + Unversioned and major-versioned symlinks `python`, `python3`, `python-config`, `python3-config`, `pip`, `pip3`, etc. pointing to + `python#{version.major_minor}`, `python#{version.major_minor}-config`, `pip#{version.major_minor}` etc., respectively, have been installed into #{opt_libexec}/bin You can install Python packages with - pip3 install + pip#{version.major_minor} install They will install into the site-package directory #{HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages"} tkinter is no longer included with this formula, but it is available separately: brew install python-tk@#{version.major_minor} + If you do not need a specific version of Python, and always want Homebrew's `python3` in your PATH: + brew install python3 + See: https://docs.brew.sh/Homebrew-and-Python EOS end @@ -486,6 +490,6 @@ def caveats EOS system "#{bin}/python#{version.major_minor}", "dbm_test.py" - system bin/"pip3", "list", "--format=columns" + system bin/"pip#{version.major_minor}", "list", "--format=columns" end end From 03ff32c664f3c15324f0871bbf12f144b02e51cd Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 14:10:47 +0800 Subject: [PATCH 02/10] python@3.10: link into `HOMEBREW_PREFIX` The previous commit minimises the conflict between `python@3.9` and `python@3.10`. The rest is handled by the `link_overwrite` lines. --- Formula/python@3.10.rb | 50 +++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/Formula/python@3.10.rb b/Formula/python@3.10.rb index 29e80d1780f0..5d8d3c5c47cb 100644 --- a/Formula/python@3.10.rb +++ b/Formula/python@3.10.rb @@ -23,8 +23,6 @@ class PythonAT310 < Formula # build packages later. Xcode-only systems need different flags. pour_bottle? only_if: :clt_installed - keg_only :versioned_formula - depends_on "pkg-config" => :build depends_on "gdbm" depends_on "mpdecimal" @@ -45,6 +43,22 @@ class PythonAT310 < Formula skip_clean "bin/easy_install3", "bin/easy_install-3.4", "bin/easy_install-3.5", "bin/easy_install-3.6", "bin/easy_install-3.7", "bin/easy_install-3.8", "bin/easy_install-3.9" + link_overwrite "bin/2to3" + link_overwrite "bin/idle3" + link_overwrite "bin/pip3" + link_overwrite "bin/pydoc3" + link_overwrite "bin/python3" + link_overwrite "bin/python3-config" + link_overwrite "bin/wheel3" + link_overwrite "share/man/man1/python3.1" + link_overwrite "lib/libpython3.so" + link_overwrite "lib/pkgconfig/python3.pc" + link_overwrite "lib/pkgconfig/python3-embed.pc" + link_overwrite "Frameworks/Python.framework/Headers" + link_overwrite "Frameworks/Python.framework/Python" + link_overwrite "Frameworks/Python.framework/Resources" + link_overwrite "Frameworks/Python.framework/Versions/Current" + # Always update to latest release resource "setuptools" do url "https://files.pythonhosted.org/packages/a8/d9/28490a9ef6592c3471bd1bcacaf5bd0dee2bb05c8a8bcf901e673b2f1732/setuptools-63.3.0.tar.gz" @@ -253,7 +267,7 @@ def install --no-build-isolation ] whl_build = buildpath/"whl_build" - system bin/"python3", "-m", "venv", whl_build + system bin/"python#{version.major_minor}", "-m", "venv", whl_build resource("wheel").stage do system whl_build/"bin/pip3", "install", *common_pip_args, "." system whl_build/"bin/pip3", "wheel", *common_pip_args, @@ -282,10 +296,10 @@ def install # Install unversioned symlinks in libexec/bin. { - "idle" => "idle3", - "pydoc" => "pydoc3", - "python" => "python3", - "python-config" => "python3-config", + "idle" => "idle#{version.major_minor}", + "pydoc" => "pydoc#{version.major_minor}", + "python" => "python#{version.major_minor}", + "python-config" => "python#{version.major_minor}-config", }.each do |unversioned_name, versioned_name| (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name end @@ -316,7 +330,7 @@ def post_install rm_rf Dir["#{site_packages}/pip[-_.][0-9]*", "#{site_packages}/pip"] rm_rf Dir["#{site_packages}/wheel[-_.][0-9]*", "#{site_packages}/wheel"] - system bin/"python3", "-m", "ensurepip" + system bin/"python#{version.major_minor}", "-m", "ensurepip" # Install desired versions of setuptools, pip, wheel using the version of # pip bootstrapped by ensurepip. @@ -324,7 +338,7 @@ def post_install # ensurepip actually used them, since other existing installations could # have been picked up (and we can't pass --ignore-installed). bundled = lib_cellar/"ensurepip/_bundled" - system bin/"python3", "-m", "pip", "install", "-v", + system bin/"python#{version.major_minor}", "-m", "pip", "install", "-v", "--no-deps", "--no-index", "--upgrade", @@ -340,15 +354,21 @@ def post_install rmdir site_packages/"bin" rm_rf bin/"pip" - mv bin/"wheel", bin/"wheel3" + mv bin/"wheel", bin/"wheel#{version.major_minor}" + bin.install_symlink "wheel#{version.major_minor}" => "wheel3" # Install unversioned symlinks in libexec/bin. { - "pip" => "pip3", - "wheel" => "wheel3", + "pip" => "pip#{version.major_minor}", + "wheel" => "wheel#{version.major_minor}", }.each do |unversioned_name, versioned_name| (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name end + + # post_install happens after link + %W[wheel3 pip3 wheel#{version.major_minor} pip#{version.major_minor}].each do |e| + (HOMEBREW_PREFIX/"bin").install_symlink bin/e + end end def sitecustomize @@ -406,14 +426,14 @@ def sitecustomize def caveats <<~EOS Python has been installed as - #{opt_bin}/python3 + #{HOMEBREW_PREFIX}/bin/python3 Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to `python3`, `python3-config`, `pip3` etc., respectively, have been installed into #{opt_libexec}/bin You can install Python packages with - #{opt_bin}/pip3 install + pip3 install They will install into the site-package directory #{HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages"} @@ -456,6 +476,6 @@ def caveats EOS system "#{bin}/python#{version.major_minor}", "dbm_test.py" - system bin/"pip3", "list", "--format=columns" + system bin/"pip#{version.major_minor}", "list", "--format=columns" end end From 8f7fd8e784cab65cc417a44f24a2db3e258c058c Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 14:15:29 +0800 Subject: [PATCH 03/10] python@3.9: cleanup --- Formula/python@3.9.rb | 70 +++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/Formula/python@3.9.rb b/Formula/python@3.9.rb index 02aa8be2811e..8350e05635e5 100644 --- a/Formula/python@3.9.rb +++ b/Formula/python@3.9.rb @@ -68,10 +68,10 @@ class PythonAT39 < Formula def lib_cellar on_macos do - return prefix/"Frameworks/Python.framework/Versions/#{version.major_minor}/lib/python#{version.major_minor}" + return frameworks/"Python.framework/Versions"/version.major_minor/"lib/python#{version.major_minor}" end on_linux do - return prefix/"lib/python#{version.major_minor}" + return lib/"python#{version.major_minor}" end end @@ -150,7 +150,7 @@ def install # superenv makes cc always find includes/libs! inreplace "setup.py", "do_readline = self.compiler.find_library_file(self.lib_dirs, 'readline')", - "do_readline = '#{Formula["readline"].opt_lib}/#{shared_library("libhistory")}'" + "do_readline = '#{Formula["readline"].opt_lib/shared_library("libhistory")}'" inreplace "setup.py" do |s| s.gsub! "sqlite_setup_debug = False", "sqlite_setup_debug = True" @@ -164,9 +164,8 @@ def install # a 32-bit system ncurses (conflicts with the brewed 64-bit one). # See https://github.com/Homebrew/linuxbrew-core/pull/22307#issuecomment-781896552 # We want our ncurses! Override system ncurses includes! - inreplace "configure", - 'CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw"', - "CPPFLAGS=\"$CPPFLAGS -I#{Formula["ncurses"].opt_include}\"" + inreplace "configure", 'CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw"', + "CPPFLAGS=\"$CPPFLAGS -I#{Formula["ncurses"].opt_include}\"" end # Allow python modules to use ctypes.find_library to find homebrew's stuff @@ -197,23 +196,33 @@ def install system "make", "frameworkinstallextras", "PYTHONAPPSDIR=#{pkgshare}" if OS.mac? end - # Any .app get a " 3" attached, so it does not conflict with python 2.x. - Dir.glob("#{prefix}/*.app") { |app| mv app, app.sub(/\.app$/, " 3.app") } - if OS.mac? + # Any .app get a " 3" attached, so it does not conflict with python 2.x. + prefix.glob("*.app") { |app| mv app, app.to_s.sub(/\.app$/, " 3.app") } + + pc_dir = frameworks/"Python.framework/Versions"/version.major_minor/"lib/pkgconfig" + # Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible. + (lib/"pkgconfig").install_symlink pc_dir.children + # Prevent third-party packages from building against fragile Cellar paths - inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py", - lib_cellar/"config*/Makefile", - frameworks/"Python.framework/Versions/3*/lib/pkgconfig/python-3.?.pc"], - prefix, opt_prefix + bad_cellar_path_files = [ + lib_cellar/"_sysconfigdata__darwin_darwin.py", + lib_cellar/"config-#{version.major_minor}-darwin/Makefile", + pc_dir/"python-#{version.major_minor}.pc", + pc_dir/"python-#{version.major_minor}-embed.pc", + ] + inreplace bad_cellar_path_files, prefix, opt_prefix # Help third-party packages find the Python framework - inreplace Dir[lib_cellar/"config*/Makefile"], + inreplace lib_cellar/"config-#{version.major_minor}-darwin/Makefile", /^LINKFORSHARED=(.*)PYTHONFRAMEWORKDIR(.*)/, "LINKFORSHARED=\\1PYTHONFRAMEWORKINSTALLDIR\\2" + # Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible. + (lib/"pkgconfig").install_symlink pc_dir.children + # Fix for https://github.com/Homebrew/homebrew-core/issues/21212 - inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py"], + inreplace lib_cellar/"_sysconfigdata__darwin_darwin.py", %r{('LINKFORSHARED': .*?)'(Python.framework/Versions/3.\d+/Python)'}m, "\\1'#{opt_prefix}/Frameworks/\\2'" @@ -235,9 +244,6 @@ def install rm lib/"libpython3.so" end - # Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible. - (lib/"pkgconfig").install_symlink Dir["#{frameworks}/Python.framework/Versions/#{version.major_minor}/lib/pkgconfig/*"] - # Remove the site-packages that Python created in its Cellar. site_packages_cellar.rmtree @@ -259,7 +265,7 @@ def install end # Replace bundled setuptools/pip with our own. - rm Dir["#{lib_cellar}/ensurepip/_bundled/{setuptools,pip}-*.whl"] + rm lib_cellar.glob("ensurepip/_bundled/{setuptools,pip}-*.whl") %w[setuptools pip].each do |r| resource(r).stage do system whl_build/"bin/pip3", "wheel", *common_pip_args, @@ -287,8 +293,8 @@ def install "python3" => "python#{version.major_minor}", "python-config" => "python#{version.major_minor}-config", "python3-config" => "python#{version.major_minor}-config", - }.each do |unversioned_name, versioned_name| - (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name + }.each do |short_name, long_name| + (libexec/"bin").install_symlink (bin/long_name).realpath => short_name end end @@ -349,8 +355,8 @@ def post_install "pip3" => "pip#{version.major_minor}", "wheel" => "wheel#{version.major_minor}", "wheel3" => "wheel#{version.major_minor}", - }.each do |unversioned_name, versioned_name| - (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name + }.each do |short_name, long_name| + (libexec/"bin").install_symlink (bin/long_name).realpath => short_name end # post_install happens after link @@ -446,7 +452,7 @@ def caveats You can install Python packages with pip#{version.major_minor} install They will install into the site-package directory - #{HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages"} + #{HOMEBREW_PREFIX}/lib/python#{version.major_minor}/site-packages tkinter is no longer included with this formula, but it is available separately: brew install python-tk@#{version.major_minor} @@ -461,17 +467,17 @@ def caveats test do # Check if sqlite is ok, because we build with --enable-loadable-sqlite-extensions # and it can occur that building sqlite silently fails if OSX's sqlite is used. - system "#{bin}/python#{version.major_minor}", "-c", "import sqlite3" + system bin/"python#{version.major_minor}", "-c", "import sqlite3" # check to see if we can create a venv - system "#{bin}/python#{version.major_minor}", "-m", "venv", testpath/"myvenv" + system bin/"python#{version.major_minor}", "-m", "venv", testpath/"myvenv" # Check if some other modules import. Then the linked libs are working. - system "#{bin}/python#{version.major_minor}", "-c", "import _ctypes" - system "#{bin}/python#{version.major_minor}", "-c", "import _decimal" - system "#{bin}/python#{version.major_minor}", "-c", "import _gdbm" - system "#{bin}/python#{version.major_minor}", "-c", "import pyexpat" - system "#{bin}/python#{version.major_minor}", "-c", "import zlib" + system bin/"python#{version.major_minor}", "-c", "import _ctypes" + system bin/"python#{version.major_minor}", "-c", "import _decimal" + system bin/"python#{version.major_minor}", "-c", "import _gdbm" + system bin/"python#{version.major_minor}", "-c", "import pyexpat" + system bin/"python#{version.major_minor}", "-c", "import zlib" # tkinter is provided in a separate formula assert_match "ModuleNotFoundError: No module named '_tkinter'", @@ -488,7 +494,7 @@ def caveats assert b"foo \\xbd" in db assert db[b"foo \\xbd"] == b"bar \\xbd" EOS - system "#{bin}/python#{version.major_minor}", "dbm_test.py" + system bin/"python#{version.major_minor}", "dbm_test.py" system bin/"pip#{version.major_minor}", "list", "--format=columns" end From 94b0341c80d3ab8d27da974a6d2c8e9c22cc010e Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 14:15:58 +0800 Subject: [PATCH 04/10] python@3.10: cleanup --- Formula/python@3.10.rb | 85 ++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/Formula/python@3.10.rb b/Formula/python@3.10.rb index 5d8d3c5c47cb..18c456a82e07 100644 --- a/Formula/python@3.10.rb +++ b/Formula/python@3.10.rb @@ -92,10 +92,10 @@ class PythonAT310 < Formula def lib_cellar on_macos do - return prefix/"Frameworks/Python.framework/Versions/#{version.major_minor}/lib/python#{version.major_minor}" + return frameworks/"Python.framework/Versions"/version.major_minor/"lib/python#{version.major_minor}" end on_linux do - return prefix/"lib/python#{version.major_minor}" + return lib/"python#{version.major_minor}" end end @@ -177,7 +177,7 @@ def install # superenv makes cc always find includes/libs! inreplace "setup.py", /do_readline = self.compiler.find_library_file\(self.lib_dirs,\s*readline_lib\)/, - "do_readline = '#{Formula["readline"].opt_lib}/#{shared_library("libhistory")}'" + "do_readline = '#{Formula["readline"].opt_lib/shared_library("libhistory")}'" inreplace "setup.py" do |s| s.gsub! "sqlite_setup_debug = False", "sqlite_setup_debug = True" @@ -191,9 +191,8 @@ def install # a 32-bit system ncurses (conflicts with the brewed 64-bit one). # See https://github.com/Homebrew/linuxbrew-core/pull/22307#issuecomment-781896552 # We want our ncurses! Override system ncurses includes! - inreplace "configure", - 'CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw"', - "CPPFLAGS=\"$CPPFLAGS -I#{Formula["ncurses"].opt_include}\"" + inreplace "configure", 'CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw"', + "CPPFLAGS=\"$CPPFLAGS -I#{Formula["ncurses"].opt_include}\"" end # Allow python modules to use ctypes.find_library to find homebrew's stuff @@ -220,23 +219,30 @@ def install system "make", "frameworkinstallextras", "PYTHONAPPSDIR=#{pkgshare}" if OS.mac? end - # Any .app get a " 3" attached, so it does not conflict with python 2.x. - Dir.glob("#{prefix}/*.app") { |app| mv app, app.sub(/\.app$/, " 3.app") } - if OS.mac? + # Any .app get a " 3" attached, so it does not conflict with python 2.x. + prefix.glob("*.app") { |app| mv app, app.to_s.sub(/\.app$/, " 3.app") } + + pc_dir = frameworks/"Python.framework/Versions"/version.major_minor/"lib/pkgconfig" + # Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible. + (lib/"pkgconfig").install_symlink pc_dir.children + # Prevent third-party packages from building against fragile Cellar paths - inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py", - lib_cellar/"config*/Makefile", - frameworks/"Python.framework/Versions/3*/lib/pkgconfig/python-3*.pc"], - prefix, opt_prefix + bad_cellar_path_files = [ + lib_cellar/"_sysconfigdata__darwin_darwin.py", + lib_cellar/"config-#{version.major_minor}-darwin/Makefile", + pc_dir/"python-#{version.major_minor}.pc", + pc_dir/"python-#{version.major_minor}-embed.pc", + ] + inreplace bad_cellar_path_files, prefix, opt_prefix # Help third-party packages find the Python framework - inreplace Dir[lib_cellar/"config*/Makefile"], + inreplace lib_cellar/"config-#{version.major_minor}-darwin/Makefile", /^LINKFORSHARED=(.*)PYTHONFRAMEWORKDIR(.*)/, "LINKFORSHARED=\\1PYTHONFRAMEWORKINSTALLDIR\\2" # Fix for https://github.com/Homebrew/homebrew-core/issues/21212 - inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py"], + inreplace lib_cellar/"_sysconfigdata__darwin_darwin.py", %r{('LINKFORSHARED': .*?)'(Python.framework/Versions/3.\d+/Python)'}m, "\\1'#{opt_prefix}/Frameworks/\\2'" else @@ -252,9 +258,6 @@ def install "prefix_real=#{opt_prefix}" end - # Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible. - (lib/"pkgconfig").install_symlink Dir["#{frameworks}/Python.framework/Versions/#{version.major_minor}/lib/pkgconfig/*"] - # Remove the site-packages that Python created in its Cellar. site_packages_cellar.rmtree @@ -276,7 +279,7 @@ def install end # Replace bundled setuptools/pip with our own. - rm Dir["#{lib_cellar}/ensurepip/_bundled/{setuptools,pip}-*.whl"] + rm lib_cellar.glob("ensurepip/_bundled/{setuptools,pip}-*.whl") %w[setuptools pip].each do |r| resource(r).stage do system whl_build/"bin/pip3", "wheel", *common_pip_args, @@ -300,8 +303,8 @@ def install "pydoc" => "pydoc#{version.major_minor}", "python" => "python#{version.major_minor}", "python-config" => "python#{version.major_minor}-config", - }.each do |unversioned_name, versioned_name| - (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name + }.each do |short_name, long_name| + (libexec/"bin").install_symlink (bin/long_name).realpath => short_name end end @@ -339,14 +342,14 @@ def post_install # have been picked up (and we can't pass --ignore-installed). bundled = lib_cellar/"ensurepip/_bundled" system bin/"python#{version.major_minor}", "-m", "pip", "install", "-v", - "--no-deps", - "--no-index", - "--upgrade", - "--isolated", - "--target=#{site_packages}", - bundled/"setuptools-#{resource("setuptools").version}-py3-none-any.whl", - bundled/"pip-#{resource("pip").version}-py3-none-any.whl", - libexec/"wheel-#{resource("wheel").version}-py2.py3-none-any.whl" + "--no-deps", + "--no-index", + "--upgrade", + "--isolated", + "--target=#{site_packages}", + bundled/"setuptools-#{resource("setuptools").version}-py3-none-any.whl", + bundled/"pip-#{resource("pip").version}-py3-none-any.whl", + libexec/"wheel-#{resource("wheel").version}-py2.py3-none-any.whl" # pip install with --target flag will just place the bin folder into the # target, so move its contents into the appropriate location @@ -361,8 +364,8 @@ def post_install { "pip" => "pip#{version.major_minor}", "wheel" => "wheel#{version.major_minor}", - }.each do |unversioned_name, versioned_name| - (libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name + }.each do |short_name, long_name| + (libexec/"bin").install_symlink (bin/long_name).realpath => short_name end # post_install happens after link @@ -435,7 +438,7 @@ def caveats You can install Python packages with pip3 install They will install into the site-package directory - #{HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages"} + #{HOMEBREW_PREFIX}/lib/python#{version.major_minor}/site-packages tkinter is no longer included with this formula, but it is available separately: brew install python-tk@#{version.major_minor} @@ -447,21 +450,21 @@ def caveats test do # Check if sqlite is ok, because we build with --enable-loadable-sqlite-extensions # and it can occur that building sqlite silently fails if OSX's sqlite is used. - system "#{bin}/python#{version.major_minor}", "-c", "import sqlite3" + system bin/"python#{version.major_minor}", "-c", "import sqlite3" # check to see if we can create a venv - system "#{bin}/python#{version.major_minor}", "-m", "venv", testpath/"myvenv" + system bin/"python#{version.major_minor}", "-m", "venv", testpath/"myvenv" # Check if some other modules import. Then the linked libs are working. - system "#{bin}/python#{version.major_minor}", "-c", "import _ctypes" - system "#{bin}/python#{version.major_minor}", "-c", "import _decimal" - system "#{bin}/python#{version.major_minor}", "-c", "import _gdbm" - system "#{bin}/python#{version.major_minor}", "-c", "import pyexpat" - system "#{bin}/python#{version.major_minor}", "-c", "import zlib" + system bin/"python#{version.major_minor}", "-c", "import _ctypes" + system bin/"python#{version.major_minor}", "-c", "import _decimal" + system bin/"python#{version.major_minor}", "-c", "import _gdbm" + system bin/"python#{version.major_minor}", "-c", "import pyexpat" + system bin/"python#{version.major_minor}", "-c", "import zlib" # tkinter is provided in a separate formula assert_match "ModuleNotFoundError: No module named '_tkinter'", - shell_output("#{bin}/python#{version.major_minor} -Sc 'import tkinter' 2>&1", 1) + shell_output("#{bin}/python#{version.major_minor} -Sc 'import tkinter' 2>&1", 1) # Verify that the selected DBM interface works (testpath/"dbm_test.py").write <<~EOS @@ -474,7 +477,7 @@ def caveats assert b"foo \\xbd" in db assert db[b"foo \\xbd"] == b"bar \\xbd" EOS - system "#{bin}/python#{version.major_minor}", "dbm_test.py" + system bin/"python#{version.major_minor}", "dbm_test.py" system bin/"pip#{version.major_minor}", "list", "--format=columns" end From bc76de17db024bb58c9f990eea156cfa1d5fcbd6 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 14:17:18 +0800 Subject: [PATCH 05/10] Update Python aliases --- Aliases/python | 2 +- Aliases/python-tk | 2 +- Aliases/python3 | 2 +- Aliases/python@3 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Aliases/python b/Aliases/python index 873ea35598d1..a5dfdd3cfd76 120000 --- a/Aliases/python +++ b/Aliases/python @@ -1 +1 @@ -../Formula/python@3.9.rb \ No newline at end of file +../Formula/python@3.10.rb \ No newline at end of file diff --git a/Aliases/python-tk b/Aliases/python-tk index 7390342d99d9..c46ab5447731 120000 --- a/Aliases/python-tk +++ b/Aliases/python-tk @@ -1 +1 @@ -../Formula/python-tk@3.9.rb \ No newline at end of file +../Formula/python-tk@3.10.rb \ No newline at end of file diff --git a/Aliases/python3 b/Aliases/python3 index 873ea35598d1..a5dfdd3cfd76 120000 --- a/Aliases/python3 +++ b/Aliases/python3 @@ -1 +1 @@ -../Formula/python@3.9.rb \ No newline at end of file +../Formula/python@3.10.rb \ No newline at end of file diff --git a/Aliases/python@3 b/Aliases/python@3 index 873ea35598d1..a5dfdd3cfd76 120000 --- a/Aliases/python@3 +++ b/Aliases/python@3 @@ -1 +1 @@ -../Formula/python@3.9.rb \ No newline at end of file +../Formula/python@3.10.rb \ No newline at end of file From 43b92411ca06234247a71142fb208c5efbd151bb Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 14:17:45 +0800 Subject: [PATCH 06/10] versioned_keg_only_allowlist: add Python 3.10 Previous changes allow Python 3.9 and Python 3.10 to be linked at the same time. --- audit_exceptions/versioned_keg_only_allowlist.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/audit_exceptions/versioned_keg_only_allowlist.json b/audit_exceptions/versioned_keg_only_allowlist.json index 93448408180f..ef8c9c1cdfa2 100644 --- a/audit_exceptions/versioned_keg_only_allowlist.json +++ b/audit_exceptions/versioned_keg_only_allowlist.json @@ -26,7 +26,9 @@ "pangomm@2.46", "pyqt@5", "python@3.9", + "python@3.10", "python-tk@3.9", + "python-tk@3.10", "spidermonkey@78", "wxwidgets@3.0" ] From e8f2f78b08c875a1491a17f34a458e10dbd64340 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 21:08:09 +0800 Subject: [PATCH 07/10] python@3.9: use `python3` helper method Co-authored-by: XuehaiPan --- Formula/python@3.9.rb | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Formula/python@3.9.rb b/Formula/python@3.9.rb index 8350e05635e5..d8d1b9226a48 100644 --- a/Formula/python@3.9.rb +++ b/Formula/python@3.9.rb @@ -84,6 +84,10 @@ def site_packages HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages" end + def python3 + bin/"python#{version.major_minor}" + end + def install # Unset these so that installing pip and setuptools puts them where we want # and not into some other Python the user has installed. @@ -256,7 +260,7 @@ def install --no-build-isolation ] whl_build = buildpath/"whl_build" - system bin/"python#{version.major_minor}", "-m", "venv", whl_build + system python3, "-m", "venv", whl_build resource("wheel").stage do system whl_build/"bin/pip3", "install", *common_pip_args, "." system whl_build/"bin/pip3", "wheel", *common_pip_args, @@ -323,7 +327,7 @@ def post_install rm_rf Dir["#{site_packages}/pip[-_.][0-9]*", "#{site_packages}/pip"] rm_rf Dir["#{site_packages}/wheel[-_.][0-9]*", "#{site_packages}/wheel"] - system bin/"python#{version.major_minor}", "-m", "ensurepip" + system python3, "-m", "ensurepip" # Install desired versions of setuptools, pip, wheel using the version of # pip bootstrapped by ensurepip. @@ -331,7 +335,7 @@ def post_install # ensurepip actually used them, since other existing installations could # have been picked up (and we can't pass --ignore-installed). bundled = lib_cellar/"ensurepip/_bundled" - system bin/"python#{version.major_minor}", "-m", "pip", "install", "-v", + system python3, "-m", "pip", "install", "-v", "--no-deps", "--no-index", "--upgrade", @@ -467,21 +471,21 @@ def caveats test do # Check if sqlite is ok, because we build with --enable-loadable-sqlite-extensions # and it can occur that building sqlite silently fails if OSX's sqlite is used. - system bin/"python#{version.major_minor}", "-c", "import sqlite3" + system python3, "-c", "import sqlite3" # check to see if we can create a venv - system bin/"python#{version.major_minor}", "-m", "venv", testpath/"myvenv" + system python3, "-m", "venv", testpath/"myvenv" # Check if some other modules import. Then the linked libs are working. - system bin/"python#{version.major_minor}", "-c", "import _ctypes" - system bin/"python#{version.major_minor}", "-c", "import _decimal" - system bin/"python#{version.major_minor}", "-c", "import _gdbm" - system bin/"python#{version.major_minor}", "-c", "import pyexpat" - system bin/"python#{version.major_minor}", "-c", "import zlib" + system python3, "-c", "import _ctypes" + system python3, "-c", "import _decimal" + system python3, "-c", "import _gdbm" + system python3, "-c", "import pyexpat" + system python3, "-c", "import zlib" # tkinter is provided in a separate formula assert_match "ModuleNotFoundError: No module named '_tkinter'", - shell_output("#{bin}/python#{version.major_minor} -Sc 'import tkinter' 2>&1", 1) + shell_output("#{python3} -Sc 'import tkinter' 2>&1", 1) # Verify that the selected DBM interface works (testpath/"dbm_test.py").write <<~EOS @@ -494,7 +498,7 @@ def caveats assert b"foo \\xbd" in db assert db[b"foo \\xbd"] == b"bar \\xbd" EOS - system bin/"python#{version.major_minor}", "dbm_test.py" + system python3, "dbm_test.py" system bin/"pip#{version.major_minor}", "list", "--format=columns" end From e8aec98fd02680441b5457e55469899453de08f1 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Sun, 7 Aug 2022 21:10:54 +0800 Subject: [PATCH 08/10] python@3.10: use `python3` helper method Co-authored-by: XuehaiPan --- Formula/python@3.10.rb | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Formula/python@3.10.rb b/Formula/python@3.10.rb index 18c456a82e07..a26cc2a9c448 100644 --- a/Formula/python@3.10.rb +++ b/Formula/python@3.10.rb @@ -108,6 +108,10 @@ def site_packages HOMEBREW_PREFIX/"lib/python#{version.major_minor}/site-packages" end + def python3 + bin/"python#{version.major_minor}" + end + def install # Unset these so that installing pip and setuptools puts them where we want # and not into some other Python the user has installed. @@ -270,7 +274,7 @@ def install --no-build-isolation ] whl_build = buildpath/"whl_build" - system bin/"python#{version.major_minor}", "-m", "venv", whl_build + system python3, "-m", "venv", whl_build resource("wheel").stage do system whl_build/"bin/pip3", "install", *common_pip_args, "." system whl_build/"bin/pip3", "wheel", *common_pip_args, @@ -333,7 +337,7 @@ def post_install rm_rf Dir["#{site_packages}/pip[-_.][0-9]*", "#{site_packages}/pip"] rm_rf Dir["#{site_packages}/wheel[-_.][0-9]*", "#{site_packages}/wheel"] - system bin/"python#{version.major_minor}", "-m", "ensurepip" + system python3, "-m", "ensurepip" # Install desired versions of setuptools, pip, wheel using the version of # pip bootstrapped by ensurepip. @@ -341,7 +345,7 @@ def post_install # ensurepip actually used them, since other existing installations could # have been picked up (and we can't pass --ignore-installed). bundled = lib_cellar/"ensurepip/_bundled" - system bin/"python#{version.major_minor}", "-m", "pip", "install", "-v", + system python3, "-m", "pip", "install", "-v", "--no-deps", "--no-index", "--upgrade", @@ -450,21 +454,21 @@ def caveats test do # Check if sqlite is ok, because we build with --enable-loadable-sqlite-extensions # and it can occur that building sqlite silently fails if OSX's sqlite is used. - system bin/"python#{version.major_minor}", "-c", "import sqlite3" + system python3, "-c", "import sqlite3" # check to see if we can create a venv - system bin/"python#{version.major_minor}", "-m", "venv", testpath/"myvenv" + system python3, "-m", "venv", testpath/"myvenv" # Check if some other modules import. Then the linked libs are working. - system bin/"python#{version.major_minor}", "-c", "import _ctypes" - system bin/"python#{version.major_minor}", "-c", "import _decimal" - system bin/"python#{version.major_minor}", "-c", "import _gdbm" - system bin/"python#{version.major_minor}", "-c", "import pyexpat" - system bin/"python#{version.major_minor}", "-c", "import zlib" + system python3, "-c", "import _ctypes" + system python3, "-c", "import _decimal" + system python3, "-c", "import _gdbm" + system python3, "-c", "import pyexpat" + system python3, "-c", "import zlib" # tkinter is provided in a separate formula assert_match "ModuleNotFoundError: No module named '_tkinter'", - shell_output("#{bin}/python#{version.major_minor} -Sc 'import tkinter' 2>&1", 1) + shell_output("#{python3} -Sc 'import tkinter' 2>&1", 1) # Verify that the selected DBM interface works (testpath/"dbm_test.py").write <<~EOS @@ -477,7 +481,7 @@ def caveats assert b"foo \\xbd" in db assert db[b"foo \\xbd"] == b"bar \\xbd" EOS - system bin/"python#{version.major_minor}", "dbm_test.py" + system python3, "dbm_test.py" system bin/"pip#{version.major_minor}", "list", "--format=columns" end From 04573e7f6e129a6bbddb139ef2be092bca80ac46 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Thu, 11 Aug 2022 08:12:26 +0800 Subject: [PATCH 09/10] python@3.9: update resources --- Formula/python@3.9.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Formula/python@3.9.rb b/Formula/python@3.9.rb index d8d1b9226a48..25dec820c279 100644 --- a/Formula/python@3.9.rb +++ b/Formula/python@3.9.rb @@ -4,7 +4,7 @@ class PythonAT39 < Formula url "https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tar.xz" sha256 "125b0c598f1e15d2aa65406e83f792df7d171cdf38c16803b149994316a3080f" license "Python-2.0" - revision 2 + revision 3 livecheck do url "https://www.python.org/ftp/python/" @@ -46,13 +46,13 @@ class PythonAT39 < Formula # Always update to latest release resource "setuptools" do - url "https://files.pythonhosted.org/packages/a8/d9/28490a9ef6592c3471bd1bcacaf5bd0dee2bb05c8a8bcf901e673b2f1732/setuptools-63.3.0.tar.gz" - sha256 "273b6847ae61f7829c1affcdd9a32f67aa65233be508f4fbaab866c5faa4e408" + url "https://files.pythonhosted.org/packages/5b/ff/69fd395c5237da934753752b71c38e95e137bd0603d5640df70ddaea8038/setuptools-63.4.3.tar.gz" + sha256 "521c833d1e5e1ef0869940e7f486a83de7773b9f029010ad0c2fe35453a9dad9" end resource "pip" do - url "https://files.pythonhosted.org/packages/46/28/addd7e66bb3af799d35a5dcbb79407b591a7ed674f4efd2bd8f930c40821/pip-22.2.1.tar.gz" - sha256 "50516e47a2b79e77446f0d05649f0d53772c192571486236b1905492bfc24bac" + url "https://files.pythonhosted.org/packages/4b/30/e15b806597e67057e07a5acdc135216ccbf76a5f1681a324533b61066b0b/pip-22.2.2.tar.gz" + sha256 "3fd1929db052f056d7a998439176d3333fa1b3f6c1ad881de1885c0717608a4b" end resource "wheel" do From f16e6550700a271879c38c8ab085b7e6b538fdd6 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> Date: Thu, 11 Aug 2022 08:13:19 +0800 Subject: [PATCH 10/10] python@3.10: update resources --- Formula/python@3.10.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Formula/python@3.10.rb b/Formula/python@3.10.rb index a26cc2a9c448..64dab880b3a2 100644 --- a/Formula/python@3.10.rb +++ b/Formula/python@3.10.rb @@ -4,6 +4,7 @@ class PythonAT310 < Formula url "https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tgz" sha256 "848cb06a5caa85da5c45bd7a9221bb821e33fc2bdcba088c127c58fad44e6343" license "Python-2.0" + revision 1 livecheck do url "https://www.python.org/ftp/python/" @@ -61,13 +62,13 @@ class PythonAT310 < Formula # Always update to latest release resource "setuptools" do - url "https://files.pythonhosted.org/packages/a8/d9/28490a9ef6592c3471bd1bcacaf5bd0dee2bb05c8a8bcf901e673b2f1732/setuptools-63.3.0.tar.gz" - sha256 "273b6847ae61f7829c1affcdd9a32f67aa65233be508f4fbaab866c5faa4e408" + url "https://files.pythonhosted.org/packages/5b/ff/69fd395c5237da934753752b71c38e95e137bd0603d5640df70ddaea8038/setuptools-63.4.3.tar.gz" + sha256 "521c833d1e5e1ef0869940e7f486a83de7773b9f029010ad0c2fe35453a9dad9" end resource "pip" do - url "https://files.pythonhosted.org/packages/46/28/addd7e66bb3af799d35a5dcbb79407b591a7ed674f4efd2bd8f930c40821/pip-22.2.1.tar.gz" - sha256 "50516e47a2b79e77446f0d05649f0d53772c192571486236b1905492bfc24bac" + url "https://files.pythonhosted.org/packages/4b/30/e15b806597e67057e07a5acdc135216ccbf76a5f1681a324533b61066b0b/pip-22.2.2.tar.gz" + sha256 "3fd1929db052f056d7a998439176d3333fa1b3f6c1ad881de1885c0717608a4b" end resource "wheel" do