aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/requirements/python_dependency.rb
diff options
context:
space:
mode:
authorSamuel John2013-06-17 09:06:38 +0200
committerSamuel John2013-06-18 10:30:17 +0200
commit2c8c8d07f6f108533f5b6d9650e1fcdf9929a937 (patch)
treeeb5c7af52cbd6cdaf88a79951ab52ce70cf2c3c3 /Library/Homebrew/requirements/python_dependency.rb
parentf393f6da8c34b91910fa2d1fe5ca5931a5004241 (diff)
downloadhomebrew-2c8c8d07f6f108533f5b6d9650e1fcdf9929a937.tar.bz2
Python module deps, ext. python fix and 10.6 fix
* Fixes #20572 by tweaking the logic that decides which python is used by the `python` object inside a formula. There was a bug when on 10.6 there is no Python 2.7 but a :recommended Python was still treated as being available. * Use the user's PATH when looking for an external Python. Until now only brewed or OS X system's python have been found by `depends_on :python`. But now we support any Python in PATH (e.g. pyenv's python). * Further, instead of handling python modules and import tests in LanguageModuleDependency, these are now handled by: depends_on :python => 'numpy' # for example The old style depends_on 'numpy' => :python is still supported and is only an alias for the newer style (only for :python, the other languages are not altered by this commit). The reasoning is that if a formula requires a python module, it basically also needs python itself - and further that specific version of python has to provide the module. So the `PythonInstalled` is the natural place to check for the availability of a python module. Using a python module and other tags like :optional or :recommended is done like so: depends_on :python => [:optional, 'numpy'] Specifying another PyPi (Python Package index) name than the module import name is seldom used but supported, too: depends_on :python => ['enchant'=>'pyenchant'] A last note: For clarity, you can define multiple depends_on statements with different modules to be importable.`
Diffstat (limited to 'Library/Homebrew/requirements/python_dependency.rb')
-rw-r--r--Library/Homebrew/requirements/python_dependency.rb63
1 files changed, 52 insertions, 11 deletions
diff --git a/Library/Homebrew/requirements/python_dependency.rb b/Library/Homebrew/requirements/python_dependency.rb
index c3753d813..610bc1c6b 100644
--- a/Library/Homebrew/requirements/python_dependency.rb
+++ b/Library/Homebrew/requirements/python_dependency.rb
@@ -31,13 +31,12 @@ class PythonInstalled < Requirement
end
end
- def initialize(*tags)
+ def initialize(version="2.6", *tags )
# Extract the min_version if given. Default to python 2.X else
- tags.flatten!
- if /(\d+\.)*\d+/ === tags.first
- @min_version = PythonVersion.new(tags.shift)
+ if /(\d+\.)*\d+/ === version.to_s
+ @min_version = PythonVersion.new(version)
else
- @min_version = PythonVersion.new("2.6") # default
+ raise "Invalid version specification for Python: '#{version}'"
end
# often used idiom: e.g. sipdir = "share/sip" + python.if3then3
@@ -51,6 +50,18 @@ class PythonInstalled < Requirement
# The name is used to generate the options like --without-python3
@name = "python" + @if3then3
+ # Check if any python modules should be importable. We use a hash to store
+ # the corresponding name on PyPi "<import_name>" => "<name_on_PyPi>".
+ # Example: `depends_on :python => ['enchant' => 'pyenchant']
+ @imports = {}
+ tags.each do |tag|
+ if tag.kind_of? String
+ @imports[tag] = tag
+ elsif tag.kind_of? Hash
+ @imports.merge!(tag)
+ end
+ end
+
# will be set later by the python_helper, because it needs the
# formula prefix to set site_packages
@site_packages = nil
@@ -78,10 +89,29 @@ class PythonInstalled < Requirement
elsif @min_version.major == 2 && `python -c "import sys; print(sys.version_info[0])"`.strip == "3"
@unsatisfied_because += "Your `python` points to a Python 3.x. This is not supported."
else
- true
+ @imports.keys.map do |module_name|
+ if not importable? module_name
+ @unsatisfied_because += "Unsatisfied dependency: #{module_name}\n"
+ @unsatisfied_because += "OS X System's " if from_osx?
+ @unsatisfied_because += "Brewed " if brewed?
+ @unsatisfied_because += "External " unless brewed? || from_osx?
+ @unsatisfied_because += "Python cannot `import #{module_name}`. Install with:\n "
+ unless importable? 'pip'
+ @unsatisfied_because += "sudo easy_install pip\n "
+ end
+ @unsatisfied_because += "pip-#{version.major}.#{version.minor} install #{@imports[module_name]}"
+ false
+ else
+ true
+ end
+ end.all? # all given `module_name`s have to be `importable?`
end
end
+ def importable? module_name
+ quiet_system(binary, "-c", "import #{module_name}")
+ end
+
# The full path to the python or python3 executable, depending on `version`.
def binary
@binary ||= begin
@@ -90,8 +120,15 @@ class PythonInstalled < Requirement
# Note, we don't support homebrew/versions/pythonXX.rb, though.
Formula.factory(@name).opt_prefix/"bin/python#{@min_version.major}"
else
- # This should find at least system python, because /usr/bin is in PATH:
- which(@name)
+ begin
+ # Using the ORIGINAL_PATHS here because in superenv, the user
+ # installed external Python is not visible otherwise.
+ tmp_PATH = ENV['PATH']
+ ENV['PATH'] = ORIGINAL_PATHS.join(':')
+ which(@name)
+ ensure
+ ENV['PATH'] = tmp_PATH
+ end
end
end
end
@@ -257,7 +294,7 @@ class PythonInstalled < Requirement
import sys
if sys.version_info[0] == #{version.major} and sys.version_info[1] == #{version.minor}:
- if sys.executable.startswith('#{HOMEBREW_PREFIX}'):
+ if sys.executable.startswith('#{HOMEBREW_PREFIX}/opt/python'):
# Fix 1)
# A setuptools.pth and/or easy-install.pth sitting either in
# /Library/Python/2.7/site-packages or in
@@ -285,7 +322,7 @@ class PythonInstalled < Requirement
from _sysconfigdata import build_time_vars
build_time_vars['LINKFORSHARED'] = '-u _PyMac_Error #{HOMEBREW_PREFIX}/opt/#{name}/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/Python'
except:
- pass # remember: don't print here. Better to fail silent.
+ pass # remember: don't print here. Better to fail silently.
# Fix 5)
# For all Pythons of the right major.minor version: Tell about homebrew's
# site-packages location. This is needed for Python to parse *.pth.
@@ -307,6 +344,10 @@ class PythonInstalled < Requirement
end
def hash
- to_s.hash
+ # Requirements are a ComparableSet. So we define our identity by the
+ # selected python binary plus the @imports in order to support multiple:
+ # depends_on :python => 'module1'
+ # depends_on :python => 'module2'
+ (binary.to_s+@imports.to_s).hash
end
end