mortar 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mortar/command/generate.rb +22 -4
- data/lib/mortar/command/jobs.rb +3 -2
- data/lib/mortar/command/local.rb +6 -6
- data/lib/mortar/command/projects.rb +1 -1
- data/lib/mortar/generators/controlscript_generator.rb +37 -0
- data/lib/mortar/generators/project_generator.rb +6 -0
- data/lib/mortar/git.rb +34 -3
- data/lib/mortar/helpers.rb +9 -5
- data/lib/mortar/local/controller.rb +6 -2
- data/lib/mortar/local/installutil.rb +30 -0
- data/lib/mortar/local/jython.rb +63 -0
- data/lib/mortar/local/pig.rb +55 -25
- data/lib/mortar/local/python.rb +24 -12
- data/lib/mortar/templates/controlscript/controlscript.py +11 -0
- data/lib/mortar/templates/pigscript/pigscript.pig +1 -1
- data/lib/mortar/templates/project/controlscripts/gitkeep +0 -0
- data/lib/mortar/templates/project/pigscripts/pigscript.pig +1 -1
- data/lib/mortar/version.rb +1 -1
- data/spec/mortar/command/generate_spec.rb +21 -0
- data/spec/mortar/command/jobs_spec.rb +0 -1
- data/spec/mortar/command/local_spec.rb +10 -2
- data/spec/mortar/command/projects_spec.rb +5 -1
- data/spec/mortar/helpers_spec.rb +25 -0
- data/spec/mortar/local/installutil_spec.rb +56 -0
- data/spec/mortar/local/jython_spec.rb +68 -0
- data/spec/mortar/local/pig_spec.rb +60 -12
- data/spec/mortar/local/python_spec.rb +68 -0
- metadata +10 -4
@@ -18,13 +18,14 @@ require "mortar/generators/project_generator"
|
|
18
18
|
require "mortar/generators/udf_generator"
|
19
19
|
require "mortar/generators/pigscript_generator"
|
20
20
|
require "mortar/generators/macro_generator"
|
21
|
+
require "mortar/generators/controlscript_generator"
|
21
22
|
require "mortar/command/base"
|
22
23
|
|
23
24
|
# generate mortar code (project, pigscript, python_udf, macro)
|
24
25
|
#
|
25
26
|
class Mortar::Command::Generate < Mortar::Command::Base
|
26
27
|
|
27
|
-
# generate:project
|
28
|
+
# generate:project PROJECTNAME
|
28
29
|
#
|
29
30
|
# Generate the files and directory structure necessary for a Mortar project.
|
30
31
|
#
|
@@ -39,7 +40,7 @@ class Mortar::Command::Generate < Mortar::Command::Base
|
|
39
40
|
end
|
40
41
|
alias_command "generate:project", "generate:_project"
|
41
42
|
|
42
|
-
# generate:python_udf
|
43
|
+
# generate:python_udf UDFNAME
|
43
44
|
#
|
44
45
|
# Generate a new python user defined function
|
45
46
|
#
|
@@ -52,7 +53,24 @@ class Mortar::Command::Generate < Mortar::Command::Base
|
|
52
53
|
udf_generator.generate_python_udf(udf_name, project, options)
|
53
54
|
end
|
54
55
|
|
55
|
-
# generate:
|
56
|
+
# generate:controlscript SCRIPTNAME
|
57
|
+
#
|
58
|
+
# Generate new control script.
|
59
|
+
#
|
60
|
+
def controlscript
|
61
|
+
script_name = shift_argument
|
62
|
+
unless script_name
|
63
|
+
error("Usage: mortar generate:controlscript SCRIPTNAME\nMust specify SCRIPTNAME.")
|
64
|
+
end
|
65
|
+
|
66
|
+
# Validates the we're in a mortar project
|
67
|
+
project
|
68
|
+
|
69
|
+
script_generator = Mortar::Generators::ControlscriptGenerator.new
|
70
|
+
script_generator.generate_controlscript(script_name, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
# generate:pigscript SCRIPTNAME
|
56
74
|
#
|
57
75
|
# Generate new pig script.
|
58
76
|
#
|
@@ -69,7 +87,7 @@ class Mortar::Command::Generate < Mortar::Command::Base
|
|
69
87
|
script_generator.generate_pigscript(script_name, project, options)
|
70
88
|
end
|
71
89
|
|
72
|
-
# generate:macro
|
90
|
+
# generate:macro MACRONAME
|
73
91
|
#
|
74
92
|
# Generate a new pig macro.
|
75
93
|
#
|
data/lib/mortar/command/jobs.rb
CHANGED
@@ -189,12 +189,13 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
189
189
|
end
|
190
190
|
|
191
191
|
if job_status["outputs"] && job_status["outputs"].length > 0
|
192
|
-
job_display_entries["outputs"] = Hash
|
192
|
+
job_display_entries["outputs"] = Hash.new { |h,k| h[k] = [] }
|
193
|
+
job_status["outputs"].select{|o| o["alias"]}.collect{ |output|
|
193
194
|
output_hash = {}
|
194
195
|
output_hash["location"] = output["location"] if output["location"]
|
195
196
|
output_hash["records"] = output["records"] if output["records"]
|
196
197
|
[output['alias'], output_hash]
|
197
|
-
|
198
|
+
}.each{ |k,v| job_display_entries["outputs"][k] << v }
|
198
199
|
end
|
199
200
|
|
200
201
|
if job_status["controlscript_name"]
|
data/lib/mortar/command/local.rb
CHANGED
@@ -32,7 +32,7 @@ class Mortar::Command::Local < Mortar::Command::Base
|
|
32
32
|
ctrl.install_and_configure
|
33
33
|
end
|
34
34
|
|
35
|
-
# local:run
|
35
|
+
# local:run SCRIPT
|
36
36
|
#
|
37
37
|
# Run a job on your local machine
|
38
38
|
#
|
@@ -44,14 +44,14 @@ class Mortar::Command::Local < Mortar::Command::Base
|
|
44
44
|
# Run the generate_regression_model_coefficients script locally.
|
45
45
|
# $ mortar local:run generate_regression_model_coefficients
|
46
46
|
def run
|
47
|
-
|
48
|
-
unless
|
49
|
-
error("Usage: mortar local:run
|
47
|
+
script_name = shift_argument
|
48
|
+
unless script_name
|
49
|
+
error("Usage: mortar local:run SCRIPT\nMust specify SCRIPT.")
|
50
50
|
end
|
51
51
|
validate_arguments!
|
52
|
-
|
52
|
+
script = validate_script!(script_name)
|
53
53
|
ctrl = Mortar::Local::Controller.new
|
54
|
-
ctrl.run(
|
54
|
+
ctrl.run(script, pig_parameters)
|
55
55
|
end
|
56
56
|
|
57
57
|
# illustrate [PIGSCRIPT] [ALIAS]
|
@@ -71,7 +71,6 @@ class Mortar::Command::Projects < Mortar::Command::Base
|
|
71
71
|
git.git("add .")
|
72
72
|
git.git("commit -m \"Mortar project scaffolding\"")
|
73
73
|
Mortar::Command::run("projects:register", [name])
|
74
|
-
git.git("push mortar master")
|
75
74
|
end
|
76
75
|
alias_command "new", "projects:create"
|
77
76
|
|
@@ -137,6 +136,7 @@ class Mortar::Command::Projects < Mortar::Command::Base
|
|
137
136
|
error("Project registration failed.\nError message: #{project_result['error_message']}")
|
138
137
|
when Mortar::API::Projects::STATUS_ACTIVE
|
139
138
|
git.remote_add("mortar", project_result['git_url'])
|
139
|
+
git.push_master
|
140
140
|
display "Your project is ready for use. Type 'mortar help' to see the commands you can perform on the project.\n\n"
|
141
141
|
else
|
142
142
|
raise RuntimeError, "Unknown project status: #{project_status} for project_id: #{project_id}"
|
@@ -0,0 +1,37 @@
|
|
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 "mortar/generators/generator_base"
|
18
|
+
module Mortar
|
19
|
+
module Generators
|
20
|
+
class ControlscriptGenerator < Base
|
21
|
+
|
22
|
+
def generate_controlscript(script_name, options)
|
23
|
+
set_script_binding(script_name, options)
|
24
|
+
|
25
|
+
generate_file "controlscript.py", "controlscripts/#{script_name}.py", :recursive => true
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def set_script_binding(script_name, options)
|
31
|
+
options = options
|
32
|
+
script_name = script_name
|
33
|
+
@script_binding = binding
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/mortar/git.rb
CHANGED
@@ -81,12 +81,45 @@ module Mortar
|
|
81
81
|
end
|
82
82
|
output
|
83
83
|
end
|
84
|
+
|
85
|
+
def push_master
|
86
|
+
unless has_commits?
|
87
|
+
raise GitError, "No commits found in repository. You must do an initial commit to initialize the repository."
|
88
|
+
end
|
89
|
+
|
90
|
+
safe_copy do
|
91
|
+
did_stash_changes = stash_working_dir("Stash for push to master")
|
92
|
+
git('push mortar master')
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Create a safe copy of the git directory
|
99
|
+
#
|
100
|
+
|
101
|
+
def safe_copy(&block)
|
102
|
+
# Copy code into a temp directory so we don't confuse editors while snapshotting
|
103
|
+
curdir = Dir.pwd
|
104
|
+
tmpdir = Dir.mktmpdir
|
105
|
+
FileUtils.cp_r(Dir.glob('*', File::FNM_DOTMATCH) - ['.', '..'], tmpdir)
|
106
|
+
Dir.chdir(tmpdir)
|
107
|
+
|
108
|
+
if block
|
109
|
+
yield
|
110
|
+
FileUtils.remove_entry_secure(tmpdir)
|
111
|
+
Dir.chdir(curdir)
|
112
|
+
else
|
113
|
+
return tmpdir
|
114
|
+
end
|
115
|
+
end
|
84
116
|
|
85
117
|
#
|
86
118
|
# snapshot
|
87
119
|
#
|
88
120
|
|
89
121
|
def create_snapshot_branch
|
122
|
+
|
90
123
|
# TODO: handle Ctrl-C in the middle
|
91
124
|
# TODO: can we do the equivalent of stash without changing the working directory
|
92
125
|
unless has_commits?
|
@@ -95,9 +128,7 @@ module Mortar
|
|
95
128
|
|
96
129
|
# Copy code into a temp directory so we don't confuse editors while snapshotting
|
97
130
|
curdir = Dir.pwd
|
98
|
-
tmpdir =
|
99
|
-
FileUtils.cp_r(Dir.glob('*', File::FNM_DOTMATCH) - ['.', '..'], tmpdir)
|
100
|
-
Dir.chdir(tmpdir)
|
131
|
+
tmpdir = safe_copy
|
101
132
|
|
102
133
|
starting_branch = current_branch
|
103
134
|
snapshot_branch = "mortar-snapshot-#{Mortar::UUID.create_random.to_s}"
|
data/lib/mortar/helpers.rb
CHANGED
@@ -422,10 +422,14 @@ module Mortar
|
|
422
422
|
next
|
423
423
|
else
|
424
424
|
elements = value.sort {|x,y| x.to_s <=> y.to_s}
|
425
|
-
display_with_indent(indent, "#{key}: ".ljust(max_key_length)
|
426
|
-
|
427
|
-
|
428
|
-
|
425
|
+
display_with_indent(indent, "#{key}: ".ljust(max_key_length))
|
426
|
+
elements[0..-1].each do |element|
|
427
|
+
case element
|
428
|
+
when Hash
|
429
|
+
styled_hash(element, nil, indent + 2)
|
430
|
+
else
|
431
|
+
display_with_indent(indent, "#{' ' * max_key_length}#{element}")
|
432
|
+
end
|
429
433
|
end
|
430
434
|
if elements.length > 1
|
431
435
|
display
|
@@ -495,7 +499,7 @@ module Mortar
|
|
495
499
|
end
|
496
500
|
|
497
501
|
def ensure_dir_exists(dir)
|
498
|
-
unless
|
502
|
+
unless File.directory? dir
|
499
503
|
Dir.mkdir(dir)
|
500
504
|
end
|
501
505
|
end
|
@@ -18,6 +18,7 @@ require "mortar/helpers"
|
|
18
18
|
require "mortar/local/pig"
|
19
19
|
require "mortar/local/java"
|
20
20
|
require "mortar/local/python"
|
21
|
+
require "mortar/local/jython"
|
21
22
|
|
22
23
|
|
23
24
|
class Mortar::Local::Controller
|
@@ -34,7 +35,7 @@ Linux systems please consult the documentation on your relevant package manager.
|
|
34
35
|
EOF
|
35
36
|
|
36
37
|
NO_PYTHON_ERROR_MESSAGE = <<EOF
|
37
|
-
|
38
|
+
A suitable python installation with virtualenv could not be located. Please ensure
|
38
39
|
you have python 2.6+ installed on your local system. If you need to obtain a copy
|
39
40
|
of virtualenv it can be located here:
|
40
41
|
https://pypi.python.org/pypi/virtualenv
|
@@ -75,7 +76,7 @@ EOF
|
|
75
76
|
end
|
76
77
|
|
77
78
|
pig = Mortar::Local::Pig.new()
|
78
|
-
pig.
|
79
|
+
pig.install_or_update()
|
79
80
|
|
80
81
|
py = Mortar::Local::Python.new()
|
81
82
|
unless py.check_or_install
|
@@ -87,6 +88,9 @@ EOF
|
|
87
88
|
msg += "see #{py.pip_error_log_path} for more details"
|
88
89
|
error(msg)
|
89
90
|
end
|
91
|
+
|
92
|
+
jy = Mortar::Local::Jython.new()
|
93
|
+
jy.install_or_update()
|
90
94
|
end
|
91
95
|
|
92
96
|
# Main entry point for user running a pig script
|
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
require 'zlib'
|
18
18
|
require 'excon'
|
19
|
+
require 'time'
|
19
20
|
require 'rbconfig'
|
20
21
|
require 'rubygems/package'
|
21
22
|
|
@@ -33,6 +34,13 @@ module Mortar
|
|
33
34
|
File.join(Dir.getwd, ".mortar-local")
|
34
35
|
end
|
35
36
|
|
37
|
+
def jython_directory
|
38
|
+
local_install_directory + "/jython"
|
39
|
+
end
|
40
|
+
|
41
|
+
def jython_cache_directory
|
42
|
+
jython_directory + "/cachedir"
|
43
|
+
end
|
36
44
|
|
37
45
|
# Drops a marker file for an installed package, used
|
38
46
|
# to help determine if updates should be performed
|
@@ -89,6 +97,28 @@ module Mortar
|
|
89
97
|
return os_platform_name.start_with?('darwin')
|
90
98
|
end
|
91
99
|
|
100
|
+
def http_date_to_epoch(date_str)
|
101
|
+
return Time.httpdate(date_str).to_i
|
102
|
+
end
|
103
|
+
|
104
|
+
def url_date(url)
|
105
|
+
result = Excon.head(url)
|
106
|
+
http_date_to_epoch(result.get_header('Last-Modified'))
|
107
|
+
end
|
108
|
+
|
109
|
+
# Given a subdirectory where we have installed some software
|
110
|
+
# and a url to the tgz file it's sourced from, check if the
|
111
|
+
# remote version is newer than the installed version
|
112
|
+
def is_newer_version(subdir, url)
|
113
|
+
existing_install_date = install_date(subdir)
|
114
|
+
if not existing_install_date then
|
115
|
+
# There is no existing install
|
116
|
+
return true
|
117
|
+
end
|
118
|
+
remote_archive_date = url_date(url)
|
119
|
+
return existing_install_date < remote_archive_date
|
120
|
+
end
|
121
|
+
|
92
122
|
end
|
93
123
|
end
|
94
124
|
end
|
@@ -0,0 +1,63 @@
|
|
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 "mortar/local/installutil"
|
18
|
+
|
19
|
+
class Mortar::Local::Jython
|
20
|
+
include Mortar::Local::InstallUtil
|
21
|
+
|
22
|
+
JYTHON_VERSION = '2.5.2'
|
23
|
+
JYTHON_JAR_NAME = 'jython_installer-' + JYTHON_VERSION + '.jar'
|
24
|
+
JYTHON_JAR_DIR = "http://s3.amazonaws.com/hawk-dev-software-mirror/jython/jython-2.5.2/"
|
25
|
+
|
26
|
+
def install_or_update
|
27
|
+
if should_install
|
28
|
+
action("Installing jython") do
|
29
|
+
install
|
30
|
+
end
|
31
|
+
elsif should_update
|
32
|
+
action("Updating jython") do
|
33
|
+
update
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_install
|
39
|
+
not File.exists?(jython_directory)
|
40
|
+
end
|
41
|
+
|
42
|
+
def install
|
43
|
+
unless File.exists?(local_install_directory + '/' + JYTHON_JAR_NAME)
|
44
|
+
download_file(JYTHON_JAR_DIR + JYTHON_JAR_NAME, local_install_directory)
|
45
|
+
end
|
46
|
+
|
47
|
+
`$JAVA_HOME/bin/java -jar #{local_install_directory + '/' + JYTHON_JAR_NAME} -s -d #{jython_directory}`
|
48
|
+
FileUtils.mkdir_p jython_cache_directory
|
49
|
+
FileUtils.chmod_R 0777, jython_cache_directory
|
50
|
+
|
51
|
+
FileUtils.rm(local_install_directory + '/' + JYTHON_JAR_NAME)
|
52
|
+
note_install('jython')
|
53
|
+
end
|
54
|
+
|
55
|
+
def should_update
|
56
|
+
return is_newer_version('jython', JYTHON_JAR_DIR + JYTHON_JAR_NAME)
|
57
|
+
end
|
58
|
+
|
59
|
+
def update
|
60
|
+
FileUtils.rm_r(jython_directory)
|
61
|
+
install
|
62
|
+
end
|
63
|
+
end
|
data/lib/mortar/local/pig.rb
CHANGED
@@ -23,7 +23,7 @@ class Mortar::Local::Pig
|
|
23
23
|
include Mortar::Local::InstallUtil
|
24
24
|
|
25
25
|
PIG_LOG_FORMAT = "humanreadable"
|
26
|
-
PIG_TAR_DEFAULT_URL = "https://s3.amazonaws.com/
|
26
|
+
PIG_TAR_DEFAULT_URL = "https://s3.amazonaws.com/mhc-software-mirror/cli/pig.tgz"
|
27
27
|
|
28
28
|
# Tempfile objects have a hook to delete the file when the object is
|
29
29
|
# destroyed by the garbage collector. In practice this means that a
|
@@ -84,34 +84,48 @@ class Mortar::Local::Pig
|
|
84
84
|
File.basename(pig_archive_url)
|
85
85
|
end
|
86
86
|
|
87
|
-
# Determines if a pig install needs to occur, true if no
|
88
|
-
# pig install present or a newer version is available
|
87
|
+
# Determines if a pig install needs to occur, true if no pig install present
|
89
88
|
def should_do_pig_install?
|
90
89
|
not (File.exists?(pig_directory))
|
91
90
|
end
|
92
91
|
|
93
|
-
#
|
94
|
-
|
92
|
+
# Determines if a pig install needs to occur, true if server side
|
93
|
+
# pig tgz is newer than date of the existing install
|
94
|
+
def should_do_pig_update?
|
95
|
+
return is_newer_version('pig', pig_archive_url)
|
96
|
+
end
|
97
|
+
|
98
|
+
def install_or_update()
|
99
|
+
call_install = false
|
95
100
|
if should_do_pig_install?
|
96
|
-
FileUtils.mkdir_p(local_install_directory)
|
97
101
|
action "Installing pig" do
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
# here to be sure it has the necessary permissions
|
104
|
-
FileUtils.chmod(0755, command)
|
105
|
-
|
106
|
-
File.delete(local_tgz)
|
107
|
-
note_install("pig")
|
102
|
+
install()
|
103
|
+
end
|
104
|
+
elsif should_do_pig_update?
|
105
|
+
action "Updating to latest pig" do
|
106
|
+
install()
|
108
107
|
end
|
109
108
|
end
|
110
109
|
end
|
111
110
|
|
111
|
+
# Installs pig for this project if it is not already present
|
112
|
+
def install
|
113
|
+
FileUtils.mkdir_p(local_install_directory)
|
114
|
+
download_file(pig_archive_url, local_install_directory)
|
115
|
+
local_tgz = File.join(local_install_directory, pig_archive_file)
|
116
|
+
extract_tgz(local_tgz, local_install_directory)
|
117
|
+
|
118
|
+
# This has been seening coming out of the tgz w/o +x so we do
|
119
|
+
# here to be sure it has the necessary permissions
|
120
|
+
FileUtils.chmod(0755, command)
|
121
|
+
|
122
|
+
File.delete(local_tgz)
|
123
|
+
note_install("pig")
|
124
|
+
end
|
125
|
+
|
112
126
|
# run the pig script with user supplied pig parameters
|
113
127
|
def run_script(pig_script, pig_parameters)
|
114
|
-
run_pig_command(" -f #{pig_script.path}", pig_parameters)
|
128
|
+
run_pig_command(" -f #{pig_script.path}", pig_parameters, true)
|
115
129
|
end
|
116
130
|
|
117
131
|
# Create a temp file to be used for writing the illustrate
|
@@ -146,8 +160,8 @@ class Mortar::Local::Pig
|
|
146
160
|
ensure_dir_exists("illustrate-output/resources/js")
|
147
161
|
ensure_dir_exists("illustrate-output/resources/flash")
|
148
162
|
|
149
|
-
["illustrate_css",
|
150
|
-
"jquery", "jquery_transit", "jquery_stylestack",
|
163
|
+
["illustrate_css",
|
164
|
+
"jquery", "jquery_transit", "jquery_stylestack",
|
151
165
|
"mortar_table", "zeroclipboard", "zeroclipboard_swf"].each { |resource|
|
152
166
|
copy_if_not_present_at_dest(@resource_locations[resource], @resource_destinations[resource])
|
153
167
|
}
|
@@ -199,14 +213,17 @@ class Mortar::Local::Pig
|
|
199
213
|
end
|
200
214
|
cmd += " #{pig_alias} '"
|
201
215
|
|
202
|
-
run_pig_command(cmd, [])
|
203
|
-
|
216
|
+
result = run_pig_command(cmd, [], false)
|
217
|
+
if result
|
218
|
+
show_illustrate_output(illustrate_outpath)
|
219
|
+
end
|
204
220
|
end
|
205
221
|
|
206
222
|
# Run pig with the specified command ('command' is anything that
|
207
223
|
# can be appended to the command line invocation of Pig that will
|
208
224
|
# get it to do something interesting, such as '-f some-file.pig'
|
209
|
-
def run_pig_command(cmd, parameters = nil)
|
225
|
+
def run_pig_command(cmd, parameters = nil, jython_output = true)
|
226
|
+
unset_hadoop_env_vars
|
210
227
|
# Generate the script for running the command, then
|
211
228
|
# write it to a temp script which will be exectued
|
212
229
|
script_text = script_for_command(cmd, parameters)
|
@@ -216,12 +233,21 @@ class Mortar::Local::Pig
|
|
216
233
|
FileUtils.chmod(0755, script.path)
|
217
234
|
system(script.path)
|
218
235
|
script.unlink
|
236
|
+
return (0 == $?.to_i)
|
237
|
+
end
|
238
|
+
|
239
|
+
# so Pig doesn't try to load the wrong hadoop jar/configuration
|
240
|
+
# this doesn't mess up the env vars in the terminal, just this process (ruby)
|
241
|
+
def unset_hadoop_env_vars
|
242
|
+
ENV['HADOOP_HOME'] = ''
|
243
|
+
ENV['HADOOP_CONF_DIR'] = ''
|
219
244
|
end
|
220
245
|
|
221
246
|
# Generates a bash script which sets up the necessary environment and
|
222
247
|
# then runs the pig command
|
223
|
-
def script_for_command(cmd, parameters)
|
248
|
+
def script_for_command(cmd, parameters, jython_output = true)
|
224
249
|
template_params = pig_command_script_template_parameters(cmd, parameters)
|
250
|
+
template_params['pig_opts']['jython.output'] = jython_output
|
225
251
|
erb = ERB.new(File.read(pig_command_script_template_path), 0, "%<>")
|
226
252
|
erb.result(BindingClazz.new(template_params).get_binding)
|
227
253
|
end
|
@@ -236,8 +262,8 @@ class Mortar::Local::Pig
|
|
236
262
|
template_params = {}
|
237
263
|
template_params['pig_params_file'] = make_pig_param_file(pig_parameters)
|
238
264
|
template_params['pig_home'] = pig_directory
|
239
|
-
template_params['pig_classpath'] = "#{pig_directory}/lib-pig
|
240
|
-
template_params['classpath'] = "#{pig_directory}/lib/*:#{pig_directory}/conf/jets3t.properties"
|
265
|
+
template_params['pig_classpath'] = "#{pig_directory}/lib-pig/*:#{jython_directory}/jython.jar"
|
266
|
+
template_params['classpath'] = "#{pig_directory}/lib/*:#{jython_directory}/jython.jar:#{pig_directory}/conf/jets3t.properties"
|
241
267
|
template_params['project_home'] = File.expand_path("..", local_install_directory)
|
242
268
|
template_params['local_install_dir'] = local_install_directory
|
243
269
|
template_params['pig_sub_command'] = cmd
|
@@ -252,6 +278,10 @@ class Mortar::Local::Pig
|
|
252
278
|
opts['fs.s3n.awsAccessKeyId'] = ENV['AWS_ACCESS_KEY']
|
253
279
|
opts['fs.s3n.awsSecretAccessKey'] = ENV['AWS_SECRET_KEY']
|
254
280
|
opts['pig.events.logformat'] = PIG_LOG_FORMAT
|
281
|
+
opts['python.verbose'] = 'error'
|
282
|
+
opts['jython.output'] = true
|
283
|
+
opts['python.home'] = jython_directory
|
284
|
+
opts['python.cachedir'] = jython_cache_directory
|
255
285
|
return opts
|
256
286
|
end
|
257
287
|
|
data/lib/mortar/local/python.rb
CHANGED
@@ -19,7 +19,7 @@ require "mortar/local/installutil"
|
|
19
19
|
class Mortar::Local::Python
|
20
20
|
include Mortar::Local::InstallUtil
|
21
21
|
|
22
|
-
PYTHON_DEFAULT_TGZ_URL = "https://s3.amazonaws.com/
|
22
|
+
PYTHON_DEFAULT_TGZ_URL = "https://s3.amazonaws.com/mhc-software-mirror/cli/mortar-python-osx.tgz"
|
23
23
|
|
24
24
|
# Path to the python binary that should be used
|
25
25
|
# for running UDFs
|
@@ -31,33 +31,45 @@ class Mortar::Local::Python
|
|
31
31
|
def check_or_install
|
32
32
|
if osx?
|
33
33
|
# We currently only install python for osx
|
34
|
-
|
34
|
+
install_or_update_osx
|
35
35
|
else
|
36
36
|
# Otherwise we check that the system supplied python will be sufficient
|
37
37
|
check_system_python
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def should_do_update?
|
42
|
+
return is_newer_version('python', python_archive_url)
|
43
|
+
end
|
44
|
+
|
41
45
|
# Performs an installation of python specific to this project, this
|
42
46
|
# install includes pip and virtualenv
|
43
|
-
def
|
47
|
+
def install_or_update_osx
|
44
48
|
@command = "#{local_install_directory}/python/bin/python"
|
45
49
|
if should_do_python_install?
|
46
|
-
FileUtils.mkdir_p(local_install_directory)
|
47
50
|
action "Installing python" do
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
FileUtils.chmod(0755, @command)
|
54
|
-
File.delete(local_install_directory + "/" + python_archive_file)
|
55
|
-
note_install("python")
|
51
|
+
install_osx
|
52
|
+
end
|
53
|
+
elsif should_do_update?
|
54
|
+
action "Updating to latest python" do
|
55
|
+
install_osx
|
56
56
|
end
|
57
57
|
end
|
58
58
|
true
|
59
59
|
end
|
60
60
|
|
61
|
+
def install_osx
|
62
|
+
FileUtils.mkdir_p(local_install_directory)
|
63
|
+
download_file(python_archive_url, local_install_directory)
|
64
|
+
extract_tgz(local_install_directory + "/" + python_archive_file, local_install_directory)
|
65
|
+
|
66
|
+
# This has been seening coming out of the tgz w/o +x so we do
|
67
|
+
# here to be sure it has the necessary permissions
|
68
|
+
FileUtils.chmod(0755, @command)
|
69
|
+
File.delete(local_install_directory + "/" + python_archive_file)
|
70
|
+
note_install("python")
|
71
|
+
end
|
72
|
+
|
61
73
|
# Determines if a python install needs to occur, true if no
|
62
74
|
# python install present or a newer version is available
|
63
75
|
def should_do_python_install?
|
@@ -6,7 +6,7 @@
|
|
6
6
|
* Parameters - set default values here; you can override with -p on the command-line.
|
7
7
|
*/
|
8
8
|
|
9
|
-
<%= '%default'%> INPUT_PATH 's3n://
|
9
|
+
<%= '%default'%> INPUT_PATH 's3n://mortar-example-data/tutorial/excite.log.bz2'
|
10
10
|
<%= '%default'%> OUTPUT_PATH 's3n://my-output-bucket/$MORTAR_EMAIL_S3_ESCAPED/<%= script_name %>'
|
11
11
|
|
12
12
|
<% if not options[:skip_udf] %>
|
File without changes
|
@@ -6,7 +6,7 @@
|
|
6
6
|
* Parameters - set default values here; you can override with -p on the command-line.
|
7
7
|
*/
|
8
8
|
|
9
|
-
<%= '%default'%> INPUT_PATH 's3n://
|
9
|
+
<%= '%default'%> INPUT_PATH 's3n://mortar-example-data/tutorial/excite.log.bz2'
|
10
10
|
<%= '%default'%> OUTPUT_PATH 's3n://my-output-bucket/$MORTAR_EMAIL_S3_ESCAPED/<%= project_name %>'
|
11
11
|
|
12
12
|
/**
|
data/lib/mortar/version.rb
CHANGED
@@ -34,6 +34,7 @@ describe Mortar::Command::Generate do
|
|
34
34
|
File.exists?("Test/macros").should be_true
|
35
35
|
File.exists?("Test/fixtures").should be_true
|
36
36
|
File.exists?("Test/pigscripts").should be_true
|
37
|
+
File.exists?("Test/controlscripts").should be_true
|
37
38
|
File.exists?("Test/udfs").should be_true
|
38
39
|
File.exists?("Test/README.md").should be_true
|
39
40
|
File.exists?("Test/Gemfile").should be_false
|
@@ -99,6 +100,26 @@ STDERR
|
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
103
|
+
describe "generate:controlscript" do
|
104
|
+
it "Generate a new controlscript in a project" do
|
105
|
+
with_blank_project do |p|
|
106
|
+
stderr, stdout = execute("generate:controlscript Oink", p)
|
107
|
+
File.exists?(File.join(p.root_path, "controlscripts/Oink.py")).should be_true
|
108
|
+
File.read("controlscripts/Oink.py").each_line { |line| line.match(/<%.*%>/).should be_nil }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it "error when controlscript name isn't provided" do
|
113
|
+
with_blank_project do |p|
|
114
|
+
stderr, stdout = execute("generate:controlscript")
|
115
|
+
stderr.should == <<-STDERR
|
116
|
+
! Usage: mortar generate:controlscript SCRIPTNAME
|
117
|
+
! Must specify SCRIPTNAME.
|
118
|
+
STDERR
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
102
123
|
describe "generate:python_udf" do
|
103
124
|
it "Generate a new python udf in a project" do
|
104
125
|
with_blank_project do |p|
|
@@ -69,11 +69,16 @@ STDERR
|
|
69
69
|
it "errors when the script doesn't exist" do
|
70
70
|
with_git_initialized_project do |p|
|
71
71
|
write_file(File.join(p.pigscripts_path, "my_other_script.pig"))
|
72
|
+
write_file(File.join(p.controlscripts_path, "my_control_script.py"))
|
72
73
|
stderr, stdout = execute("local:run my_script", p)
|
73
74
|
stderr.should == <<-STDERR
|
74
|
-
! Unable to find pigscript my_script
|
75
|
-
!
|
75
|
+
! Unable to find a pigscript or controlscript for my_script
|
76
|
+
!
|
77
|
+
! Available pigscripts:
|
76
78
|
! my_other_script
|
79
|
+
!
|
80
|
+
! Available controlscripts:
|
81
|
+
! my_control_script
|
77
82
|
STDERR
|
78
83
|
end
|
79
84
|
end
|
@@ -132,6 +137,9 @@ STDERR
|
|
132
137
|
any_instance_of(Mortar::Local::Python) do |j|
|
133
138
|
mock(j).setup_project_python_environment.returns(true)
|
134
139
|
end
|
140
|
+
any_instance_of(Mortar::Local::Jython) do |j|
|
141
|
+
mock(j).install_or_update.returns(true)
|
142
|
+
end
|
135
143
|
stderr, stdout = execute("local:configure")
|
136
144
|
stderr.should == ""
|
137
145
|
end
|
@@ -104,7 +104,7 @@ STDOUT
|
|
104
104
|
# if the git stuff doesn't work, the registration will fail, so we can pretend it does work here
|
105
105
|
mock(@git).git("add .").returns(true)
|
106
106
|
mock(@git).git("commit -m \"Mortar project scaffolding\"").returns(true)
|
107
|
-
mock(@git).
|
107
|
+
mock(@git).push_master
|
108
108
|
|
109
109
|
stderr, stdout = execute("projects:create #{project_name}", nil, @git)
|
110
110
|
Dir.pwd.end_with?("some_new_project").should be_true
|
@@ -127,6 +127,8 @@ STDOUT
|
|
127
127
|
\e[1;32m create\e[0m .gitignore
|
128
128
|
\e[1;32m create\e[0m pigscripts
|
129
129
|
\e[1;32m create\e[0m pigscripts/some_new_project.pig
|
130
|
+
\e[1;32m create\e[0m controlscripts
|
131
|
+
\e[1;32m create\e[0m controlscripts/.gitkeep
|
130
132
|
\e[1;32m create\e[0m macros
|
131
133
|
\e[1;32m create\e[0m macros/.gitkeep
|
132
134
|
\e[1;32m create\e[0m fixtures
|
@@ -215,6 +217,7 @@ STDERR
|
|
215
217
|
mock(@git).has_dot_git?().returns(true)
|
216
218
|
mock(@git).remotes.with_any_args.returns({})
|
217
219
|
mock(@git).remote_add("mortar", project_git_url)
|
220
|
+
mock(@git).push_master
|
218
221
|
|
219
222
|
stderr, stdout = execute("projects:register #{project_name} --polling_interval 0.05", nil, @git)
|
220
223
|
stdout.should == <<-STDOUT
|
@@ -236,6 +239,7 @@ STDOUT
|
|
236
239
|
mock(@git).has_dot_git?().returns(true)
|
237
240
|
mock(@git).remotes.with_any_args.returns({})
|
238
241
|
mock(@git).remote_add("mortar", project_git_url)
|
242
|
+
mock(@git).push_master
|
239
243
|
|
240
244
|
stderr, stdout = execute("projects:register #{project_name} --polling_interval 0.05", nil, @git)
|
241
245
|
stdout.should == <<-STDOUT
|
data/spec/mortar/helpers_spec.rb
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
|
20
20
|
require "spec_helper"
|
21
21
|
require "mortar/helpers"
|
22
|
+
require 'fakefs/spec_helpers'
|
22
23
|
|
23
24
|
module Mortar
|
24
25
|
describe Helpers do
|
@@ -78,5 +79,29 @@ OUT
|
|
78
79
|
infile.close()
|
79
80
|
end
|
80
81
|
end
|
82
|
+
|
83
|
+
context "ensure_dir_exists" do
|
84
|
+
|
85
|
+
it "does not have an existing directory" do
|
86
|
+
FakeFS do
|
87
|
+
dir_name = "./foo-bar-dir"
|
88
|
+
expect(File.directory?(dir_name)).to be_false
|
89
|
+
ensure_dir_exists(dir_name)
|
90
|
+
expect(File.directory?(dir_name)).to be_true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it "does have an existing directory" do
|
95
|
+
FakeFS do
|
96
|
+
dir_name = "./foo-bar-dir"
|
97
|
+
FileUtils.mkdir_p(dir_name)
|
98
|
+
expect(File.directory?(dir_name)).to be_true
|
99
|
+
ensure_dir_exists(dir_name)
|
100
|
+
expect(File.directory?(dir_name)).to be_true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
81
106
|
end
|
82
107
|
end
|
@@ -49,6 +49,17 @@ module Mortar::Local
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
it "works with file created by note-install" do
|
53
|
+
install_file_path = @installutil.install_file_for("foo")
|
54
|
+
install_date = 1234568
|
55
|
+
stub(Time).now.returns(install_date)
|
56
|
+
FakeFS do
|
57
|
+
FileUtils.mkdir_p(File.dirname(install_file_path))
|
58
|
+
@installutil.note_install('foo')
|
59
|
+
expect(@installutil.install_date('foo')).to eq(install_date)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
52
63
|
end
|
53
64
|
|
54
65
|
context("note-install") do
|
@@ -66,5 +77,50 @@ module Mortar::Local
|
|
66
77
|
|
67
78
|
end
|
68
79
|
|
80
|
+
context "is_newer_version" do
|
81
|
+
|
82
|
+
it "is if remote file is newer" do
|
83
|
+
stub(@installutil).install_date.returns(1)
|
84
|
+
stub(@installutil).url_date.returns(2)
|
85
|
+
expect(@installutil.is_newer_version('foo', 'http://bar')).to be_true
|
86
|
+
end
|
87
|
+
|
88
|
+
it "is not if remote file is older" do
|
89
|
+
stub(@installutil).install_date.returns(2)
|
90
|
+
stub(@installutil).url_date.returns(1)
|
91
|
+
expect(@installutil.is_newer_version('foo', 'http://bar')).to be_false
|
92
|
+
end
|
93
|
+
|
94
|
+
it "if no version is present" do
|
95
|
+
install_file_path = @installutil.install_file_for("foo")
|
96
|
+
stub(@installutil).url_date.returns(1)
|
97
|
+
FakeFS do
|
98
|
+
FileUtils.rm_rf(File.dirname(install_file_path), :force => true)
|
99
|
+
expect(@installutil.is_newer_version('foo', 'http://bar')).to be_true
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
context "url_date" do
|
106
|
+
|
107
|
+
it "returns an epoch" do
|
108
|
+
excon_response = Excon::Response.new(:headers => {"Last-Modified" => "Mon, 11 Mar 2013 15:03:55 GMT"})
|
109
|
+
mock(Excon).head("http://foo/bar").returns(excon_response)
|
110
|
+
actual_epoch = @installutil.url_date("http://foo/bar")
|
111
|
+
expect(actual_epoch).to eq(1363014235)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
context "parse_http_date" do
|
117
|
+
|
118
|
+
it "returns the appropriate epoch" do
|
119
|
+
epoch = @installutil.http_date_to_epoch("Mon, 11 Mar 2013 15:03:55 GMT")
|
120
|
+
expect(epoch).to eq(1363014235)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
69
125
|
end
|
70
126
|
end
|
@@ -0,0 +1,68 @@
|
|
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 'spec_helper'
|
18
|
+
require 'fakefs/spec_helpers'
|
19
|
+
require 'mortar/local/jython'
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
module Mortar::Local
|
24
|
+
describe Jython do
|
25
|
+
|
26
|
+
context("update") do
|
27
|
+
|
28
|
+
it "removes existing install and does install" do
|
29
|
+
install_dir = "/foo/bar/jython"
|
30
|
+
jython = Mortar::Local::Jython.new
|
31
|
+
mock(jython).jython_directory.returns(install_dir)
|
32
|
+
mock(jython).install
|
33
|
+
FakeFS do
|
34
|
+
FileUtils.mkdir_p(install_dir)
|
35
|
+
expect(File.directory?(install_dir)).to be_true
|
36
|
+
jython.update
|
37
|
+
expect(File.directory?(install_dir)).to be_false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
context "should_install" do
|
44
|
+
|
45
|
+
it "is true if the directory does not exist" do
|
46
|
+
install_dir = "/foo/bar/jython"
|
47
|
+
jython = Mortar::Local::Jython.new
|
48
|
+
mock(jython).jython_directory.returns(install_dir)
|
49
|
+
FakeFS do
|
50
|
+
FileUtils.mkdir_p(install_dir)
|
51
|
+
expect(jython.should_install).to be_false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "is false if the directory already exists" do
|
56
|
+
install_dir = "/foo/bar/jython"
|
57
|
+
jython = Mortar::Local::Jython.new
|
58
|
+
mock(jython).jython_directory.returns(install_dir)
|
59
|
+
FakeFS do
|
60
|
+
FileUtils.rm_rf(install_dir, :force => true)
|
61
|
+
expect(jython.should_install).to be_true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -30,24 +30,12 @@ module Mortar::Local
|
|
30
30
|
|
31
31
|
context("install") do
|
32
32
|
|
33
|
-
it "does nothing if told not to" do
|
34
|
-
pig = Mortar::Local::Pig.new
|
35
|
-
mock(pig).should_do_pig_install?.returns(false)
|
36
|
-
FakeFS do
|
37
|
-
FileUtils.mkdir_p(File.dirname(pig.local_install_directory))
|
38
|
-
FileUtils.rm_rf(pig.local_install_directory, :force => true)
|
39
|
-
pig.install
|
40
|
-
expect(File.exists?(pig.local_install_directory)).to be_false
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
33
|
it "handles necessary installation steps" do
|
45
34
|
# creates the parent directory, downloads the tgz, extracts it,
|
46
35
|
# chmods bin/pig, removes tgz, and notes the installation
|
47
36
|
FakeFS do
|
48
37
|
pig = Mortar::Local::Pig.new
|
49
38
|
local_pig_archive = File.join(pig.local_install_directory, pig.pig_archive_file)
|
50
|
-
mock(pig).should_do_pig_install?.returns(true)
|
51
39
|
mock(pig).download_file(pig.pig_archive_url, pig.local_install_directory) do
|
52
40
|
# Simulate the tgz file being downloaded, this should be deleted
|
53
41
|
# before the method finishes executing
|
@@ -67,6 +55,42 @@ module Mortar::Local
|
|
67
55
|
|
68
56
|
end
|
69
57
|
|
58
|
+
context "install_or_update" do
|
59
|
+
|
60
|
+
it "does nothing if existing install and no update available" do
|
61
|
+
pig = Mortar::Local::Pig.new
|
62
|
+
mock(pig).should_do_pig_install?.returns(false)
|
63
|
+
mock(pig).should_do_pig_update?.returns(false)
|
64
|
+
FakeFS do
|
65
|
+
FileUtils.mkdir_p(File.dirname(pig.local_install_directory))
|
66
|
+
FileUtils.rm_rf(pig.local_install_directory, :force => true)
|
67
|
+
pig.install_or_update
|
68
|
+
expect(File.exists?(pig.local_install_directory)).to be_false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "does install if none has been done before" do
|
73
|
+
pig = Mortar::Local::Pig.new
|
74
|
+
mock(pig).should_do_pig_install?.returns(true)
|
75
|
+
mock(pig).install
|
76
|
+
capture_stdout do
|
77
|
+
pig.install_or_update
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "does install if one was done before but there is an update" do
|
82
|
+
pig = Mortar::Local::Pig.new
|
83
|
+
mock(pig).should_do_pig_install?.returns(false)
|
84
|
+
mock(pig).should_do_pig_update?.returns(true)
|
85
|
+
mock(pig).install
|
86
|
+
capture_stdout do
|
87
|
+
pig.install_or_update
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
70
94
|
context "show_illustrate_output" do
|
71
95
|
|
72
96
|
it "takes a path to a json file, renders the html template, and opens it" do
|
@@ -153,5 +177,29 @@ module Mortar::Local
|
|
153
177
|
|
154
178
|
end
|
155
179
|
|
180
|
+
context "illustrate_alias" do
|
181
|
+
|
182
|
+
it "displays html results if illustrate was successful" do
|
183
|
+
any_instance_of(Mortar::Project::PigScripts, :elements => nil, :path => "/foo/bar/baz.pig")
|
184
|
+
script = Mortar::Project::PigScripts.new('/foo/bar/baz.pig', 'baz', 'pig')
|
185
|
+
pig = Mortar::Local::Pig.new
|
186
|
+
mock(pig).run_pig_command.with_any_args.returns(true)
|
187
|
+
mock(pig).show_illustrate_output.with_any_args
|
188
|
+
stub(pig).make_pig_param_file.returns('param.file')
|
189
|
+
pig.illustrate_alias(script, 'my_alias', false, [])
|
190
|
+
end
|
191
|
+
|
192
|
+
it "skips results if illustrate was unsuccessful" do
|
193
|
+
any_instance_of(Mortar::Project::PigScripts, :elements => nil, :path => "/foo/bar/baz.pig")
|
194
|
+
script = Mortar::Project::PigScripts.new('/foo/bar/baz.pig', 'baz', 'pig')
|
195
|
+
pig = Mortar::Local::Pig.new
|
196
|
+
mock(pig).run_pig_command.with_any_args.returns(false)
|
197
|
+
mock(pig).show_illustrate_output.with_any_args.never
|
198
|
+
stub(pig).make_pig_param_file.returns('param.file')
|
199
|
+
pig.illustrate_alias(script, 'my_alias', false, [])
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
|
156
204
|
end
|
157
205
|
end
|
@@ -0,0 +1,68 @@
|
|
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 'spec_helper'
|
18
|
+
require 'fakefs/spec_helpers'
|
19
|
+
require 'mortar/local/python'
|
20
|
+
require 'launchy'
|
21
|
+
|
22
|
+
|
23
|
+
module Mortar::Local
|
24
|
+
describe Python do
|
25
|
+
|
26
|
+
context("check_or_install") do
|
27
|
+
|
28
|
+
it "checks for python system requirements if not osx" do
|
29
|
+
python = Mortar::Local::Python.new
|
30
|
+
mock(python).osx?.returns(true)
|
31
|
+
mock(python).install_or_update_osx.returns(true)
|
32
|
+
python.check_or_install
|
33
|
+
end
|
34
|
+
|
35
|
+
it "installs python on osx" do
|
36
|
+
python = Mortar::Local::Python.new
|
37
|
+
mock(python).osx?.returns(false)
|
38
|
+
mock(python).check_system_python.returns(true)
|
39
|
+
python.check_or_install
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context("install_or_update_osx") do
|
45
|
+
|
46
|
+
it "does install if none present" do
|
47
|
+
python = Mortar::Local::Python.new
|
48
|
+
mock(python).should_do_python_install?.returns(true)
|
49
|
+
mock(python).install_osx.returns(true)
|
50
|
+
capture_stdout do
|
51
|
+
python.install_or_update_osx
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does install if an update is available" do
|
56
|
+
python = Mortar::Local::Python.new
|
57
|
+
mock(python).should_do_python_install?.returns(false)
|
58
|
+
mock(python).should_do_update?.returns(true)
|
59
|
+
mock(python).install_osx.returns(true)
|
60
|
+
capture_stdout do
|
61
|
+
python.install_or_update_osx
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mortar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 0.7.
|
9
|
+
- 2
|
10
|
+
version: 0.7.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mortar Data
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-03-
|
18
|
+
date: 2013-03-26 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: mortar-api-ruby
|
@@ -187,6 +187,7 @@ files:
|
|
187
187
|
- lib/mortar/command/validate.rb
|
188
188
|
- lib/mortar/command/version.rb
|
189
189
|
- lib/mortar/errors.rb
|
190
|
+
- lib/mortar/generators/controlscript_generator.rb
|
190
191
|
- lib/mortar/generators/generator_base.rb
|
191
192
|
- lib/mortar/generators/macro_generator.rb
|
192
193
|
- lib/mortar/generators/pigscript_generator.rb
|
@@ -197,13 +198,16 @@ files:
|
|
197
198
|
- lib/mortar/local/controller.rb
|
198
199
|
- lib/mortar/local/installutil.rb
|
199
200
|
- lib/mortar/local/java.rb
|
201
|
+
- lib/mortar/local/jython.rb
|
200
202
|
- lib/mortar/local/pig.rb
|
201
203
|
- lib/mortar/local/python.rb
|
202
204
|
- lib/mortar/project.rb
|
205
|
+
- lib/mortar/templates/controlscript/controlscript.py
|
203
206
|
- lib/mortar/templates/macro/macro.pig
|
204
207
|
- lib/mortar/templates/pigscript/pigscript.pig
|
205
208
|
- lib/mortar/templates/pigscript/python_udf.py
|
206
209
|
- lib/mortar/templates/project/README.md
|
210
|
+
- lib/mortar/templates/project/controlscripts/gitkeep
|
207
211
|
- lib/mortar/templates/project/fixtures/gitkeep
|
208
212
|
- lib/mortar/templates/project/gitignore
|
209
213
|
- lib/mortar/templates/project/macros/gitkeep
|
@@ -235,7 +239,9 @@ files:
|
|
235
239
|
- spec/mortar/local/controller_spec.rb
|
236
240
|
- spec/mortar/local/installutil_spec.rb
|
237
241
|
- spec/mortar/local/java_spec.rb
|
242
|
+
- spec/mortar/local/jython_spec.rb
|
238
243
|
- spec/mortar/local/pig_spec.rb
|
244
|
+
- spec/mortar/local/python_spec.rb
|
239
245
|
- spec/mortar/project_spec.rb
|
240
246
|
- spec/mortar/updater_spec.rb
|
241
247
|
- spec/spec.opts
|