class Licensed::Sources::Pip

Constants

PACKAGE_INFO_SEPARATOR

Public Instance Methods

enabled?() click to toggle source
# File lib/licensed/sources/pip.rb, line 12
def enabled?
  !pip_command.empty? && Licensed::Shell.tool_available?(pip_command.join(""))
end
enumerate_dependencies() click to toggle source
# File lib/licensed/sources/pip.rb, line 16
def enumerate_dependencies
  packages.map do |package|
    Dependency.new(
      name: package["Name"],
      version: package["Version"],
      path: package_license_location(package),
      metadata: {
        "type"        => self.class.type,
        "summary"     => package["Summary"],
        "homepage"    => package["Home-page"]
      }
    )
  end
end

Protected Instance Methods

pip_command() click to toggle source

Returns the command to run pip

# File lib/licensed/sources/pip.rb, line 34
def pip_command
  return [] unless virtual_env_dir
  Array(File.join(virtual_env_dir, "bin", "pip"))
end

Private Instance Methods

package_license_location(package) click to toggle source

Returns the location of license files in the package, checking for the inclusion of a new ‘license_files` folder per peps.python.org/pep-0639/

# File lib/licensed/sources/pip.rb, line 43
def package_license_location(package)
  dist_info = File.join(package["Location"], package["Name"].gsub("-", "_") +  "-" + package["Version"] + ".dist-info")

  license_path = ["license_files", "licenses"]
    .map { |directory| File.join(dist_info, directory) }
    .find { |path| File.exist?(path) }

  license_path || dist_info
end
package_names() click to toggle source

Returns the names of all of the packages used by the current project, as returned from ‘pip list`

# File lib/licensed/sources/pip.rb, line 65
def package_names
  @package_names ||= begin
    JSON.parse(pip_list_command).map { |package| package["name"] }
  rescue JSON::ParserError => e
    message = "Licensed was unable to parse the output from 'npm list'. JSON Error: #{e.message}"
    raise Licensed::Sources::Source::Error, message
  end
end
packages() click to toggle source

Returns parsed information for all packages used by the project, using ‘pip list` to determine what packages are used and `pip show` to gather package information

# File lib/licensed/sources/pip.rb, line 56
def packages
  all_packages = pip_show_command(package_names)
  all_packages.split(PACKAGE_INFO_SEPARATOR).reduce([]) do |accum, val|
    accum << parse_package_info(val)
  end
end
parse_package_info(package_info) click to toggle source

Returns a hash filled with package info parsed from the email-header formatted output returned by ‘pip show`

# File lib/licensed/sources/pip.rb, line 76
def parse_package_info(package_info)
  package_info.lines.each_with_object(Hash.new(0)) do |pkg, a|
    next if pkg.start_with?(/^\s/)

    k, v = pkg.split(":", 2)
    next if k.nil? || k.empty?
    a[k.strip] = v&.strip
  end
end
pip_list_command() click to toggle source

Returns the output from ‘pip list –format=json`

# File lib/licensed/sources/pip.rb, line 87
def pip_list_command
  Licensed::Shell.execute(*pip_command, "--disable-pip-version-check", "list", "--format=json")
end
pip_show_command(packages) click to toggle source

Returns the output from ‘pip show <package> <package> …`

# File lib/licensed/sources/pip.rb, line 92
def pip_show_command(packages)
  Licensed::Shell.execute(*pip_command, "--disable-pip-version-check", "show", *packages)
end
virtual_env_dir() click to toggle source
# File lib/licensed/sources/pip.rb, line 96
def virtual_env_dir
  return @virtual_env_dir if defined?(@virtual_env_dir)
  @virtual_env_dir = begin
    python_config = config["python"]
    return unless python_config.is_a?(Hash)

    venv_dir = python_config["virtual_env_dir"]
    File.expand_path(venv_dir, config.root) if venv_dir
  end
end