mortar 0.9.3 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|