Class: FPM::Package::Virtualenv

Inherits:
FPM::Package show all
Defined in:
lib/fpm/package/virtualenv.rb

Overview

Support for python virtualenv packages.

This supports input, but not output.

Instance Attribute Summary

Attributes inherited from FPM::Package

#architecture, #attributes, #attrs, #category, #config_files, #conflicts, #dependencies, #description, #directories, #epoch, #iteration, #license, #maintainer, #name, #provides, #replaces, #scripts, #url, #vendor, #version

Instance Method Summary collapse

Methods inherited from FPM::Package

apply_options, #build_path, #cleanup, #cleanup_build, #cleanup_staging, #convert, #converted_from, default_attributes, #edit_file, #files, inherited, #initialize, option, #output, #script, #staging_path, #to_s, #type, type, types

Methods included from Util

#ar_cmd, #ar_cmd_deterministic?, #copied_entries, #copy_entry, #copy_metadata, #default_shell, #erbnew, #execmd, #expand_pessimistic_constraints, #logger, #program_exists?, #program_in_path?, #safesystem, #safesystemout, #tar_cmd, #tar_cmd_supports_sort_names_and_set_mtime?

Constructor Details

This class inherits a constructor from FPM::Package

Instance Method Details

#input(package) ⇒ Object

Input a package.

`package` can look like `psutil==2.2.1` or `psutil`.


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/fpm/package/virtualenv.rb', line 56

def input(package)
  installdir = attributes[:virtualenv_install_location]
  m = /^([^=]+)==([^=]+)$/.match(package)
  package_version = nil

  is_requirements_file = (File.basename(package) == "requirements.txt")

  if is_requirements_file
    if !File.file?(package)
      raise FPM::InvalidPackageConfiguration, "Path looks like a requirements.txt, but it doesn't exist: #{package}"
    end

    package = File.join(::Dir.pwd, package) if File.dirname(package) == "."
    package_name = File.basename(File.dirname(package))
    logger.info("No name given. Using the directory's name", :name => package_name)
    package_version = nil
  elsif m
    package_name = m[1]
    package_version = m[2]
    self.version ||= package_version
  else
    package_name = package
    package_version = nil
  end

  virtualenv_name = package_name

  self.name ||= package_name

  if self.attributes[:virtualenv_fix_name?]
    self.name = [self.attributes[:virtualenv_package_name_prefix],
                 self.name].join("-")
  end

  # prefix wins over previous virtual_install_location behaviour
  virtualenv_folder =
    if self.attributes[:prefix]
      self.attributes[:prefix]
    else
      File.join(installdir,
                virtualenv_name)
    end

  virtualenv_build_folder = build_path(virtualenv_folder)

  ::FileUtils.mkdir_p(virtualenv_build_folder)

  if self.attributes[:virtualenv_system_site_packages?]
      logger.info("Creating virtualenv with --system-site-packages")
      safesystem("virtualenv", "--system-site-packages", virtualenv_build_folder)
  else
      safesystem("virtualenv", virtualenv_build_folder)
  end

  pip_exe = File.join(virtualenv_build_folder, "bin", "pip")
  python_exe = File.join(virtualenv_build_folder, "bin", "python")

  # Why is this hack here? It looks important, so I'll keep it in.
  safesystem(python_exe, pip_exe, "install", "-U", "-i",
             attributes[:virtualenv_pypi],
             "pip")

  extra_index_url_args = []
  if attributes[:virtualenv_pypi_extra_index_urls]
    attributes[:virtualenv_pypi_extra_index_urls].each do |extra_url|
      extra_index_url_args << "--extra-index-url" << extra_url
    end
  end

  find_links_url_args = []
  if attributes[:virtualenv_find_links_urls]
    attributes[:virtualenv_find_links_urls].each do |links_url|
      find_links_url_args << "--find-links" << links_url
    end
  end

  target_args = []
  if is_requirements_file
    target_args << "-r" << package
  else
    target_args << package
  end

  pip_args = [python_exe, pip_exe, "install", "-i", attributes[:virtualenv_pypi]] << extra_index_url_args << find_links_url_args << target_args
  safesystem(*pip_args.flatten)

  if attributes[:virtualenv_setup_install?]
    logger.info("Running PACKAGE setup.py")
    setup_args = [python_exe, "setup.py", "install"]
    safesystem(*setup_args.flatten)
  end

  if ! is_requirements_file && package_version.nil?
    frozen = safesystemout(python_exe, pip_exe, "freeze")
    frozen_version = frozen[/#{package}==[^=]+$/]
    package_version = frozen_version && frozen_version.split("==")[1].chomp!
    self.version ||= package_version
  end

  ::Dir[build_path + "/**/*"].each do |f|
    if ! File.readable? f
      File.lchmod(File.stat(f).mode | 444)
    end
  end

  ::Dir.chdir(virtualenv_build_folder) do
    safesystem("virtualenv-tools", "--update-path", virtualenv_folder)
  end

  if !attributes[:virtualenv_other_files_dir].nil?
    # Copy all files from other dir to build_path
    Find.find(attributes[:virtualenv_other_files_dir]) do |path|
      src = path.gsub(/^#{attributes[:virtualenv_other_files_dir]}/, '')
      dst = File.join(build_path, src)
      copy_entry(path, dst, preserve=true, remove_destination=true)
      (path, dst)
    end
  end

  remove_python_compiled_files virtualenv_build_folder

  # use dir to set stuff up properly, mainly so I don't have to reimplement
  # the chdir/prefix stuff special for tar.
  dir = convert(FPM::Package::Dir)
  # don't double prefix the files
  dir.attributes[:prefix] = nil
  if attributes[:chdir]
    dir.attributes[:chdir] = File.join(build_path, attributes[:chdir])
  else
    dir.attributes[:chdir] = build_path
  end

  cleanup_staging
  # Tell 'dir' to input "." and chdir/prefix will help it figure out the
  # rest.
  dir.input(".")
  @staging_path = dir.staging_path
  dir.cleanup_build

end