mortar 0.9.3 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mortar/auth.rb +0 -8
- data/lib/mortar/command/local.rb +14 -2
- data/lib/mortar/generators/characterize_generator.rb +105 -0
- data/lib/mortar/generators/generator_base.rb +1 -1
- data/lib/mortar/generators/project_generator.rb +0 -4
- data/lib/mortar/helpers.rb +13 -0
- data/lib/mortar/local/controller.rb +11 -3
- data/lib/mortar/local/installutil.rb +66 -6
- data/lib/mortar/local/jython.rb +11 -5
- data/lib/mortar/local/pig.rb +6 -9
- data/lib/mortar/local/python.rb +43 -23
- data/lib/mortar/plugin.rb +1 -0
- data/lib/mortar/templates/characterize/README.md +7 -0
- data/lib/mortar/templates/characterize/controlscripts/lib/__init__.py +0 -0
- data/lib/mortar/templates/characterize/controlscripts/lib/characterize_control.py +27 -0
- data/lib/mortar/templates/characterize/fixtures/gitkeep +0 -0
- data/lib/mortar/templates/characterize/gitignore +8 -0
- data/lib/mortar/templates/{project → characterize}/macros/characterize_macro.pig +0 -0
- data/lib/mortar/templates/characterize/macros/gitkeep +0 -0
- data/lib/mortar/templates/{project → characterize}/pigscripts/characterize.pig +0 -0
- data/lib/mortar/templates/characterize/pigscripts/pigscript.pig +38 -0
- data/lib/mortar/templates/characterize/udfs/java/gitkeep +0 -0
- data/lib/mortar/templates/characterize/udfs/jython/gitkeep +0 -0
- data/lib/mortar/templates/{project → characterize}/udfs/jython/top_5_tuple.py +0 -0
- data/lib/mortar/templates/characterize/udfs/python/python_udf.py +13 -0
- data/lib/mortar/templates/characterize/vendor/controlscripts/lib/__init__.py +0 -0
- data/lib/mortar/templates/characterize/vendor/macros/gitkeep +0 -0
- data/lib/mortar/templates/characterize/vendor/pigscripts/gitkeep +0 -0
- data/lib/mortar/templates/characterize/vendor/udfs/java/gitkeep +0 -0
- data/lib/mortar/templates/characterize/vendor/udfs/jython/gitkeep +0 -0
- data/lib/mortar/templates/characterize/vendor/udfs/python/gitkeep +0 -0
- data/lib/mortar/version.rb +1 -1
- data/spec/mortar/command/local_spec.rb +29 -2
- data/spec/mortar/command/projects_spec.rb +0 -4
- data/spec/mortar/local/installutil_spec.rb +69 -1
- data/spec/mortar/local/pig_spec.rb +2 -2
- metadata +173 -132
- data/lib/mortar/templates/project/controlscripts/lib/characterize_control.py +0 -23
data/lib/mortar/auth.rb
CHANGED
data/lib/mortar/command/local.rb
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
require "mortar/local/controller"
|
18
18
|
require "mortar/command/base"
|
19
|
+
require "mortar/generators/characterize_generator"
|
19
20
|
|
20
21
|
# run select pig commands on your local machine
|
21
22
|
#
|
@@ -71,7 +72,7 @@ class Mortar::Command::Local < Mortar::Command::Base
|
|
71
72
|
ctrl.run(script, pig_parameters)
|
72
73
|
end
|
73
74
|
|
74
|
-
# local:characterize
|
75
|
+
# local:characterize -f PARAMFILE
|
75
76
|
#
|
76
77
|
# Characterize will inspect your input data, inferring a schema and
|
77
78
|
# generating keys, if needed. It will output CSV containing various
|
@@ -80,7 +81,7 @@ class Mortar::Command::Local < Mortar::Command::Base
|
|
80
81
|
# -f, --param-file PARAMFILE # Load pig parameter values from a file
|
81
82
|
#
|
82
83
|
# Load some data and emit statistics.
|
83
|
-
# PARAMFILE:
|
84
|
+
# PARAMFILE (Required):
|
84
85
|
# LOADER=<full class path of loader function>
|
85
86
|
# INPUT_SRC=<Location of the input data>
|
86
87
|
# OUTPUT_PATH=<Relative path from project root for output>
|
@@ -95,17 +96,28 @@ class Mortar::Command::Local < Mortar::Command::Base
|
|
95
96
|
def characterize
|
96
97
|
validate_arguments!
|
97
98
|
|
99
|
+
unless options[:param_file]
|
100
|
+
error("Usage: mortar local:characterize -f PARAMFILE.\nMust specify parameter file. For detailed help run:\n\n mortar local:characterize -h")
|
101
|
+
end
|
102
|
+
|
98
103
|
#cd into the project root
|
99
104
|
project_root = options[:project_root] ||= Dir.getwd
|
100
105
|
unless File.directory?(project_root)
|
101
106
|
error("No such directory #{project_root}")
|
102
107
|
end
|
108
|
+
|
103
109
|
Dir.chdir(project_root)
|
104
110
|
|
111
|
+
gen = Mortar::Generators::CharacterizeGenerator.new
|
112
|
+
gen.generate_characterize
|
113
|
+
|
105
114
|
controlscript_name = "controlscripts/lib/characterize_control.py"
|
115
|
+
gen = Mortar::Generators::CharacterizeGenerator.new
|
116
|
+
gen.generate_characterize
|
106
117
|
script = validate_script!(controlscript_name)
|
107
118
|
ctrl = Mortar::Local::Controller.new
|
108
119
|
ctrl.run(script, pig_parameters)
|
120
|
+
gen.cleanup_characterize(project_root)
|
109
121
|
end
|
110
122
|
|
111
123
|
# local:illustrate PIGSCRIPT [ALIAS]
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2012 Mortar Data Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require "fileutils"
|
18
|
+
require "mortar/generators/generator_base"
|
19
|
+
module Mortar
|
20
|
+
module Generators
|
21
|
+
class CharacterizeGenerator < Base
|
22
|
+
|
23
|
+
def generate_characterize
|
24
|
+
begin
|
25
|
+
inside "pigscripts" do
|
26
|
+
copy_file_char "characterize.pig", "characterize.pig"
|
27
|
+
end
|
28
|
+
|
29
|
+
inside "controlscripts" do
|
30
|
+
inside "lib" do
|
31
|
+
copy_file_char "characterize_control.py", "characterize_control.py"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
inside "macros" do
|
36
|
+
copy_file_char "characterize_macro.pig", "characterize_macro.pig"
|
37
|
+
end
|
38
|
+
|
39
|
+
inside "udfs" do
|
40
|
+
inside "jython" do
|
41
|
+
copy_file_char "top_5_tuple.py", "top_5_tuple.py"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# how best to handle exceptions, here?
|
46
|
+
rescue => e
|
47
|
+
display("\nCharacterize script generation failed.\n\n")
|
48
|
+
raise e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def cleanup_characterize(project_root)
|
53
|
+
@src_path = project_root
|
54
|
+
begin
|
55
|
+
inside "pigscripts" do
|
56
|
+
remove_file "characterize.pig"
|
57
|
+
end
|
58
|
+
|
59
|
+
inside "controlscripts" do
|
60
|
+
inside "lib" do
|
61
|
+
remove_file "characterize_control.py"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
inside "macros" do
|
66
|
+
remove_file "characterize_macro.pig"
|
67
|
+
end
|
68
|
+
|
69
|
+
inside "udfs" do
|
70
|
+
inside "jython" do
|
71
|
+
remove_file "top_5_tuple.py"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# how best to handle exceptions, here?
|
76
|
+
rescue => e
|
77
|
+
display("\nCharacterize script cleanup failed.\n\n")
|
78
|
+
raise e
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def remove_file(target_file, options={ :recursive => false })
|
83
|
+
target_path = File.join(@src_path, @rel_path, target_file)
|
84
|
+
msg = File.join(@rel_path, target_file)[1..-1]
|
85
|
+
|
86
|
+
if File.exists?(target_path)
|
87
|
+
FileUtils.rm(target_path)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def copy_file_char(src_file, dest_file, options={ :recursive => false })
|
92
|
+
src_path = File.join(@src_path, @rel_path, src_file)
|
93
|
+
dest_path = File.join(@dest_path, @rel_path, dest_file)
|
94
|
+
msg = File.join(@rel_path, dest_file)[1..-1]
|
95
|
+
|
96
|
+
unless File.exists?(dest_path) and
|
97
|
+
FileUtils.compare_file(src_path, dest_path)
|
98
|
+
FileUtils.mkdir_p(File.dirname(dest_path)) if options[:recursive]
|
99
|
+
FileUtils.cp(src_path, dest_path)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -38,7 +38,6 @@ module Mortar
|
|
38
38
|
|
39
39
|
inside "pigscripts" do
|
40
40
|
generate_file "pigscript.pig", "#{project_name}.pig"
|
41
|
-
copy_file "characterize.pig", "characterize.pig"
|
42
41
|
end
|
43
42
|
|
44
43
|
mkdir "controlscripts"
|
@@ -47,7 +46,6 @@ module Mortar
|
|
47
46
|
mkdir "lib"
|
48
47
|
inside "lib" do
|
49
48
|
copy_file "__init__.py", "__init__.py"
|
50
|
-
copy_file "characterize_control.py", "characterize_control.py"
|
51
49
|
end
|
52
50
|
end
|
53
51
|
|
@@ -55,7 +53,6 @@ module Mortar
|
|
55
53
|
|
56
54
|
inside "macros" do
|
57
55
|
copy_file "gitkeep", ".gitkeep"
|
58
|
-
copy_file "characterize_macro.pig", "characterize_macro.pig"
|
59
56
|
end
|
60
57
|
|
61
58
|
mkdir "fixtures"
|
@@ -75,7 +72,6 @@ module Mortar
|
|
75
72
|
mkdir "jython"
|
76
73
|
inside "jython" do
|
77
74
|
copy_file "gitkeep", ".gitkeep"
|
78
|
-
copy_file "top_5_tuple.py", "top_5_tuple.py"
|
79
75
|
end
|
80
76
|
|
81
77
|
mkdir "java"
|
data/lib/mortar/helpers.rb
CHANGED
@@ -38,6 +38,18 @@ module Mortar
|
|
38
38
|
RUBY_PLATFORM =~ /-darwin\d/
|
39
39
|
end
|
40
40
|
|
41
|
+
def default_host
|
42
|
+
"mortardata.com"
|
43
|
+
end
|
44
|
+
|
45
|
+
def host
|
46
|
+
ENV['MORTAR_HOST'] || default_host
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_name
|
50
|
+
ENV['MORTAR_TEST_NAME']
|
51
|
+
end
|
52
|
+
|
41
53
|
def write_to_file(str_data, path, mkdir_p=true)
|
42
54
|
if mkdir_p
|
43
55
|
FileUtils.mkdir_p File.dirname(path)
|
@@ -528,5 +540,6 @@ module Mortar
|
|
528
540
|
create_display_method("exists", "1;34")
|
529
541
|
create_display_method("identical", "1;34")
|
530
542
|
create_display_method("conflict", "1;31")
|
543
|
+
create_display_method("remove", "1;35")
|
531
544
|
end
|
532
545
|
end
|
@@ -33,9 +33,13 @@ Linux systems please consult the documentation on your relevant package manager.
|
|
33
33
|
EOF
|
34
34
|
|
35
35
|
NO_PYTHON_ERROR_MESSAGE = <<EOF
|
36
|
-
A suitable python installation
|
37
|
-
|
38
|
-
|
36
|
+
A suitable python installation could not be located. Please ensure you have python 2.6+
|
37
|
+
installed on your local system.
|
38
|
+
EOF
|
39
|
+
|
40
|
+
NO_VIRTENV_ERROR_MESSAGE = <<EOF
|
41
|
+
A suitable Python installation was found, but it is required that virtualenv be installed
|
42
|
+
as well. You can install it with pip, or download it directly from:
|
39
43
|
https://pypi.python.org/pypi/virtualenv
|
40
44
|
EOF
|
41
45
|
|
@@ -86,6 +90,10 @@ EOF
|
|
86
90
|
error(NO_PYTHON_ERROR_MESSAGE)
|
87
91
|
end
|
88
92
|
|
93
|
+
unless py.check_virtualenv
|
94
|
+
error(NO_VIRTENV_ERROR_MESSAGE)
|
95
|
+
end
|
96
|
+
|
89
97
|
unless py.setup_project_python_environment
|
90
98
|
msg = "\nUnable to setup a python environment with your dependencies, "
|
91
99
|
msg += "see #{py.pip_error_log_path} for more details"
|
@@ -107,13 +107,73 @@ module Mortar
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
# Downloads the file at a specified url into the supplied
|
111
|
-
def download_file(url,
|
112
|
-
|
110
|
+
# Downloads the file at a specified url into the supplied directory
|
111
|
+
def download_file(url, dest_file_path)
|
112
|
+
response = get_resource(url)
|
113
|
+
|
113
114
|
File.open(dest_file_path, "wb") do |dest_file|
|
114
|
-
|
115
|
-
dest_file.write(contents)
|
115
|
+
dest_file.write(response.body)
|
116
116
|
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
# Perform a get request to a url and follow redirects if necessary.
|
121
|
+
def get_resource(url)
|
122
|
+
make_call(url, 'get')
|
123
|
+
end
|
124
|
+
|
125
|
+
# Perform a head request to a url and follow redirects if necessary.
|
126
|
+
def head_resource(url)
|
127
|
+
make_call(url, 'head')
|
128
|
+
end
|
129
|
+
|
130
|
+
# Make a request to a mortar resource url. Check response for a
|
131
|
+
# redirect and if necessary call the new url. Excon doesn't currently
|
132
|
+
# support automatically following redirects. Adds parameter that
|
133
|
+
# checks an environment variable to identify the test making this call
|
134
|
+
# (if being run by a test).
|
135
|
+
def make_call(url, call_func, redirect_times=0, errors=0)
|
136
|
+
if redirect_times >= 5
|
137
|
+
raise RuntimeError, "Too many redirects. Last url: #{url}"
|
138
|
+
end
|
139
|
+
|
140
|
+
if errors >= 5
|
141
|
+
raise RuntimeError, "Server Error at #{url}"
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
query = {}
|
146
|
+
if test_name
|
147
|
+
query[:test_name] = test_name
|
148
|
+
end
|
149
|
+
|
150
|
+
headers = {'User-Agent' => Mortar::USER_AGENT}
|
151
|
+
if call_func == 'head'
|
152
|
+
response = Excon.head( url,
|
153
|
+
:headers => headers,
|
154
|
+
:query => query
|
155
|
+
)
|
156
|
+
elsif call_func == 'get'
|
157
|
+
response = Excon.get( url,
|
158
|
+
:headers => headers,
|
159
|
+
:query => query
|
160
|
+
)
|
161
|
+
else
|
162
|
+
raise RuntimeError, "Unknown call type: #{call_func}"
|
163
|
+
end
|
164
|
+
case response.status
|
165
|
+
when 300..303 then
|
166
|
+
make_call(response.headers['Location'], call_func, redirect_times+1, errors)
|
167
|
+
when 500..599 then
|
168
|
+
sleep(make_call_sleep_seconds)
|
169
|
+
make_call(url, call_func, redirect_times, errors+1)
|
170
|
+
else
|
171
|
+
response
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def make_call_sleep_seconds
|
176
|
+
2
|
117
177
|
end
|
118
178
|
|
119
179
|
def osx?
|
@@ -126,7 +186,7 @@ module Mortar
|
|
126
186
|
end
|
127
187
|
|
128
188
|
def url_date(url)
|
129
|
-
result =
|
189
|
+
result = head_resource(url)
|
130
190
|
http_date_to_epoch(result.get_header('Last-Modified'))
|
131
191
|
end
|
132
192
|
|
data/lib/mortar/local/jython.rb
CHANGED
@@ -21,7 +21,7 @@ class Mortar::Local::Jython
|
|
21
21
|
|
22
22
|
JYTHON_VERSION = '2.5.2'
|
23
23
|
JYTHON_JAR_NAME = 'jython_installer-' + JYTHON_VERSION + '.jar'
|
24
|
-
|
24
|
+
JYTHON_JAR_DEFAULT_URL_PATH = "resource/jython"
|
25
25
|
|
26
26
|
def install_or_update
|
27
27
|
if should_install
|
@@ -40,24 +40,30 @@ class Mortar::Local::Jython
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def install
|
43
|
-
|
44
|
-
|
43
|
+
jython_file = File.join(local_install_directory, JYTHON_JAR_NAME)
|
44
|
+
unless File.exists?(jython_file)
|
45
|
+
download_file(jython_jar_url, jython_file)
|
45
46
|
end
|
46
47
|
|
47
48
|
`$JAVA_HOME/bin/java -jar #{local_install_directory + '/' + JYTHON_JAR_NAME} -s -d #{jython_directory}`
|
48
49
|
FileUtils.mkdir_p jython_cache_directory
|
49
50
|
FileUtils.chmod_R 0777, jython_cache_directory
|
50
51
|
|
51
|
-
FileUtils.rm(
|
52
|
+
FileUtils.rm(jython_file)
|
52
53
|
note_install('jython')
|
53
54
|
end
|
54
55
|
|
55
56
|
def should_update
|
56
|
-
return is_newer_version('jython',
|
57
|
+
return is_newer_version('jython', jython_jar_url)
|
57
58
|
end
|
58
59
|
|
59
60
|
def update
|
60
61
|
FileUtils.rm_r(jython_directory)
|
61
62
|
install
|
62
63
|
end
|
64
|
+
|
65
|
+
def jython_jar_url
|
66
|
+
default_url = host + "/" + JYTHON_JAR_DEFAULT_URL_PATH
|
67
|
+
ENV.fetch('JYTHON_JAR_URL', default_url)
|
68
|
+
end
|
63
69
|
end
|
data/lib/mortar/local/pig.rb
CHANGED
@@ -23,7 +23,8 @@ class Mortar::Local::Pig
|
|
23
23
|
include Mortar::Local::InstallUtil
|
24
24
|
|
25
25
|
PIG_LOG_FORMAT = "humanreadable"
|
26
|
-
|
26
|
+
PIG_TGZ_NAME = "pig.tgz"
|
27
|
+
PIG_TGZ_DEFAULT_URL_PATH = "resource/pig"
|
27
28
|
|
28
29
|
# Tempfile objects have a hook to delete the file when the object is
|
29
30
|
# destroyed by the garbage collector. In practice this means that a
|
@@ -77,11 +78,8 @@ class Mortar::Local::Pig
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def pig_archive_url
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
def pig_archive_file
|
84
|
-
File.basename(pig_archive_url)
|
81
|
+
default_url = host + "/" + PIG_TGZ_DEFAULT_URL_PATH
|
82
|
+
ENV.fetch('PIG_DISTRO_URL', default_url)
|
85
83
|
end
|
86
84
|
|
87
85
|
# Determines if a pig install needs to occur, true if no pig install present
|
@@ -96,7 +94,6 @@ class Mortar::Local::Pig
|
|
96
94
|
end
|
97
95
|
|
98
96
|
def install_or_update()
|
99
|
-
call_install = false
|
100
97
|
if should_do_pig_install?
|
101
98
|
action "Installing pig to #{local_install_directory_name}" do
|
102
99
|
install()
|
@@ -111,8 +108,8 @@ class Mortar::Local::Pig
|
|
111
108
|
# Installs pig for this project if it is not already present
|
112
109
|
def install
|
113
110
|
FileUtils.mkdir_p(local_install_directory)
|
114
|
-
|
115
|
-
|
111
|
+
local_tgz = File.join(local_install_directory, PIG_TGZ_NAME)
|
112
|
+
download_file(pig_archive_url, local_tgz)
|
116
113
|
extract_tgz(local_tgz, local_install_directory)
|
117
114
|
|
118
115
|
# This has been seening coming out of the tgz w/o +x so we do
|
data/lib/mortar/local/python.rb
CHANGED
@@ -19,13 +19,16 @@ require "mortar/local/installutil"
|
|
19
19
|
class Mortar::Local::Python
|
20
20
|
include Mortar::Local::InstallUtil
|
21
21
|
|
22
|
-
|
22
|
+
PYTHON_OSX_TGZ_NAME = "mortar-python-osx.tgz"
|
23
|
+
PYTHON_OSX_TGZ_DEFAULT_URL_PATH = "resource/python_osx"
|
23
24
|
|
24
25
|
# Path to the python binary that should be used
|
25
26
|
# for running UDFs
|
26
27
|
@command = nil
|
27
28
|
|
28
29
|
|
30
|
+
@candidate_pythons = nil
|
31
|
+
|
29
32
|
# Execute either an installation of python or an inspection
|
30
33
|
# of the local system to see if a usable python is available
|
31
34
|
def check_or_install
|
@@ -38,6 +41,17 @@ class Mortar::Local::Python
|
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
44
|
+
def check_virtualenv
|
45
|
+
# Assumes you've already called check_or_install(), in which case
|
46
|
+
# we can skip osx as its installation includeds virtualenv
|
47
|
+
if osx?
|
48
|
+
return true
|
49
|
+
else
|
50
|
+
return check_pythons_for_virtenv
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
41
55
|
def should_do_update?
|
42
56
|
return is_newer_version('python', python_archive_url)
|
43
57
|
end
|
@@ -60,13 +74,14 @@ class Mortar::Local::Python
|
|
60
74
|
|
61
75
|
def install_osx
|
62
76
|
FileUtils.mkdir_p(local_install_directory)
|
63
|
-
|
64
|
-
|
77
|
+
python_tgz_path = File.join(local_install_directory, PYTHON_OSX_TGZ_NAME)
|
78
|
+
download_file(python_archive_url, python_tgz_path)
|
79
|
+
extract_tgz(python_tgz_path, local_install_directory)
|
65
80
|
|
66
81
|
# This has been seening coming out of the tgz w/o +x so we do
|
67
82
|
# here to be sure it has the necessary permissions
|
68
83
|
FileUtils.chmod(0755, @command)
|
69
|
-
File.delete(
|
84
|
+
File.delete(python_tgz_path)
|
70
85
|
note_install("python")
|
71
86
|
end
|
72
87
|
|
@@ -76,21 +91,31 @@ class Mortar::Local::Python
|
|
76
91
|
return (osx? and (not (File.exists?(python_directory))))
|
77
92
|
end
|
78
93
|
|
94
|
+
def candidates
|
95
|
+
@candidate_pythons.dup
|
96
|
+
end
|
79
97
|
|
80
98
|
# Checks if there is a usable versionpython already installed
|
81
99
|
def check_system_python
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
100
|
+
@candidate_pythons = lookup_local_pythons
|
101
|
+
return 0 != @candidate_pythons.length
|
102
|
+
end
|
103
|
+
|
104
|
+
# Inspects the list of found python installations and
|
105
|
+
# checks if they have virtualenv installed. The first
|
106
|
+
# one found will be used.
|
107
|
+
def check_pythons_for_virtenv
|
108
|
+
@candidate_pythons.each{ |py|
|
109
|
+
if has_virtualenv_installed(py)
|
110
|
+
@command = py
|
111
|
+
true
|
112
|
+
end
|
113
|
+
}
|
89
114
|
end
|
90
115
|
|
91
116
|
# Checks if the specified python command has
|
92
117
|
# virtualenv installed
|
93
|
-
def
|
118
|
+
def has_virtualenv_installed(python)
|
94
119
|
`#{python} -m virtualenv --help`
|
95
120
|
if (0 != $?.to_i)
|
96
121
|
false
|
@@ -99,18 +124,16 @@ class Mortar::Local::Python
|
|
99
124
|
end
|
100
125
|
end
|
101
126
|
|
102
|
-
def
|
127
|
+
def lookup_local_pythons
|
103
128
|
# Check several python commands in decending level of desirability
|
129
|
+
found_bins = []
|
104
130
|
[ "python#{desired_python_minor_version}", "python" ].each{ |cmd|
|
105
131
|
path_to_python = `which #{cmd}`.to_s.strip
|
106
132
|
if path_to_python != ''
|
107
|
-
|
108
|
-
if check_virtualenv_installed(path_to_python)
|
109
|
-
return path_to_python
|
110
|
-
end
|
133
|
+
found_bins << path_to_python
|
111
134
|
end
|
112
135
|
}
|
113
|
-
return
|
136
|
+
return found_bins
|
114
137
|
end
|
115
138
|
|
116
139
|
|
@@ -135,11 +158,8 @@ class Mortar::Local::Python
|
|
135
158
|
end
|
136
159
|
|
137
160
|
def python_archive_url
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
def python_archive_file
|
142
|
-
File.basename(python_archive_url)
|
161
|
+
default_url = host + "/" + PYTHON_OSX_TGZ_DEFAULT_URL_PATH
|
162
|
+
return ENV.fetch('PYTHON_DISTRO_URL', default_url)
|
143
163
|
end
|
144
164
|
|
145
165
|
# Creates a virtualenv in a well known location and installs any packages
|