parent
							
								
									cb024e222c
								
							
						
					
					
						commit
						28143fb653
					
				@ -74,9 +74,6 @@ class DependencyCollector
 | 
				
			|||||||
    if tags.empty?
 | 
					    if tags.empty?
 | 
				
			||||||
      Dependency.new(spec, tags)
 | 
					      Dependency.new(spec, tags)
 | 
				
			||||||
    elsif (tag = tags.first) && LANGUAGE_MODULES.include?(tag)
 | 
					    elsif (tag = tags.first) && LANGUAGE_MODULES.include?(tag)
 | 
				
			||||||
      # Next line only for legacy support of `depends_on 'module' => :python`
 | 
					 | 
				
			||||||
      # It should be replaced by `depends_on :python => 'module'`
 | 
					 | 
				
			||||||
      return PythonDependency.new("2", Array(spec)) if tag == :python
 | 
					 | 
				
			||||||
      LanguageModuleDependency.new(tag, spec)
 | 
					      LanguageModuleDependency.new(tag, spec)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      Dependency.new(spec, tags)
 | 
					      Dependency.new(spec, tags)
 | 
				
			||||||
@ -105,8 +102,9 @@ class DependencyCollector
 | 
				
			|||||||
    when :clt        then CLTDependency.new(tags)
 | 
					    when :clt        then CLTDependency.new(tags)
 | 
				
			||||||
    when :arch       then ArchRequirement.new(tags)
 | 
					    when :arch       then ArchRequirement.new(tags)
 | 
				
			||||||
    when :hg         then MercurialDependency.new(tags)
 | 
					    when :hg         then MercurialDependency.new(tags)
 | 
				
			||||||
    when :python, :python2 then PythonDependency.new("2", tags)
 | 
					    # python2 is deprecated
 | 
				
			||||||
    when :python3    then PythonDependency.new("3", tags)
 | 
					    when :python, :python2 then PythonDependency.new(tags)
 | 
				
			||||||
 | 
					    when :python3    then Python3Dependency.new(tags)
 | 
				
			||||||
    # Tiger's ld is too old to properly link some software
 | 
					    # Tiger's ld is too old to properly link some software
 | 
				
			||||||
    when :ld64       then LD64Dependency.new if MacOS.version < :leopard
 | 
					    when :ld64       then LD64Dependency.new if MacOS.version < :leopard
 | 
				
			||||||
    when :ant        then ant_dep(spec, tags)
 | 
					    when :ant        then ant_dep(spec, tags)
 | 
				
			||||||
 | 
				
			|||||||
@ -340,24 +340,14 @@ class Formula
 | 
				
			|||||||
    ]
 | 
					    ]
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Install python bindings inside of a block given to this method and/or
 | 
					  # Deprecated
 | 
				
			||||||
  # call python so: `system python, "setup.py", "install", "--prefix=#{prefix}"
 | 
					  def python(options={}, &block)
 | 
				
			||||||
  # Note that there are no quotation marks around python!
 | 
					    opoo 'Formula#python is deprecated and will go away shortly.'
 | 
				
			||||||
  # <https://github.com/Homebrew/homebrew/wiki/Homebrew-and-Python>
 | 
					    block.call if block_given?
 | 
				
			||||||
  def python(options={:allowed_major_versions => [2, 3]}, &block)
 | 
					    PythonDependency.new
 | 
				
			||||||
    require 'python_helper'
 | 
					 | 
				
			||||||
    python_helper(options, &block)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Explicitly only execute the block for 2.x (if a python 2.x is available)
 | 
					 | 
				
			||||||
  def python2 &block
 | 
					 | 
				
			||||||
    python(:allowed_major_versions => [2], &block)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Explicitly only execute the block for 3.x (if a python 3.x is available)
 | 
					 | 
				
			||||||
  def python3 &block
 | 
					 | 
				
			||||||
    python(:allowed_major_versions => [3], &block)
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					  alias_method :python2, :python
 | 
				
			||||||
 | 
					  alias_method :python3, :python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Generates a formula's ruby class name from a formula's name
 | 
					  # Generates a formula's ruby class name from a formula's name
 | 
				
			||||||
  def self.class_s name
 | 
					  def self.class_s name
 | 
				
			||||||
 | 
				
			|||||||
@ -1,90 +0,0 @@
 | 
				
			|||||||
# This helper method is used in the Formula class when the user calls
 | 
					 | 
				
			||||||
# `python`, `python2` or `python3`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# This method has a dual nature. For one, it takes a &block and sets up
 | 
					 | 
				
			||||||
# the ENV such that a Python, as defined in the requirements, is the default.
 | 
					 | 
				
			||||||
# If there are multiple `PythonDependency` requirements, the block is evaluated
 | 
					 | 
				
			||||||
# once for each Python. This makes it possible to easily support 2.x and
 | 
					 | 
				
			||||||
# 3.x Python bindings without code duplication in formulae.
 | 
					 | 
				
			||||||
# If you need to special case stuff, set :allowed_major_versions.
 | 
					 | 
				
			||||||
# Second, inside the block, a formula author may call this method to access
 | 
					 | 
				
			||||||
# certain convienience methods for the currently selected Python, e.g.
 | 
					 | 
				
			||||||
# `python.site_packages`.
 | 
					 | 
				
			||||||
# This method should be executed in the context of the formula, so that
 | 
					 | 
				
			||||||
# prefix is defined. Note, that this method will set @current_python to be
 | 
					 | 
				
			||||||
# able to refer to the current python if a block is executed for 2.x and 3.x.
 | 
					 | 
				
			||||||
def python_helper(options={:allowed_major_versions => [2, 3]}, &block)
 | 
					 | 
				
			||||||
  if !block_given? and !@current_python.nil?
 | 
					 | 
				
			||||||
    # We are already inside of a `python do ... end` block, so just return
 | 
					 | 
				
			||||||
    # the current_python or nil if the version.major is not allowed.
 | 
					 | 
				
			||||||
    if options[:allowed_major_versions].include?(@current_python.version.major)
 | 
					 | 
				
			||||||
      return @current_python
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      return nil
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Look for PythonDependency requirements for this formula:
 | 
					 | 
				
			||||||
  python_reqs = requirements.select{ |r| r.kind_of?(PythonDependency) }
 | 
					 | 
				
			||||||
  if python_reqs.empty?
 | 
					 | 
				
			||||||
    raise "If you use python in the formula, you have to add `depends_on :python` (or :python3)!"
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
  # Now select those that are satisfied and matching the version.major and
 | 
					 | 
				
			||||||
  # check that no two python binaries are the same (which could be the case
 | 
					 | 
				
			||||||
  # because more than one `depends_on :python => 'module_name' may be present).
 | 
					 | 
				
			||||||
  filtered_python_reqs = []
 | 
					 | 
				
			||||||
  python_reqs.each do |py|
 | 
					 | 
				
			||||||
    next if filtered_python_reqs.any? { |req| req.binary == py.binary }
 | 
					 | 
				
			||||||
    next unless py.satisfied?
 | 
					 | 
				
			||||||
    next unless options[:allowed_major_versions].include?(py.version.major)
 | 
					 | 
				
			||||||
    next if (py.optional? || py.recommended?) && build.without?(py.name)
 | 
					 | 
				
			||||||
    filtered_python_reqs << py
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Allow to use an else-branch like so: `if python do ... end; else ... end`.
 | 
					 | 
				
			||||||
  return nil if filtered_python_reqs.empty?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Sort by version, so the older 2.x will be used first and if no
 | 
					 | 
				
			||||||
  # block_given? then 2.x is preferred because it is returned.
 | 
					 | 
				
			||||||
  # Further note, having 3.x last allows us to run `2to3 --write .`
 | 
					 | 
				
			||||||
  # which modifies the sources in-place (for some packages that need this).
 | 
					 | 
				
			||||||
  filtered_python_reqs.sort_by{ |py| py.version }.map do |py|
 | 
					 | 
				
			||||||
    # Now is the time to `site_packages` to the correct value in the Cellar.
 | 
					 | 
				
			||||||
    py.site_packages = lib/py.xy/'site-packages'
 | 
					 | 
				
			||||||
    py.private_site_packages = libexec/"lib"/py.xy/"site-packages"
 | 
					 | 
				
			||||||
    return py if !block_given?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    puts "brew: Python block (#{py.binary})..." if ARGV.verbose? && ARGV.debug?
 | 
					 | 
				
			||||||
    # Ensure env changes are only temporary:
 | 
					 | 
				
			||||||
    old_env = ENV.to_hash
 | 
					 | 
				
			||||||
    begin
 | 
					 | 
				
			||||||
      # In order to install into the `Cellar`, the dir must exist and be in the
 | 
					 | 
				
			||||||
      # `PYTHONPATH`. This will be executed in the context of the formula and
 | 
					 | 
				
			||||||
      # lib points to the `HOMEBREW_PREFIX/Cellar/<formula>/<version>/lib`.
 | 
					 | 
				
			||||||
      mkdir_p py.site_packages
 | 
					 | 
				
			||||||
      ENV.append_path 'PYTHONPATH', py.site_packages
 | 
					 | 
				
			||||||
      # Allow to --prefix=libexec if a private site-packages is needed.
 | 
					 | 
				
			||||||
      mkdir_p py.private_site_packages
 | 
					 | 
				
			||||||
      ENV.append_path 'PYTHONPATH', py.private_site_packages
 | 
					 | 
				
			||||||
      puts "brew: PYTHONPATH=#{ENV['PYTHONPATH']}" if ARGV.verbose?
 | 
					 | 
				
			||||||
      ENV['PYTHON'] = py.binary
 | 
					 | 
				
			||||||
      ENV.prepend_path 'CMAKE_INCLUDE_PATH', py.incdir
 | 
					 | 
				
			||||||
      ENV.prepend_path 'PKG_CONFIG_PATH', py.pkg_config_path if py.pkg_config_path
 | 
					 | 
				
			||||||
      ENV.prepend_path 'PATH', py.binary.dirname unless py.from_osx?
 | 
					 | 
				
			||||||
      #Note: Don't set LDFLAGS to point to the Python.framework, because
 | 
					 | 
				
			||||||
      #      it breaks builds (for example scipy.)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      # Track the state of the currently selected python for this block,
 | 
					 | 
				
			||||||
      # so if this python_helper is called again _inside_ the block,
 | 
					 | 
				
			||||||
      # we can just return the right python.
 | 
					 | 
				
			||||||
      @current_python = py
 | 
					 | 
				
			||||||
      res = instance_eval(&block)
 | 
					 | 
				
			||||||
      @current_python = nil
 | 
					 | 
				
			||||||
      res
 | 
					 | 
				
			||||||
    ensure
 | 
					 | 
				
			||||||
      # Clean up if the private_site_packages has not been used.
 | 
					 | 
				
			||||||
      py.private_site_packages.rmdir if py.private_site_packages.children.empty?
 | 
					 | 
				
			||||||
      ENV.replace(old_env)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
@ -1,365 +1,42 @@
 | 
				
			|||||||
require 'requirement'
 | 
					require 'requirement'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# We support Python 2.x and 3.x, either brewed or external.
 | 
					 | 
				
			||||||
# This requirement locates the correct CPython binary (no PyPy), provides
 | 
					 | 
				
			||||||
# support methods like `site_packages`, and writes our sitecustomize.py file.
 | 
					 | 
				
			||||||
# In `dependency_collector.rb`, special `:python` and `:python3` shortcuts are
 | 
					 | 
				
			||||||
# defined. You can specify a minimum version of the Python that needs to be
 | 
					 | 
				
			||||||
# present, but since not every package is ported to 3.x yet,
 | 
					 | 
				
			||||||
# `PythonDependency("2")` is not satisfied by 3.x.
 | 
					 | 
				
			||||||
# In a formula that shall provide support for 2.x and 3.x, the idiom is:
 | 
					 | 
				
			||||||
# depends_on :python
 | 
					 | 
				
			||||||
# depends_on :python3 => :optional # or :recommended
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Todo:
 | 
					 | 
				
			||||||
# - Allow further options that choose: universal, framework?, brewed?...
 | 
					 | 
				
			||||||
class PythonDependency < Requirement
 | 
					class PythonDependency < Requirement
 | 
				
			||||||
  attr_reader :min_version
 | 
					  fatal true
 | 
				
			||||||
  attr_reader :if3then3
 | 
					 | 
				
			||||||
  attr_reader :imports
 | 
					 | 
				
			||||||
  attr_reader :python
 | 
					 | 
				
			||||||
  attr_accessor :site_packages
 | 
					 | 
				
			||||||
  attr_accessor :private_site_packages
 | 
					 | 
				
			||||||
  attr_writer :binary # The python.rb formula needs to set the binary
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fatal true  # you can still make Python optional by `depends_on :python => :optional`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  class PythonVersion < Version
 | 
					 | 
				
			||||||
    def major
 | 
					 | 
				
			||||||
      tokens[0].to_s.to_i  # Python's major.minor are always ints.
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    def minor
 | 
					 | 
				
			||||||
      tokens[1].to_s.to_i
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def initialize(default_version="2.6", tags=[])
 | 
					 | 
				
			||||||
    # Extract the min_version if given. Default to default_version else
 | 
					 | 
				
			||||||
    if /(\d+\.)*\d+/ === tags.first.to_s
 | 
					 | 
				
			||||||
      @min_version = PythonVersion.new(tags.shift)
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      @min_version = PythonVersion.new(default_version)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # often used idiom: e.g. sipdir = "share/sip#{python.if3then3}"
 | 
					 | 
				
			||||||
    if @min_version.major == 3
 | 
					 | 
				
			||||||
      @if3then3 = "3"
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      @if3then3 = ""
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @python = "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  # if the module name is the same as the PyPi name
 | 
					 | 
				
			||||||
      elsif tag.kind_of? Hash
 | 
					 | 
				
			||||||
        @imports.merge!(tag)
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Set name according to the major version and optionally python modules:
 | 
					 | 
				
			||||||
    # Used to generate the options like --without-python3, --with-python-numpy
 | 
					 | 
				
			||||||
    @name = "python#{@if3then3}"
 | 
					 | 
				
			||||||
    @name += "-#{@imports.values*'-'}" unless @imports.empty?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # will be set later by the python_helper, because it needs the
 | 
					 | 
				
			||||||
    # formula prefix to set site_packages
 | 
					 | 
				
			||||||
    @site_packages = nil
 | 
					 | 
				
			||||||
    @private_site_packages = nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    super tags
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Note that during `satisfy` we still have the PATH as the user has set.
 | 
					 | 
				
			||||||
  # We look for a brewed python or an external Python and store the loc of
 | 
					 | 
				
			||||||
  # that binary for later usage. (See Formula#python)
 | 
					 | 
				
			||||||
  satisfy :build_env => false do
 | 
					  satisfy :build_env => false do
 | 
				
			||||||
    begin
 | 
					    which python_binary
 | 
				
			||||||
      # Unset the PYTHONPATH during these tests, but later ensure it is restored.
 | 
					 | 
				
			||||||
      pythonpath = ENV['PYTHONPATH']
 | 
					 | 
				
			||||||
      ENV['PYTHONPATH'] = nil
 | 
					 | 
				
			||||||
      @unsatisfied_because = ''
 | 
					 | 
				
			||||||
      if binary.nil? || !binary.executable?
 | 
					 | 
				
			||||||
        @unsatisfied_because += "No `#{@python}` found in your PATH. To install with Homebrew use `brew install #{@python}`."
 | 
					 | 
				
			||||||
        false
 | 
					 | 
				
			||||||
      elsif pypy?
 | 
					 | 
				
			||||||
        @unsatisfied_because += "Your #{@python} executable appears to be a PyPy, which is not supported."
 | 
					 | 
				
			||||||
        false
 | 
					 | 
				
			||||||
      elsif version.major != @min_version.major
 | 
					 | 
				
			||||||
        @unsatisfied_because += "No Python #{@min_version.major}.x found in your PATH! --> `brew install #{@python}`?"
 | 
					 | 
				
			||||||
        false
 | 
					 | 
				
			||||||
      elsif version < @min_version
 | 
					 | 
				
			||||||
        @unsatisfied_because += "Python version #{version} is too old (need at least #{@min_version})."
 | 
					 | 
				
			||||||
        false
 | 
					 | 
				
			||||||
      elsif @min_version.major == 2 && `python -c "import sys; print(sys.version_info[0])"`.strip == "3"
 | 
					 | 
				
			||||||
        @unsatisfied_because += "Your `python` points to Python 3.x; this is not supported."
 | 
					 | 
				
			||||||
        false
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        @imports.keys.all? do |module_name|
 | 
					 | 
				
			||||||
          if importable? module_name
 | 
					 | 
				
			||||||
            true
 | 
					 | 
				
			||||||
          else
 | 
					 | 
				
			||||||
            @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  "
 | 
					 | 
				
			||||||
            @unsatisfied_because += "sudo easy_install pip\n  " unless importable? 'pip'
 | 
					 | 
				
			||||||
            @unsatisfied_because += "pip-#{version.major}.#{version.minor} install #{@imports[module_name]}"
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
          end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    ensure
 | 
					 | 
				
			||||||
      ENV['PYTHONPATH'] = pythonpath
 | 
					 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
      if brewed?
 | 
					 | 
				
			||||||
        # If the python is brewed we always prefer it!
 | 
					 | 
				
			||||||
        # Note, we don't support homebrew/versions/pythonXX.rb, though.
 | 
					 | 
				
			||||||
        Formula.factory(@python).opt_prefix/"bin/python#{@min_version.major}"
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        which(@python)
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # The python prefix (special cased for a brewed python to point into the opt_prefix)
 | 
					 | 
				
			||||||
  def prefix
 | 
					 | 
				
			||||||
    if brewed?
 | 
					 | 
				
			||||||
      # Homebrew since a long while only supports frameworked python
 | 
					 | 
				
			||||||
      HOMEBREW_PREFIX/"opt/#{python}/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}"
 | 
					 | 
				
			||||||
    elsif from_osx? and MacOS.version < :mavericks
 | 
					 | 
				
			||||||
      # Python on OS X before Mavericks has been stripped off its includes (unless you install the CLT), therefore we use the MacOS.sdk.
 | 
					 | 
				
			||||||
      Pathname.new("#{MacOS.sdk_path}/System/Library/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}")
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      # What Python knows about itself
 | 
					 | 
				
			||||||
      Pathname.new(`#{binary} -c 'import sys;print(sys.prefix)'`.strip)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Get the actual x.y.z version by asking python (or python3 if @min_version>=3)
 | 
					 | 
				
			||||||
  def version
 | 
					 | 
				
			||||||
    @version ||= PythonVersion.new(`#{binary} -c 'import sys;print(sys.version[:5])'`.strip)
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # python.xy => "python2.7" is often used (and many formulae had this as `which_python`).
 | 
					 | 
				
			||||||
  def xy
 | 
					 | 
				
			||||||
    "python#{version.major}.#{version.minor}"
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Homebrew's global site-packages. The local ones (just `site_packages`) are
 | 
					 | 
				
			||||||
  # populated by the python_helperg method when the `prefix` of a formula is known.
 | 
					 | 
				
			||||||
  def global_site_packages
 | 
					 | 
				
			||||||
    HOMEBREW_PREFIX/"lib/#{xy}/site-packages"
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Dir containing Python.h and others.
 | 
					 | 
				
			||||||
  def incdir
 | 
					 | 
				
			||||||
    if (from_osx? || brewed?) && framework?
 | 
					 | 
				
			||||||
      prefix/"Headers"
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      # For all other we use Python's own standard method (works with a non-framework version, too)
 | 
					 | 
				
			||||||
      Pathname.new(`#{binary} -c 'from distutils import sysconfig; print(sysconfig.get_python_inc())'`.strip)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Dir containing e.g. libpython2.7.dylib
 | 
					 | 
				
			||||||
  def libdir
 | 
					 | 
				
			||||||
    if brewed? || from_osx?
 | 
					 | 
				
			||||||
      if @min_version.major == 3
 | 
					 | 
				
			||||||
        prefix/"lib/#{xy}/config-#{version.major}.#{version.minor}m"
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        prefix/"lib/#{xy}/config"
 | 
					 | 
				
			||||||
      end
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      Pathname.new(`#{binary} -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))"`.strip)
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Pkgconfig (pc) files of python
 | 
					 | 
				
			||||||
  def pkg_config_path
 | 
					 | 
				
			||||||
    if from_osx?
 | 
					 | 
				
			||||||
      # No matter if CLT-only or Xcode-only, the pc file is always here on OS X:
 | 
					 | 
				
			||||||
      path = Pathname.new("/System/Library/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/lib/pkgconfig")
 | 
					 | 
				
			||||||
      path if path.exist?
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      prefix/"lib/pkgconfig"
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Is the brewed Python installed?
 | 
					 | 
				
			||||||
  def brewed?
 | 
					 | 
				
			||||||
    @brewed ||= begin
 | 
					 | 
				
			||||||
      require 'formula'
 | 
					 | 
				
			||||||
      Formula.factory(@python).linked_keg.exist?
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Is the python the one from OS X?
 | 
					 | 
				
			||||||
  def from_osx?
 | 
					 | 
				
			||||||
    @from_osx ||= begin
 | 
					 | 
				
			||||||
      p = `#{binary} -c "import sys; print(sys.prefix)"`.strip
 | 
					 | 
				
			||||||
      p.start_with?("/System/Library/Frameworks/Python.framework")
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # Is the `python` a PyPy?
 | 
					 | 
				
			||||||
  def pypy?
 | 
					 | 
				
			||||||
    @pypy ||= !(`#{binary} -c "import sys; print(sys.version)"`.downcase =~ /.*pypy.*/).nil?
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def framework
 | 
					 | 
				
			||||||
    # We return the path to Frameworks and not the 'Python.framework', because
 | 
					 | 
				
			||||||
    # the latter is (sadly) the same for 2.x and 3.x.
 | 
					 | 
				
			||||||
    if prefix.to_s =~ /^(.*\/Frameworks)\/(Python\.framework).*$/
 | 
					 | 
				
			||||||
      @framework = $1
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
  def framework?; not framework.nil? end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def universal?
 | 
					 | 
				
			||||||
    @universal ||= archs_for_command(binary).universal?
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def standard_caveats
 | 
					 | 
				
			||||||
    if brewed?
 | 
					 | 
				
			||||||
      ""  # empty string, so we can concat this
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      <<-EOS.undent
 | 
					 | 
				
			||||||
        For non-homebrew #{@python} (#{@min_version.major}.x), you need to amend your PYTHONPATH like so:
 | 
					 | 
				
			||||||
          export PYTHONPATH=#{global_site_packages}:$PYTHONPATH
 | 
					 | 
				
			||||||
      EOS
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def modify_build_environment
 | 
					  def modify_build_environment
 | 
				
			||||||
    # Most methods fail if we don't have a binary.
 | 
					    ENV['PYTHONPATH'] = "#{HOMEBREW_PREFIX}/lib/python2.7/site-packages"
 | 
				
			||||||
    return if binary.nil?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ENV['PYTHONHOME'] = nil  # to avoid fuck-ups.
 | 
					 | 
				
			||||||
    ENV['PYTHONPATH'] = nil  # first unset, because global_site_packages may fail
 | 
					 | 
				
			||||||
    ENV['PYTHONPATH'] = if brewed? then nil; else global_site_packages.to_s; end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # For non-system python's we add the opt_prefix/bin of python to the path.
 | 
					 | 
				
			||||||
    ENV.prepend_path 'PATH', binary.dirname unless from_osx?
 | 
					 | 
				
			||||||
    ENV.append_path 'CMAKE_INCLUDE_PATH', incdir
 | 
					 | 
				
			||||||
    ENV.append_path 'PKG_CONFIG_PATH', pkg_config_path if pkg_config_path
 | 
					 | 
				
			||||||
    # We don't set the -F#{framework} here, because if Python 2.x and 3.x are
 | 
					 | 
				
			||||||
    # used, `Python.framework` is ambiguous. However, in the `python do` block
 | 
					 | 
				
			||||||
    # we can set LDFLAGS+="-F#{framework}" because only one is temporarily set.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Write our sitecustomize.py
 | 
					 | 
				
			||||||
    file = global_site_packages/"sitecustomize.py"
 | 
					 | 
				
			||||||
    ohai "Writing #{file}" if ARGV.verbose? && ARGV.debug?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    %w{.pyc .pyo .py}.each do |ext|
 | 
					 | 
				
			||||||
      f = global_site_packages/"sitecustomize#{ext}"
 | 
					 | 
				
			||||||
      f.unlink if f.exist?
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    file.write(sitecustomize)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Udpate distutils.cfg (later we can remove this, but people still have
 | 
					 | 
				
			||||||
    # their old brewed pythons and we have to update it here)
 | 
					 | 
				
			||||||
    # Todo: If Jack's formula revisions arrive, we can get rid of this here!
 | 
					 | 
				
			||||||
    if brewed?
 | 
					 | 
				
			||||||
      require 'formula'
 | 
					 | 
				
			||||||
      file = Formula.factory(@python).opt_prefix/"Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/lib/#{xy}/distutils/distutils.cfg"
 | 
					 | 
				
			||||||
      ohai "Writing #{file}" if ARGV.verbose? && ARGV.debug?
 | 
					 | 
				
			||||||
      file.delete if file.exist?
 | 
					 | 
				
			||||||
      file.write <<-EOF.undent
 | 
					 | 
				
			||||||
        [global]
 | 
					 | 
				
			||||||
        verbose=1
 | 
					 | 
				
			||||||
        [install]
 | 
					 | 
				
			||||||
        force=1
 | 
					 | 
				
			||||||
        prefix=#{HOMEBREW_PREFIX}
 | 
					 | 
				
			||||||
      EOF
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def sitecustomize
 | 
					 | 
				
			||||||
    <<-EOF.undent
 | 
					 | 
				
			||||||
      # 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://github.com/Homebrew/homebrew/wiki/Homebrew-and-Python>
 | 
					 | 
				
			||||||
      import os
 | 
					 | 
				
			||||||
      import sys
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if sys.version_info[0] != #{version.major}:
 | 
					 | 
				
			||||||
          # 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 #{version.major}.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.')
 | 
					 | 
				
			||||||
      else:
 | 
					 | 
				
			||||||
          # Only do this for a brewed python:
 | 
					 | 
				
			||||||
          opt_executable = '#{HOMEBREW_PREFIX}/opt/#{python}/bin/#{xy}'
 | 
					 | 
				
			||||||
          if os.path.realpath(sys.executable) == os.path.realpath(opt_executable):
 | 
					 | 
				
			||||||
              # Remove /System site-packages, and the Cellar site-packages
 | 
					 | 
				
			||||||
              # which we moved to lib/pythonX.Y/site-packages. Further, remove
 | 
					 | 
				
			||||||
              # HOMEBREW_PREFIX/lib/python because we later addsitedir(...).
 | 
					 | 
				
			||||||
              sys.path = [ p for p in sys.path
 | 
					 | 
				
			||||||
                           if (not p.startswith('/System') and
 | 
					 | 
				
			||||||
                               not p.startswith('#{HOMEBREW_PREFIX}/lib/python') and
 | 
					 | 
				
			||||||
                               not (p.startswith('#{HOMEBREW_PREFIX}/Cellar/python') and p.endswith('site-packages'))) ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              # LINKFORSHARED (and python-config --ldflags) return the
 | 
					 | 
				
			||||||
              # full path to the lib (yes, "Python" is actually the lib, not a
 | 
					 | 
				
			||||||
              # dir) so that third-party software does not need to add the
 | 
					 | 
				
			||||||
              # -F/#{HOMEBREW_PREFIX}/Frameworks switch.
 | 
					 | 
				
			||||||
              # Assume Framework style build (default since months in brew)
 | 
					 | 
				
			||||||
              try:
 | 
					 | 
				
			||||||
                  from _sysconfigdata import build_time_vars
 | 
					 | 
				
			||||||
                  build_time_vars['LINKFORSHARED'] = '-u _PyMac_Error #{HOMEBREW_PREFIX}/opt/#{python}/Frameworks/Python.framework/Versions/#{version.major}.#{version.minor}/Python'
 | 
					 | 
				
			||||||
              except:
 | 
					 | 
				
			||||||
                  pass  # remember: don't print here. Better to fail silently.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              # Set the sys.executable to use the opt_prefix
 | 
					 | 
				
			||||||
              sys.executable = opt_executable
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          # Tell about homebrew's site-packages location.
 | 
					 | 
				
			||||||
          # This is needed for Python to parse *.pth.
 | 
					 | 
				
			||||||
          import site
 | 
					 | 
				
			||||||
          site.addsitedir('#{HOMEBREW_PREFIX}/lib/#{xy}/site-packages')
 | 
					 | 
				
			||||||
    EOF
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def message
 | 
					 | 
				
			||||||
    @unsatisfied_because
 | 
					 | 
				
			||||||
  end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  def <=> other
 | 
					 | 
				
			||||||
    version <=> other.version
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Deprecated
 | 
				
			||||||
  def to_s
 | 
					  def to_s
 | 
				
			||||||
    binary.to_s
 | 
					    python_binary
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Objects of this class are used to represent dependencies on Python and
 | 
					  protected
 | 
				
			||||||
  # dependencies on Python modules. Both are already included in `name`
 | 
					
 | 
				
			||||||
  def eql?(other)
 | 
					  def python_binary
 | 
				
			||||||
    instance_of?(other.class) && name == other.name
 | 
					    'python'
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def hash
 | 
					  def system_python?
 | 
				
			||||||
    name.hash
 | 
					    which(python_binary).to_s == "/usr/bin/python"
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Python3Dependency < PythonDependency
 | 
				
			||||||
 | 
					  default_formula 'python3'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def python_binary
 | 
				
			||||||
 | 
					    'python3'
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def system_python?
 | 
				
			||||||
 | 
					    false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user