mortar 0.7.1 → 0.7.2
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/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
|