Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Aliases/python
2 changes: 1 addition & 1 deletion Aliases/python-tk
2 changes: 1 addition & 1 deletion Aliases/python3
2 changes: 1 addition & 1 deletion Aliases/python@3
148 changes: 88 additions & 60 deletions Formula/python@3.10.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
Expand All @@ -23,8 +24,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"
Expand All @@ -45,15 +44,31 @@ 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"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean whichever version is linked last will be Current?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I contemplated that, but found it too confusing, so decided against it.

In this PR, only the newest Python in Homebrew/core (i.e. python@3.10) will have these symlinks.

I would like to find a way to do it so that the newest Python you have installed will have these symlinks, so that the behaviour is consistent and predictable, but im punting on that for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I contemplated that, but found it too confusing, so decided against it.

Agreed, I think it's better this way.

In this PR, only the newest Python in Homebrew/core (i.e. python@3.10) will have these symlinks.

How do we ensure these get updated/migrated on a new Python version? Audit? Could do something like fail if the alias doesn't point to python.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we ensure these get updated/migrated on a new Python version? Audit? Could do something like fail if the alias doesn't point to python.

Yup, we should add an audit for this. Will look at one soon.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlocab Sounds great, doesn't need to block this PR 👍🏻


# 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
Expand All @@ -78,10 +93,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

Expand All @@ -94,6 +109,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.
Expand Down Expand Up @@ -163,7 +182,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"
Expand All @@ -177,9 +196,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
Expand All @@ -206,23 +224,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
Expand All @@ -238,9 +263,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

Expand All @@ -253,7 +275,7 @@ def install
--no-build-isolation
]
whl_build = buildpath/"whl_build"
system bin/"python3", "-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,
Expand All @@ -262,7 +284,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,
Expand All @@ -282,12 +304,12 @@ def install

# Install unversioned symlinks in libexec/bin.
{
"idle" => "idle3",
"pydoc" => "pydoc3",
"python" => "python3",
"python-config" => "python3-config",
}.each do |unversioned_name, versioned_name|
(libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name
"idle" => "idle#{version.major_minor}",
"pydoc" => "pydoc#{version.major_minor}",
"python" => "python#{version.major_minor}",
"python-config" => "python#{version.major_minor}-config",
}.each do |short_name, long_name|
(libexec/"bin").install_symlink (bin/long_name).realpath => short_name
end
end

Expand Down Expand Up @@ -316,38 +338,44 @@ 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 python3, "-m", "ensurepip"

# Install desired versions of setuptools, pip, wheel using the version of
# pip bootstrapped by ensurepip.
# Note that while we replaced the ensurepip wheels, there's no guarantee
# 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",
"--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"
system python3, "-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"

# pip install with --target flag will just place the bin folder into the
# target, so move its contents into the appropriate location
mv (site_packages/"bin").children, bin
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",
}.each do |unversioned_name, versioned_name|
(libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name
"pip" => "pip#{version.major_minor}",
"wheel" => "wheel#{version.major_minor}",
}.each do |short_name, long_name|
(libexec/"bin").install_symlink (bin/long_name).realpath => short_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

Expand Down Expand Up @@ -406,16 +434,16 @@ 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 <package>
pip3 install <package>
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}
Expand All @@ -427,21 +455,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
Expand All @@ -454,8 +482,8 @@ 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/"pip3", "list", "--format=columns"
system bin/"pip#{version.major_minor}", "list", "--format=columns"
end
end
Loading