Skip to content

Instantly share code, notes, and snippets.

@iexa
Last active July 20, 2021 05:35
  • Star 39 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save iexa/2ac761bfd96ab78988b76c030d54a5b8 to your computer and use it in GitHub Desktop.
MacOS homebrew python 3.8.6 with tcl-tk (properly)
class Python < Formula
desc "Interpreted, interactive, object-oriented programming language"
homepage "https://www.python.org/"
url "https://www.python.org/ftp/python/3.8.6/Python-3.8.6.tar.xz"
sha256 "a9e0b79d27aa056eb9cce8d63a427b5f9bab1465dee3f942dcfdb25a82f4ab8a"
head "https://github.com/python/cpython.git"
license "Python-2.0"
revision 1
bottle do
sha256 "123ddd272ba0670d72578b36c4801b59449ac21e9d5a7e47c34c9e489330600a" => :catalina
sha256 "6367896e90735c0f1476d297d608ee08cd5f7fccf7c794c45589093fa86f4faa" => :mojave
sha256 "8714bfcc84ab6486cc7c757028298478fc28609f148ef27497940cd5cd7292e7" => :high_sierra
end
# setuptools remembers the build flags python is built with and uses them to
# build packages later. Xcode-only systems need different flags.
pour_bottle? do
reason <<~EOS
The bottle needs the Apple Command Line Tools to be installed.
You can install them, if desired, with:
xcode-select --install
EOS
satisfy { MacOS::CLT.installed? }
end
depends_on "pkg-config" => :build
depends_on "gdbm"
depends_on "openssl@1.1"
depends_on "readline"
depends_on "sqlite"
depends_on "xz"
depends_on "tcl-tk" # as apple's one is shiiiiite
uses_from_macos "bzip2"
uses_from_macos "libffi"
uses_from_macos "ncurses"
uses_from_macos "unzip"
uses_from_macos "zlib"
skip_clean "bin/pip3", "bin/pip-3.4", "bin/pip-3.5", "bin/pip-3.6", "bin/pip-3.7", "bin/pip-3.8"
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"
resource "setuptools" do
url "https://files.pythonhosted.org/packages/a7/e0/30642b9c2df516506d40b563b0cbd080c49c6b3f11a70b4c7a670f13a78b/setuptools-50.3.2.zip"
sha256 "ed0519d27a243843b05d82a5e9d01b0b083d9934eaa3d02779a23da18077bd3c"
end
resource "pip" do
url "https://files.pythonhosted.org/packages/0b/f5/be8e741434a4bf4ce5dbc235aa28ed0666178ea8986ddc10d035023744e6/pip-20.2.4.tar.gz"
sha256 "85c99a857ea0fb0aedf23833d9be5c40cf253fe24443f0829c7b472e23c364a1"
end
resource "wheel" do
url "https://files.pythonhosted.org/packages/83/72/611c121b6bd15479cb62f1a425b2e3372e121b324228df28e64cc28b01c2/wheel-0.35.1.tar.gz"
sha256 "99a22d87add3f634ff917310a3d87e499f19e663413a52eb9232c447aa646c9f"
end
# Remove this block when upstream adds arm64 compatibility
if Hardware::CPU.arm?
# Upstream PRs #20171, #21114, #21224 and #21249
patch do
url "https://raw.githubusercontent.com/Homebrew/formula-patches/113aa84/python/3.8.3.patch"
sha256 "9c0d7c28c33c6036860457bd9c5a03026c71bd034907b77fbf861ff5fe216ed0"
end
end
# Homebrew's tcl-tk is built in a standard unix fashion (due to link errors)
# so we have to stop python from searching for frameworks and linking against
# X11.
patch :DATA
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.
ENV["PYTHONHOME"] = nil
ENV["PYTHONPATH"] = nil
xy = (buildpath/"configure.ac").read.slice(/PYTHON_VERSION, (3\.\d)/, 1)
lib_cellar = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}"
args = %W[
--prefix=#{prefix}
--enable-ipv6
--datarootdir=#{share}
--datadir=#{share}
--enable-framework=#{frameworks}
--enable-loadable-sqlite-extensions
--without-ensurepip
--with-dtrace
--with-openssl=#{Formula["openssl@1.1"].opt_prefix}
]
# args << "--without-gcc" if ENV.compiler == :clang
cflags = []
ldflags = []
cppflags = []
if MacOS.sdk_path_if_needed
# Help Python's build system (setuptools/pip) to build things on SDK-based systems
# The setup.py looks at "-isysroot" to get the sysroot (and not at --sysroot)
cflags << "-isysroot #{MacOS.sdk_path}" << "-I#{MacOS.sdk_path}/usr/include"
ldflags << "-isysroot #{MacOS.sdk_path}"
# For the Xlib.h, Python needs this header dir with the system Tk
# Yep, this needs the absolute path where zlib needed a path relative
# to the SDK.
# as external tck is added later on uncomment this
# cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
end
# Avoid linking to libgcc https://mail.python.org/pipermail/python-dev/2012-February/116205.html
args << "MACOSX_DEPLOYMENT_TARGET=#{MacOS.version}"
# We want our readline! This is just to outsmart the detection code,
# 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}/libhistory.dylib'"
inreplace "setup.py" do |s|
s.gsub! "sqlite_setup_debug = False", "sqlite_setup_debug = True"
s.gsub! "for d_ in self.inc_dirs + sqlite_inc_paths:",
"for d_ in ['#{Formula["sqlite"].opt_include}']:"
end
# Allow python modules to use ctypes.find_library to find homebrew's stuff
# even if homebrew is not a /usr/local/lib. Try this with:
# `brew install enchant && pip install pyenchant`
inreplace "./Lib/ctypes/macholib/dyld.py" do |f|
f.gsub! "DEFAULT_LIBRARY_FALLBACK = [", "DEFAULT_LIBRARY_FALLBACK = [ '#{HOMEBREW_PREFIX}/lib',"
f.gsub! "DEFAULT_FRAMEWORK_FALLBACK = [", "DEFAULT_FRAMEWORK_FALLBACK = [ '#{HOMEBREW_PREFIX}/Frameworks',"
end
# ADD tcl-tk include / lib paths
tcl_tk = Formula["tcl-tk"].opt_prefix
cppflags << "-I#{tcl_tk}/include"
ldflags << "-L#{tcl_tk}/lib"
args << "CFLAGS=#{cflags.join(" ")}" unless cflags.empty?
args << "LDFLAGS=#{ldflags.join(" ")}" unless ldflags.empty?
args << "CPPFLAGS=#{cppflags.join(" ")}" unless cppflags.empty?
system "./configure", *args
system "make"
ENV.deparallelize do
# Tell Python not to install into /Applications (default for framework builds)
system "make", "install", "PYTHONAPPSDIR=#{prefix}"
system "make", "frameworkinstallextras", "PYTHONAPPSDIR=#{pkgshare}"
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") }
# 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
# Help third-party packages find the Python framework
inreplace Dir[lib_cellar/"config*/Makefile"],
/^LINKFORSHARED=(.*)PYTHONFRAMEWORKDIR(.*)/,
"LINKFORSHARED=\\1PYTHONFRAMEWORKINSTALLDIR\\2"
# Fix for https://github.com/Homebrew/homebrew-core/issues/21212
inreplace Dir[lib_cellar/"**/_sysconfigdata__darwin_darwin.py"],
%r{('LINKFORSHARED': .*?)'(Python.framework/Versions/3.\d+/Python)'}m,
"\\1'#{opt_prefix}/Frameworks/\\2'"
# A fix, because python and python3 both want to install Python.framework
# and therefore we can't link both into HOMEBREW_PREFIX/Frameworks
# https://github.com/Homebrew/homebrew/issues/15943
# ["Headers", "Python", "Resources"].each { |f| rm(prefix/"Frameworks/Python.framework/#{f}") }
# rm prefix/"Frameworks/Python.framework/Versions/Current"
# Symlink the pkgconfig files into HOMEBREW_PREFIX so they're accessible.
(lib/"pkgconfig").install_symlink Dir["#{frameworks}/Python.framework/Versions/#{xy}/lib/pkgconfig/*"]
# Remove the site-packages that Python created in its Cellar.
(prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/site-packages").rmtree
%w[setuptools pip wheel].each do |r|
(libexec/r).install resource(r)
end
# Remove wheel test data.
# It's for people editing wheel and contains binaries which fail `brew linkage`.
rm libexec/"wheel/tox.ini"
rm_r libexec/"wheel/tests"
# 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
end
end
def post_install
ENV.delete "PYTHONPATH"
xy = (prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
site_packages = HOMEBREW_PREFIX/"lib/python#{xy}/site-packages"
site_packages_cellar = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/site-packages"
# Fix up the site-packages so that user-installed Python software survives
# minor updates, such as going from 3.3.2 to 3.3.3:
# Create a site-packages in HOMEBREW_PREFIX/lib/python#{xy}/site-packages
site_packages.mkpath
# Symlink the prefix site-packages into the cellar.
site_packages_cellar.unlink if site_packages_cellar.exist?
site_packages_cellar.parent.install_symlink site_packages
# Write our sitecustomize.py
rm_rf Dir["#{site_packages}/sitecustomize.py[co]"]
(site_packages/"sitecustomize.py").atomic_write(sitecustomize)
# Remove old setuptools installations that may still fly around and be
# listed in the easy_install.pth. This can break setuptools build with
# zipimport.ZipImportError: bad local file header
# setuptools-0.9.8-py3.3.egg
rm_rf Dir["#{site_packages}/setuptools*"]
rm_rf Dir["#{site_packages}/distribute*"]
rm_rf Dir["#{site_packages}/pip[-_.][0-9]*", "#{site_packages}/pip"]
%w[setuptools pip wheel].each do |pkg|
(libexec/pkg).cd do
system bin/"python3", "-s", "setup.py", "--no-user-cfg", "install",
"--force", "--verbose", "--install-scripts=#{bin}",
"--install-lib=#{site_packages}",
"--single-version-externally-managed",
"--record=installed.txt"
end
end
rm_rf [bin/"pip", bin/"easy_install"]
mv bin/"wheel", bin/"wheel3"
# Install unversioned symlinks in libexec/bin.
{
"easy_install" => "easy_install-#{xy}",
"pip" => "pip3",
"wheel" => "wheel3",
}.each do |unversioned_name, versioned_name|
(libexec/"bin").install_symlink (bin/versioned_name).realpath => unversioned_name
end
# post_install happens after link
%W[pip3 pip#{xy} easy_install-#{xy} wheel3].each do |e|
(HOMEBREW_PREFIX/"bin").install_symlink bin/e
end
# Help distutils find brewed stuff when building extensions
include_dirs = [HOMEBREW_PREFIX/"include", Formula["openssl@1.1"].opt_include,
Formula["sqlite"].opt_include]
library_dirs = [HOMEBREW_PREFIX/"lib", Formula["openssl@1.1"].opt_lib,
Formula["sqlite"].opt_lib]
# Again tcl-tk
include_dirs << Formula["tcl-tk"].opt_include
library_dirs << Formula["tcl-tk"].opt_lib
cfg = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/distutils/distutils.cfg"
cfg.atomic_write <<~EOS
[install]
prefix=#{HOMEBREW_PREFIX}
[build_ext]
include_dirs=#{include_dirs.join ":"}
library_dirs=#{library_dirs.join ":"}
EOS
end
def sitecustomize
xy = (prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
<<~EOS
# This file is created by Homebrew and is executed on each python startup.
# Don't print from here, or else python command line scripts may fail!
# <https://docs.brew.sh/Homebrew-and-Python>
import re
import os
import sys
if sys.version_info[0] != 3:
# This can only happen if the user has set the PYTHONPATH for 3.x and run Python 2.x or vice versa.
# Every Python looks at the PYTHONPATH variable and we can't fix it here in sitecustomize.py,
# because the PYTHONPATH is evaluated after the sitecustomize.py. Many modules (e.g. PyQt4) are
# built only for a specific version of Python and will fail with cryptic error messages.
# In the end this means: Don't set the PYTHONPATH permanently if you use different Python versions.
exit('Your PYTHONPATH points to a site-packages dir for Python 3.x but you are running Python ' +
str(sys.version_info[0]) + '.x!\\n PYTHONPATH is currently: "' + str(os.environ['PYTHONPATH']) + '"\\n' +
' You should `unset PYTHONPATH` to fix this.')
# Only do this for a brewed python:
if os.path.realpath(sys.executable).startswith('#{rack}'):
# Shuffle /Library site-packages to the end of sys.path
library_site = '/Library/Python/#{xy}/site-packages'
library_packages = [p for p in sys.path if p.startswith(library_site)]
sys.path = [p for p in sys.path if not p.startswith(library_site)]
# .pth files have already been processed so don't use addsitedir
sys.path.extend(library_packages)
# the Cellar site-packages is a symlink to the HOMEBREW_PREFIX
# site_packages; prefer the shorter paths
long_prefix = re.compile(r'#{rack}/[0-9\._abrc]+/Frameworks/Python\.framework/Versions/#{xy}/lib/python#{xy}/site-packages')
sys.path = [long_prefix.sub('#{HOMEBREW_PREFIX/"lib/python#{xy}/site-packages"}', p) for p in sys.path]
# Set the sys.executable to use the opt_prefix, unless explicitly set
# with PYTHONEXECUTABLE:
if 'PYTHONEXECUTABLE' not in os.environ:
sys.executable = '#{opt_bin}/python#{xy}'
EOS
end
def caveats
xy = if prefix.exist?
(prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
else
version.to_s.slice(/(3\.\d)/) || "3.8"
end
<<~EOS
Python has been installed as
#{opt_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>
They will install into the site-package directory
#{HOMEBREW_PREFIX/"lib/python#{xy}/site-packages"}
See: https://docs.brew.sh/Homebrew-and-Python
EOS
end
test do
xy = (prefix/"Frameworks/Python.framework/Versions").children.min.basename.to_s
# 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#{xy}", "-c", "import sqlite3"
# Check if some other modules import. Then the linked libs are working.
system "#{bin}/python#{xy}", "-c", "import tkinter; root = tkinter.Tk()"
system "#{bin}/python#{xy}", "-c", "import _gdbm"
system "#{bin}/python#{xy}", "-c", "import zlib"
system bin/"pip3", "list", "--format=columns"
end
end
__END__
diff --git a/setup.py b/setup.py
index 20d7f35..b9616d3 100644
--- a/setup.py
+++ b/setup.py
@@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
# Rather than complicate the code below, detecting and building
# AquaTk is a separate method. Only one Tkinter will be built on
# Darwin - either AquaTk, if it is found, or X11 based Tk.
- if (MACOS and self.detect_tkinter_darwin()):
- return True
# Assume we haven't found any of the libraries or include files
# The versions with dots are used on Unix, and the versions without
@@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
if dir not in include_dirs:
include_dirs.append(dir)
- # Check for various platform-specific directories
- if HOST_PLATFORM == 'sunos5':
- include_dirs.append('/usr/openwin/include')
- added_lib_dirs.append('/usr/openwin/lib')
- elif os.path.exists('/usr/X11R6/include'):
- include_dirs.append('/usr/X11R6/include')
- added_lib_dirs.append('/usr/X11R6/lib64')
- added_lib_dirs.append('/usr/X11R6/lib')
- elif os.path.exists('/usr/X11R5/include'):
- include_dirs.append('/usr/X11R5/include')
- added_lib_dirs.append('/usr/X11R5/lib')
- else:
- # Assume default location for X11
- include_dirs.append('/usr/X11/include')
- added_lib_dirs.append('/usr/X11/lib')
# If Cygwin, then verify that X is installed before proceeding
if CYGWIN:
@@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
libs.append('tk'+ version)
libs.append('tcl'+ version)
- # Finally, link with the X11 libraries (not appropriate on cygwin)
- if not CYGWIN:
- libs.append('X11')
# XXX handle these, but how to detect?
# *** Uncomment and edit for PIL (TkImaging) extension only:
@rd0fun
Copy link

rd0fun commented Nov 5, 2020

Been struggling for some time now, step 3 just doesn't seem to work

HOMEBREW_NO_AUTO_UPDATE=1 brew install --build-from-source python@3.8
==> Searching for similarly named formulae...
This similarly named formula was found:
python@3.8
To install it, run:
  brew install python@3.8
Error: No available formula or cask with the name "python@3.8".
==> Searching taps on GitHub...
Error: No formulae found in taps.

brew doctor shows the following

Warning: You have uncommitted modifications to Homebrew/homebrew-core.
If this is a surprise to you, then you should stash these modifications.
Stashing returns Homebrew to a pristine state but can be undone
should you later need to do so for some reason.
  cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash && git clean -d -f

Uncommitted files:
   M Formula/python@3.8.rb

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 5, 2020

@sergey-arkhipov Thanks for your input, your method is in fact faster - if you've already did this install once at least (xcode, brew no autoupdate, etc.).
Yes, I checked this way. Xcode is not necessary, but Command Line tools is necessary for compilation from source codes (homebrew demands Command Line tools, so it has to be already installed).
The described sequence of actions does not demand anything more, necessary dependencies will be installed in process. During of installation (REINSTALL !!!) the brew does not replace patched file. Certainly, at the following updates of versions this procedure should be made again, making changes in path, if python@3.8.rb will be replaced.(3.8.6 for now, path for 3.8.5)

@iexa
Copy link
Author

iexa commented Nov 5, 2020

@rd0fun if you type brew show python@3.8 what will it print? if it seems to not find a recipe, then there must be something wrong with the python@3.8.rb file. I had that first but fixed it (and fixed version is up here).

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 5, 2020

I have just tried this path for python homebrew version 3.9.
This works as described above. I have python@3.9 and tcl-tk already installed via Homebrew
Attached the full steps.

  1. brew upgrade
  2. path python@3.9.rb
  3. brew reinstall python@3.9 --build-from-source

++++++++++++++++++++++++++++++++++++++++++++++++++++
-> MBA ! ~ % python3 -V
Python 3.9.0
-> MBA ! ~ % echo "import tkinter as tk\nprint(tk.TkVersion,tk.TclVersion)" |python3
8.5 8.5

++++++++++++++++++++++++++++++++++++++++++++++++++++

-> MBA ! % colordiff python@3.9.rb python@3.9.pathed.rb

36a37
>   depends_on "tcl-tk"  # as apple's one is shiiiiite
77d77
< 
87c87
< 
---
>   patch :DATA
121c121,122
<       cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
---
>       #cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
>       cflags << "-I#{MacOS.sdk_path}/usr/local/opt/tcl-tk/include"
145c146,151
< 
---
>     
>     # ADD tcl-tk include / lib paths
>     tcl_tk = Formula["tcl-tk"].opt_prefix
>     cppflags << "-I#{tcl_tk}/include"
>     ldflags  << "-L#{tcl_tk}/lib"
>     
265c271,275
< 
---
>     
>     # Again tcl-tk
>     include_dirs << Formula["tcl-tk"].opt_include
>     library_dirs << Formula["tcl-tk"].opt_lib
>     
349a360,405
> __END__
> diff --git a/setup.py b/setup.py
> index 20d7f35..b9616d3 100644
> --- a/setup.py
> +++ b/setup.py
> @@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
>          # Rather than complicate the code below, detecting and building
>          # AquaTk is a separate method. Only one Tkinter will be built on
>          # Darwin - either AquaTk, if it is found, or X11 based Tk.
> -        if (MACOS and self.detect_tkinter_darwin()):
> -            return True
> 
>          # Assume we haven't found any of the libraries or include files
>          # The versions with dots are used on Unix, and the versions without
> @@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
>              if dir not in include_dirs:
>                  include_dirs.append(dir)
> 
> -        # Check for various platform-specific directories
> -        if HOST_PLATFORM == 'sunos5':
> -            include_dirs.append('/usr/openwin/include')
> -            added_lib_dirs.append('/usr/openwin/lib')
> -        elif os.path.exists('/usr/X11R6/include'):
> -            include_dirs.append('/usr/X11R6/include')
> -            added_lib_dirs.append('/usr/X11R6/lib64')
> -            added_lib_dirs.append('/usr/X11R6/lib')
> -        elif os.path.exists('/usr/X11R5/include'):
> -            include_dirs.append('/usr/X11R5/include')
> -            added_lib_dirs.append('/usr/X11R5/lib')
> -        else:
> -            # Assume default location for X11
> -            include_dirs.append('/usr/X11/include')
> -            added_lib_dirs.append('/usr/X11/lib')
> 
>          # If Cygwin, then verify that X is installed before proceeding
>          if CYGWIN:
> @@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
>          libs.append('tk'+ version)
>          libs.append('tcl'+ version)
> 
> -        # Finally, link with the X11 libraries (not appropriate on cygwin)
> -        if not CYGWIN:
> -            libs.append('X11')
> 
>          # XXX handle these, but how to detect?
>          # *** Uncomment and edit for PIL (TkImaging) extension only:

++++++++++++++++++++++++++++++++++++++++++++++++++++
-> MBA ! % cp python@3.9.pathed.rb /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/python@3.9.rb
overwrite /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/python@3.9.rb? (y/n [n]) y

++++++++++++++++++++++++++++++++++++++++++++++++++++
-> MBA ! ~/ownCloud/AS/Python/Patch/3.9 % brew reinstall python@3.9 --build-from-source
==> Downloading https://files.pythonhosted.org/packages/a7/e0/30642b9c2df516506d40b563b0cbd080c49c6b3f11a70b4c7a670f13a78b/setuptools-50.3.2.zip
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/6c4cd84935cccfee61e433509bdda7951ea6b77ae5db203b1e708eea72d93603--setuptools-50.3.2.zip
==> Downloading https://files.pythonhosted.org/packages/0b/f5/be8e741434a4bf4ce5dbc235aa28ed0666178ea8986ddc10d035023744e6/pip-20.2.4.tar.gz
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/8420c2f6f4c2831dfbd1b0e1caa05c0c044729c31b52f8884a785a56038ad0e7--pip-20.2.4.tar.gz
==> Downloading https://files.pythonhosted.org/packages/83/72/611c121b6bd15479cb62f1a425b2e3372e121b324228df28e64cc28b01c2/wheel-0.35.1.tar.gz
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/1aa1a9563d6af09f2712c180679dfd512aac6c710fc3fb573175e88eaa7c6de3--wheel-0.35.1.tar.gz
==> Downloading https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tar.xz
Already downloaded: /Users/as/Library/Caches/Homebrew/downloads/d37370983bfa2dfe731256050c2097e61210550756783e4623a6eb9a8812b210--Python-3.9.0.tar.xz
==> Reinstalling python@3.9
==> Patching
==> ./configure --prefix=/usr/local/Cellar/python@3.9/3.9.0_1 --enable-ipv6 --datarootdir=/usr/local/Cellar/python@3.9/3.9.0_1/share --datadir=/usr/local/Cellar
==> make
==> make install PYTHONAPPSDIR=/usr/local/Cellar/python@3.9/3.9.0_1
==> make frameworkinstallextras PYTHONAPPSDIR=/usr/local/Cellar/python@3.9/3.9.0_1/share/python@3.9
Unlinking /usr/local/Cellar/python@3.8/3.8.6_1... 9 symlinks removed
==> /usr/local/Cellar/python@3.9/3.9.0_1/bin/python3 -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python@3.9/3.9.0_1/
==> /usr/local/Cellar/python@3.9/3.9.0_1/bin/python3 -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python@3.9/3.9.0_1/
==> /usr/local/Cellar/python@3.9/3.9.0_1/bin/python3 -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python@3.9/3.9.0_1/
==> Caveats
Python has been installed as
/usr/local/bin/python3

Unversioned symlinks python, python-config, pip etc. pointing to
python3, python3-config, pip3 etc., respectively, have been installed into
/usr/local/opt/python@3.9/libexec/bin

You can install Python packages with
pip3 install
They will install into the site-package directory
/usr/local/lib/python3.9/site-packages

See: https://docs.brew.sh/Homebrew-and-Python
==> Summary
🍺 /usr/local/Cellar/python@3.9/3.9.0_1: 9,224 files, 136.2MB, built in 3 minutes 28 seconds
++++++++++++++++++++++++++++++++++++++++++++++++++++

-> MBA ! % echo "import tkinter as tk\nprint(tk.TkVersion,tk.TclVersion)" |python3
8.6 8.6

-> MBA ! % date
Thu Nov 5 23:12:20 MSK 2020

@rd0fun
Copy link

rd0fun commented Nov 5, 2020

Is this a problem with my version of brew?

$ brew show
Error: Unknown command: show
brew --version
Homebrew 2.5.8
Homebrew/homebrew-core (git revision a0e08; last commit 2020-11-05)
Homebrew/homebrew-cask (git revision 97d5ff; last commit 2020-11-05)

@iexa
Copy link
Author

iexa commented Nov 6, 2020

@rd0fun sorry, I mixed it up, do brew info python@3.8 -- not show... there are so many command line tools I use (brew, node, pip, npm, yarn, etc.) i just try each option until one works with each one of them.

@iexa
Copy link
Author

iexa commented Nov 6, 2020

@sergey-arkhipov -- good to know that python 3.9 works as well. I know there's not much change from 3.8 -> 3.9 (like before the walrus operator for instance and f-string speedups) - some speedups for sure. Once it hits 3.9.2 or so I will update.

Do you have any problems with any pip packages on 3.9? I mean packages that have native parts and not just pure python.

@sergey-arkhipov
Copy link

sergey-arkhipov commented Nov 6, 2020

Do you have any problems with any pip packages on 3.9? I mean packages that have native parts and not just pure python.

I haven't faced yet any problems just now :-)

+++++++++++++++++++++++++++++++++++

-> MBA ! ~ % pip3 -V
pip 20.2.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
-> MBA ! ~ % pip3 list outdated
Package    Version
---------- -------
pip        20.2.4
setuptools 50.3.2
wheel      0.35.1
-> MBA ! ~ % pip3 list --outdated 
-> MBA ! ~ % pip3 install numpy
Collecting numpy
  Downloading numpy-1.19.4-cp39-cp39-macosx_10_9_x86_64.whl (15.4 MB)
     |████████████████████████████████| 15.4 MB 12.8 MB/s 
Installing collected packages: numpy
Successfully installed numpy-1.19.4
 -> MBA ! ~ % echo "import numpy as np\na = np.arange(15).reshape(3, 5)\nprint(a)\nprint(a.ndim)" |python3
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
2
-> MBA ! ~ % 

+++++++++++++++++++++++++++++++++++

@iexa
Copy link
Author

iexa commented Nov 6, 2020

Ok, good to know it's fine. I like your piping of a small python code string into the python interpreter. It got me for a bit until I saw the |.

@a4840639
Copy link

Apparently you now need to rename the classname from Python to PythonAT38
Took me a while to figure this out

@sergey-arkhipov
Copy link

I can confirm that it works at Mac OS Big Sur. I used the same patch and steps, described above.

-> mba ! ~ % sw_vers          
ProductName:	macOS
ProductVersion:	11.0.1
BuildVersion:	20B29
-> mba ! ~ % python3 -V
Python 3.9.0
-> mba ! ~ % echo "import tkinter as tk\nprint(tk.TkVersion,tk.TclVersion)" |python3
8.6 8.6
-> mba ! ~ % date
Tue Nov 24 01:37:38 MSK 2020
-> mba ! ~ % 

@sergey-arkhipov
Copy link

-> mba ! ~ % colordiff -Naur python@3.9.rb python@3.9.pathed.rb
--- python@3.9.rb	2020-11-24 01:04:58.000000000 +0300
+++ python@3.9.pathed.rb	2020-11-24 01:45:40.000000000 +0300
@@ -34,6 +34,7 @@
   depends_on "readline"
   depends_on "sqlite"
   depends_on "xz"
+  depends_on "tcl-tk"  # as apple's one is shiiiiite
 
   uses_from_macos "bzip2"
   uses_from_macos "libffi"
@@ -85,6 +86,7 @@
     end
   end
 
+  patch :DATA
   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.
@@ -118,7 +120,8 @@
       # For the Xlib.h, Python needs this header dir with the system Tk
       # Yep, this needs the absolute path where zlib needed a path relative
       # to the SDK.
-      cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
+      #cflags << "-I#{MacOS.sdk_path}/System/Library/Frameworks/Tk.framework/Versions/8.5/Headers"
+      cflags << "-I#{MacOS.sdk_path}/usr/local/opt/tcl-tk/include"
     end
     # Avoid linking to libgcc https://mail.python.org/pipermail/python-dev/2012-February/116205.html
     args << "MACOSX_DEPLOYMENT_TARGET=#{MacOS.version}"
@@ -142,7 +145,12 @@
       f.gsub! "DEFAULT_LIBRARY_FALLBACK = [", "DEFAULT_LIBRARY_FALLBACK = [ '#{HOMEBREW_PREFIX}/lib',"
       f.gsub! "DEFAULT_FRAMEWORK_FALLBACK = [", "DEFAULT_FRAMEWORK_FALLBACK = [ '#{HOMEBREW_PREFIX}/Frameworks',"
     end
-
+    
+    # ADD tcl-tk include / lib paths
+    tcl_tk = Formula["tcl-tk"].opt_prefix
+    cppflags << "-I#{tcl_tk}/include"
+    ldflags  << "-L#{tcl_tk}/lib"
+    
     args << "CFLAGS=#{cflags.join(" ")}" unless cflags.empty?
     args << "LDFLAGS=#{ldflags.join(" ")}" unless ldflags.empty?
     args << "CPPFLAGS=#{cppflags.join(" ")}" unless cppflags.empty?
@@ -262,7 +270,11 @@
                     Formula["sqlite"].opt_include]
     library_dirs = [HOMEBREW_PREFIX/"lib", Formula["openssl@1.1"].opt_lib,
                     Formula["sqlite"].opt_lib]
-
+    
+    # Again tcl-tk
+    include_dirs << Formula["tcl-tk"].opt_include
+    library_dirs << Formula["tcl-tk"].opt_lib
+    
     cfg = prefix/"Frameworks/Python.framework/Versions/#{xy}/lib/python#{xy}/distutils/distutils.cfg"
 
     cfg.atomic_write <<~EOS
@@ -347,3 +359,49 @@
     system bin/"pip3", "list", "--format=columns"
   end
 end
+__END__
+diff --git a/setup.py b/setup.py
+index 20d7f35..b9616d3 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1851,8 +1851,6 @@ class PyBuildExt(build_ext):
+         # Rather than complicate the code below, detecting and building
+         # AquaTk is a separate method. Only one Tkinter will be built on
+         # Darwin - either AquaTk, if it is found, or X11 based Tk.
+-        if (MACOS and self.detect_tkinter_darwin()):
+-            return True
+
+         # Assume we haven't found any of the libraries or include files
+         # The versions with dots are used on Unix, and the versions without
+@@ -1901,21 +1899,6 @@ class PyBuildExt(build_ext):
+             if dir not in include_dirs:
+                 include_dirs.append(dir)
+
+-        # Check for various platform-specific directories
+-        if HOST_PLATFORM == 'sunos5':
+-            include_dirs.append('/usr/openwin/include')
+-            added_lib_dirs.append('/usr/openwin/lib')
+-        elif os.path.exists('/usr/X11R6/include'):
+-            include_dirs.append('/usr/X11R6/include')
+-            added_lib_dirs.append('/usr/X11R6/lib64')
+-            added_lib_dirs.append('/usr/X11R6/lib')
+-        elif os.path.exists('/usr/X11R5/include'):
+-            include_dirs.append('/usr/X11R5/include')
+-            added_lib_dirs.append('/usr/X11R5/lib')
+-        else:
+-            # Assume default location for X11
+-            include_dirs.append('/usr/X11/include')
+-            added_lib_dirs.append('/usr/X11/lib')
+
+         # If Cygwin, then verify that X is installed before proceeding
+         if CYGWIN:
+@@ -1937,9 +1920,6 @@ class PyBuildExt(build_ext):
+         libs.append('tk'+ version)
+         libs.append('tcl'+ version)
+
+-        # Finally, link with the X11 libraries (not appropriate on cygwin)
+-        if not CYGWIN:
+-            libs.append('X11')
+
+         # XXX handle these, but how to detect?
+         # *** Uncomment and edit for PIL (TkImaging) extension only:

@iexa
Copy link
Author

iexa commented Nov 27, 2020

@sergey-arkhipov thanks for the info - i wont update to big sur for a good while so thanks for testing it out.

@neilyoung
Copy link

neilyoung commented Nov 27, 2020

I had to change the first line of this gist to match the first line of the existing python@3.8.rb:

class PythonAT38 < Formula

otherwise the error was Error: No available formula or cask with the name "python@3.8.rb".

I was a bit irritated about the diff statement in the .rb, but this was no problem.

Mac OS Catalina 10.15.7.

EDIT: Even though tk sources have been downloaded, this gist didn't bring me TK support

EDIT_2: Got it working now

@iexa
Copy link
Author

iexa commented Dec 1, 2020

The homebrew package changed it. I'll update to 3.9 once 3.9.1 or 3.9.2 is out. Then this change won't be necessary.

@jimmybrancaccio
Copy link

I'd love to see this get updated for 3.9.1. I had a look myself but couldn't seem to figure out the setup.py bit. ☹️

@dhinakg
Copy link

dhinakg commented Feb 19, 2021

With Homebrew/homebrew-core@e41f896, this doesn't seem to be needed anymore. Can anyone confirm?
image

@jimmybrancaccio
Copy link

Looks like you're right @dhinakg 👍 🎉

@tomoyanonymous
Copy link

Homebrew/homebrew-core@80412c2#diff-38ae209ebc6d2954d5532ae8c3e6e579dc77a7d3002bed515fa930d6ea528139

Now tkinter is newly in python-tk formula. If you fail to execute tkinter, just run brew update && brew install python-tk .

@iexa
Copy link
Author

iexa commented Jun 24, 2021

So finally tk made its way back to brew. It's back in the official repo so I'm glad :)
https://github.com/Homebrew/homebrew-core/blob/master/Formula/python-tk@3.9.rb

https://www.youtube.com/watch?v=d-diB65scQU

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment