mortar 0.9.1 → 0.9.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.
@@ -66,12 +66,48 @@ class Mortar::Command::Local < Mortar::Command::Base
66
66
  error("No such directory #{project_root}")
67
67
  end
68
68
  Dir.chdir(project_root)
69
-
70
69
  script = validate_script!(script_name)
71
70
  ctrl = Mortar::Local::Controller.new
72
71
  ctrl.run(script, pig_parameters)
73
72
  end
74
73
 
74
+ # local:characterize
75
+ #
76
+ # Characterize will inspect your input data, inferring a schema and
77
+ # generating keys, if needed. It will output CSV containing various
78
+ # statistics about your data (most common values, percent null, etc.)
79
+ #
80
+ # -f, --param-file PARAMFILE # Load pig parameter values from a file
81
+ #
82
+ # Load some data and emit statistics.
83
+ # PARAMFILE:
84
+ # LOADER=<full class path of loader function>
85
+ # INPUT_SRC=<Location of the input data>
86
+ # OUTPUT_PATH=<Relative path from project root for output>
87
+ # INFER_TYPES=<when true, recursively infers types for input data>
88
+ #
89
+ # Example paramfile:
90
+ # LOADER=org.apache.pig.piggybank.storage.JsonLoader()
91
+ # INPUT_SRC=s3n://twitter-gardenhose-mortar/example
92
+ # OUTPUT_PATH=twitter_char
93
+ # INFER_TYPES=true
94
+ #
95
+ def characterize
96
+ validate_arguments!
97
+
98
+ #cd into the project root
99
+ project_root = options[:project_root] ||= Dir.getwd
100
+ unless File.directory?(project_root)
101
+ error("No such directory #{project_root}")
102
+ end
103
+ Dir.chdir(project_root)
104
+
105
+ controlscript_name = "controlscripts/lib/characterize_control.py"
106
+ script = validate_script!(controlscript_name)
107
+ ctrl = Mortar::Local::Controller.new
108
+ ctrl.run(script, pig_parameters)
109
+ end
110
+
75
111
  # local:illustrate PIGSCRIPT [ALIAS]
76
112
  #
77
113
  # Locally illustrate the effects and output of a pigscript.
@@ -46,7 +46,7 @@ module Mortar::Command
46
46
  plugin.install
47
47
  Mortar::Plugin.load_plugin(plugin.name)
48
48
  rescue StandardError => e
49
- error e
49
+ error e.message
50
50
  end
51
51
  end
52
52
  end
@@ -68,7 +68,7 @@ module Mortar::Command
68
68
  begin
69
69
  plugin.uninstall
70
70
  rescue Mortar::Plugin::ErrorPluginNotFound => e
71
- error e
71
+ error e.message
72
72
  end
73
73
  end
74
74
  end
@@ -101,7 +101,7 @@ module Mortar::Command
101
101
  status "skipped symlink"
102
102
  rescue StandardError => e
103
103
  status "error"
104
- display e
104
+ display e.message
105
105
  end
106
106
  end
107
107
  end
@@ -47,19 +47,31 @@ class Mortar::Command::Projects < Mortar::Command::Base
47
47
  error("Usage: mortar projects:delete PROJECTNAME\nMust specify PROJECTNAME.")
48
48
  end
49
49
  validate_arguments!
50
-
51
- # delete embedded project mirror if one exists
52
- mirror_dir = "#{git.mortar_mirrors_dir()}/#{name}"
53
- if File.directory? mirror_dir
54
- FileUtils.rm_r mirror_dir
50
+ projects = api.get_projects().body['projects']
51
+ project_id = nil
52
+ if projects.any?
53
+ projects.each do |project|
54
+ if project['name'] == name
55
+ project_id = project['project_id']
56
+ end
57
+ end
55
58
  end
56
59
 
57
- # delete Mortar remote
58
- project_id = nil
59
- action("Sending request to delete project: #{name}") do
60
- api.delete_project(name).body["project_id"]
60
+ if project_id.nil?
61
+ display "\nNo project with name: #{name}"
62
+ else
63
+ # delete embedded project mirror if one exists
64
+ mirror_dir = "#{git.mortar_mirrors_dir()}/#{name}"
65
+ if File.directory? mirror_dir
66
+ FileUtils.rm_r mirror_dir
67
+ end
68
+
69
+ # delete Mortar remote
70
+ action("Sending request to delete project: #{name}") do
71
+ api.delete_project(project_id).body['project_id']
72
+ end
73
+ display "\nYour project has been deleted."
61
74
  end
62
- display "\nYour project has been deleted."
63
75
 
64
76
  end
65
77
 
@@ -38,6 +38,7 @@ 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"
41
42
  end
42
43
 
43
44
  mkdir "controlscripts"
@@ -46,6 +47,7 @@ module Mortar
46
47
  mkdir "lib"
47
48
  inside "lib" do
48
49
  copy_file "__init__.py", "__init__.py"
50
+ copy_file "characterize_control.py", "characterize_control.py"
49
51
  end
50
52
  end
51
53
 
@@ -53,6 +55,7 @@ module Mortar
53
55
 
54
56
  inside "macros" do
55
57
  copy_file "gitkeep", ".gitkeep"
58
+ copy_file "characterize_macro.pig", "characterize_macro.pig"
56
59
  end
57
60
 
58
61
  mkdir "fixtures"
@@ -72,6 +75,7 @@ module Mortar
72
75
  mkdir "jython"
73
76
  inside "jython" do
74
77
  copy_file "gitkeep", ".gitkeep"
78
+ copy_file "top_5_tuple.py", "top_5_tuple.py"
75
79
  end
76
80
 
77
81
  mkdir "java"
@@ -142,4 +146,4 @@ module Mortar
142
146
  end
143
147
  end
144
148
  end
145
- end
149
+ end
data/lib/mortar/plugin.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  # based on the Rails Plugin
2
+
3
+ require "stringio"
4
+
2
5
  module Mortar
3
6
  class Plugin
4
7
  include Mortar::Helpers
@@ -41,7 +44,40 @@ module Mortar
41
44
  end
42
45
 
43
46
  def self.install_bundle
44
- system("bundle install --standalone --without development >> ./../plugin_install.log")
47
+ # TODO: Deal with the bundler as a runtime dependency issue
48
+ # before moving these require statements to the top.
49
+ begin
50
+ require 'bundler/cli'
51
+ require 'bundler/friendly_errors'
52
+ rescue LoadError => e
53
+ raise <<-ERROR
54
+ Unable to install this plugin. Make sure you have bundler installed:
55
+
56
+ $ gem install bundler
57
+
58
+ ERROR
59
+ end
60
+
61
+ out = StringIO.new
62
+ $stdout = out
63
+ begin
64
+ bundle_def = Bundler.definition({})
65
+ Bundler.ui = Bundler::UI::Shell.new({})
66
+ Bundler.ui.level = "silent"
67
+ Bundler.settings[:path] = "bundle"
68
+ Bundler::Installer.install(Bundler.root, bundle_def, {
69
+ :standalone => [],
70
+ })
71
+ result = true
72
+ rescue StandardError => e
73
+ out.write e.message
74
+ result = false
75
+ end
76
+ open("#{Plugin.directory}/plugin_install.log", 'a') do |f|
77
+ f.puts out.string
78
+ end
79
+ $stdout = STDOUT
80
+ return result
45
81
  end
46
82
 
47
83
  def self.load!
@@ -111,8 +147,7 @@ ERROR
111
147
  Mortar::Plugin.without_bundler_env do
112
148
  ENV["BUNDLE_GEMFILE"] = File.expand_path("Gemfile", path)
113
149
  if File.exists? ENV["BUNDLE_GEMFILE"]
114
- Mortar::Plugin.install_bundle
115
- unless $?.success?
150
+ unless Mortar::Plugin.install_bundle
116
151
  FileUtils.rm_rf path
117
152
  raise Mortar::Plugin::ErrorInstallingDependencies, <<-ERROR
118
153
  Unable to install dependencies for #{name}.
@@ -0,0 +1,23 @@
1
+ from org.apache.pig.scripting import Pig
2
+ import os
3
+
4
+ if __name__ == "__main__":
5
+ params = Pig.getParameters()
6
+ loader = params["LOADER"]
7
+ input_source = params["INPUT_SRC"]
8
+ output_path = params["OUTPUT_PATH"]
9
+ infer_types = params["INFER_TYPES"]
10
+
11
+ Pig.compileFromFile("../pigscripts/characterize.pig").bind({
12
+ "LOADER" : loader,
13
+ "INPUT_SRC" : input_source,
14
+ "OUTPUT_PATH" : output_path,
15
+ "INFER_TYPES" : infer_types
16
+ }).runSingle()
17
+
18
+ for root, _, files in os.walk("../%s" % output_path):
19
+ for f in files:
20
+ if f[0] != '.':
21
+ fullpath = os.path.join(root, f)
22
+ copypath = os.path.join(root, f + '.csv')
23
+ os.system ("cp %s %s" % (fullpath, copypath))
@@ -0,0 +1,129 @@
1
+ /*
2
+ Copyright 2013 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
+ /*
18
+ * A pig macro to characterize some data.
19
+ * Take an alias to some pre-loaded data and return a relation
20
+ * containing statistics about that data in a bag.
21
+ * Each field is listed up to five times (with their five most common
22
+ * example values) as a tuple of the following form:
23
+ * (
24
+ * Field Name (embedded fields have their parent's field name prepended),
25
+ * Number of distinct values associated with the field,
26
+ * Total number of values,
27
+ * Deciles,
28
+ * Number of null appearences,
29
+ * Percentage null,
30
+ * Minimum value,
31
+ * Maximum value,
32
+ * Range of values (Max - Min),
33
+ * Type,
34
+ * Values (tuple of top 5 values, bags/chararrays/tuples are converted to length)
35
+ * Value Counts (tuple of corresponding number of value occurrences)
36
+ * Original Values (tuple of corresponding original values)
37
+ * )
38
+ *
39
+ * data: {anything}
40
+ * inferTypes: when true, characterize will infer numeric types for values
41
+ * without an explicit schema (e.g. values in a complex map object)
42
+ *
43
+ * Example:
44
+ * data = LOAD '/path/to/data' USING JsonLoader();
45
+ * characterized = Characterize(data, 'true')
46
+ */
47
+
48
+ REGISTER 's3://mhc-software-mirror/datafu/datafu-0.0.10.jar';
49
+ REGISTER 's3://mhc-software-mirror/bacon-bits/udfs/java/bacon-bits-0.1.0.jar';
50
+ REGISTER '../udfs/jython/top_5_tuple.py' USING jython AS top5;
51
+
52
+ DEFINE Deciles datafu.pig.stats.StreamingQuantile('11');
53
+
54
+ DEFINE Characterize(data, inferTypes)
55
+ RETURNS out {
56
+
57
+ DEFINE Characterize__ExtractFields com.mortardata.pig.ExtractFields('$inferTypes');
58
+
59
+ raw_fields = FOREACH $data
60
+ GENERATE FLATTEN(Characterize__ExtractFields(*)) as
61
+ (keyname:chararray, type:chararray, val:double, orig:chararray);
62
+
63
+ --Group the rows by field name and find the number of unique values for each field in the collection
64
+ key_groups = GROUP raw_fields BY (keyname);
65
+ unique_vals = FOREACH key_groups {
66
+ v = raw_fields.val;
67
+ null_fields = filter raw_fields by val is null;
68
+ unique_v = distinct v;
69
+ GENERATE flatten(group) as keyname:chararray,
70
+ COUNT(unique_v) as num_distinct_vals_count:long, COUNT(v) as num_vals:long, COUNT(null_fields) as num_null:long,
71
+ (double) COUNT(null_fields) / (double) COUNT(raw_fields) as percentage_null:double,
72
+ MIN(unique_v.val) as min_val:double, MAX(unique_v.val) as max_val:double;
73
+ }
74
+
75
+ -- calculate decile tuples for each key (filtering out null values to make datafu happy)
76
+ no_nulls = filter raw_fields by val is not null;
77
+ no_null_groups = GROUP no_nulls BY keyname;
78
+ key_deciles = FOREACH no_null_groups {
79
+ GENERATE flatten(group) as keyname:chararray, Deciles(no_nulls.val) as deciles:tuple();
80
+ }
81
+
82
+ -- Find the number of times each value occurs for each field
83
+ key_val_groups = GROUP raw_fields BY (keyname, type, val, orig);
84
+ key_val_groups_with_counts = FOREACH key_val_groups
85
+ GENERATE flatten(group),
86
+ COUNT($1) as val_count:long;
87
+
88
+ -- Find the top 5 most common values for each field
89
+ key_vals = GROUP key_val_groups_with_counts BY (keyname);
90
+ top_5_vals = FOREACH key_vals {
91
+ ordered_vals = ORDER key_val_groups_with_counts BY val_count DESC;
92
+ limited_vals = LIMIT ordered_vals 5;
93
+ GENERATE flatten(limited_vals);
94
+ }
95
+
96
+ cogroup_result = COGROUP unique_vals BY keyname,
97
+ top_5_vals BY keyname;
98
+
99
+ flat_vals = FOREACH cogroup_result {
100
+ top_vals = top5.key_bag_to_tuple(top_5_vals);
101
+ GENERATE flatten(unique_vals) as
102
+ (keyname:chararray, num_distinct_vals_count:long, num_vals:long,
103
+ num_null:long, percent_null:double, min_val:double, max_val:double), top_vals.vals as vals,
104
+ top_vals.type as type:chararray, top_vals.orig as orig:tuple(), top_vals.val_counts as val_counts:tuple();
105
+ }
106
+
107
+ join_result = JOIN flat_vals BY keyname,
108
+ key_deciles BY keyname;
109
+
110
+ -- Clean up columns (remove duplicate keyname field)
111
+ result = FOREACH join_result
112
+ GENERATE flat_vals::keyname as Key,
113
+ num_distinct_vals_count as NDistinct,
114
+ num_vals as NVals,
115
+ deciles as Deciles,
116
+ num_null as NNull,
117
+ percent_null as PctNull,
118
+ min_val as Min,
119
+ max_val as Max,
120
+ max_val - min_val as Range,
121
+ type as Type,
122
+ vals as Vals,
123
+ val_counts as ValCounts,
124
+ orig as OrigVals;
125
+
126
+ -- -- Sort by field name and number of values
127
+ $out = ORDER result BY Key;
128
+
129
+ };
@@ -0,0 +1,6 @@
1
+ IMPORT '../macros/characterize_macro.pig';
2
+ data = LOAD '$INPUT_SRC'
3
+ USING $LOADER;
4
+ characterize_data = Characterize(data, $INFER_TYPES);
5
+ STORE characterize_data INTO '../$OUTPUT_PATH'
6
+ USING org.apache.pig.piggybank.storage.CSVExcelStorage(',', 'YES_MULTILINE', 'UNIX', 'WRITE_OUTPUT_HEADER');
@@ -0,0 +1,27 @@
1
+ @outputSchema("five:tuple(vals:tuple(v1:double, v2:double, v3:double, v4:double, v5:double), type:chararray, orig:tuple(v1:chararray, v2:chararray, v3:chararray, v4:chararray, v5:chararray), val_counts:tuple(v1:long, v2:long, v3:long, v4:long, v5:long))")
2
+ def key_bag_to_tuple(input_bag):
3
+ output = []
4
+ #sort by val_count
5
+ input_bag = sorted(input_bag, key=lambda tup: tup[4], reverse=True)
6
+ vals = [None, None, None, None, None]
7
+ val_counts = [None, None, None, None, None]
8
+ orig_vals = [None, None, None, None, None]
9
+ for idx, t in enumerate(input_bag):
10
+ vals[idx] = t[2]
11
+ orig_vals[idx] = t[3]
12
+ val_counts[idx] = t[4]
13
+ val_tup = tuple(vals)
14
+ val_count_tup = tuple(val_counts)
15
+ orig_val_tup = tuple(orig_vals)
16
+ output.append(val_tup)
17
+ if all(i[1] == "NULL" for i in input_bag):
18
+ output.append("NULL")
19
+ else:
20
+ for t in input_bag:
21
+ if t[1] != "NULL":
22
+ output.append(t[1])
23
+ break
24
+ output.append(orig_val_tup)
25
+ output.append(val_count_tup)
26
+ return tuple(output)
27
+
@@ -16,5 +16,5 @@
16
16
 
17
17
  module Mortar
18
18
  # see http://semver.org/
19
- VERSION = "0.9.1"
19
+ VERSION = "0.9.2"
20
20
  end
@@ -36,9 +36,11 @@ module Mortar::Command
36
36
 
37
37
  project1 = {'name' => "Project1",
38
38
  'status' => Mortar::API::Projects::STATUS_ACTIVE,
39
+ 'project_id' => 'abcd1234',
39
40
  'git_url' => "git@github.com:mortarcode-dev/Project1"}
40
41
  project2 = {'name' => "Project2",
41
42
  'status' => Mortar::API::Projects::STATUS_ACTIVE,
43
+ 'project_id' => 'defg5678',
42
44
  'git_url' => "git@github.com:mortarcode-dev/Project2"}
43
45
 
44
46
  context("index") do
@@ -75,12 +77,13 @@ STDERR
75
77
  end
76
78
 
77
79
  it "deletes project" do
78
- project_name = "COMMANDO"
80
+ project_id = "abcd1234"
79
81
 
80
- mock(Mortar::Auth.api).delete_project(project_name).returns(Excon::Response.new(:body => {}, :status => 200 ))
81
- stderr, stdout = execute("projects:delete COMMANDO")
82
+ mock(Mortar::Auth.api).get_projects().returns(Excon::Response.new(:body => {"projects" => [project1, project2]}))
83
+ mock(Mortar::Auth.api).delete_project(project_id).returns(Excon::Response.new(:body => {}, :status => 200 ))
84
+ stderr, stdout = execute("projects:delete Project1")
82
85
  stdout.should == <<-STDOUT
83
- Sending request to delete project: COMMANDO... done
86
+ Sending request to delete project: Project1... done
84
87
 
85
88
  Your project has been deleted.
86
89
  STDOUT
@@ -127,11 +130,14 @@ STDOUT
127
130
  \e[1;32m create\e[0m .gitignore
128
131
  \e[1;32m create\e[0m pigscripts
129
132
  \e[1;32m create\e[0m pigscripts/some_new_project.pig
133
+ \e[1;32m create\e[0m pigscripts/characterize.pig
130
134
  \e[1;32m create\e[0m controlscripts
131
135
  \e[1;32m create\e[0m controlscripts/lib
132
136
  \e[1;32m create\e[0m controlscripts/lib/__init__.py
137
+ \e[1;32m create\e[0m controlscripts/lib/characterize_control.py
133
138
  \e[1;32m create\e[0m macros
134
139
  \e[1;32m create\e[0m macros/.gitkeep
140
+ \e[1;32m create\e[0m macros/characterize_macro.pig
135
141
  \e[1;32m create\e[0m fixtures
136
142
  \e[1;32m create\e[0m fixtures/.gitkeep
137
143
  \e[1;32m create\e[0m udfs
@@ -139,6 +145,7 @@ STDOUT
139
145
  \e[1;32m create\e[0m udfs/python/some_new_project.py
140
146
  \e[1;32m create\e[0m udfs/jython
141
147
  \e[1;32m create\e[0m udfs/jython/.gitkeep
148
+ \e[1;32m create\e[0m udfs/jython/top_5_tuple.py
142
149
  \e[1;32m create\e[0m udfs/java
143
150
  \e[1;32m create\e[0m udfs/java/.gitkeep
144
151
  \e[1;32m create\e[0m vendor
@@ -426,4 +433,4 @@ STDERR
426
433
 
427
434
  end
428
435
  end
429
- end
436
+ end
@@ -100,15 +100,30 @@ module Mortar
100
100
 
101
101
  describe "installing plugins with dependencies" do
102
102
  it "should install plugin dependencies" do
103
+ ## Setup Fake Gem
104
+ mortar_fake_gem_folder = create_fake_gem("/tmp")
103
105
  plugin_folder = "/tmp/mortar_plugin"
104
106
  FileUtils.mkdir_p(plugin_folder)
105
- File.open(plugin_folder + '/Gemfile', 'w') { |f| f.write "# dummy content" }
107
+ File.open(plugin_folder + '/Gemfile', 'w') { |f|
108
+ f.write "gem 'mortar_fake_gem', :path => '#{mortar_fake_gem_folder}'"
109
+ }
110
+ File.open(plugin_folder + '/init.rb', 'w') { |f|
111
+ f.write <<-EOS
112
+ require File.join(File.dirname(__FILE__), "bundle/bundler/setup")
113
+ require "mortar_fake_gem"
114
+
115
+ PluginTest = MortarFakeGem::WhoIs.awesome?
116
+ EOS
117
+ }
106
118
  `cd #{plugin_folder} && git init && echo 'test' > README && git add . && git commit -m 'my plugin'`
107
119
  Plugin.new(plugin_folder).install
108
120
  File.directory?("#{@sandbox}/mortar_plugin").should be_true
109
121
  File.directory?("#{@sandbox}/mortar_plugin/bundle").should be_true
110
122
  File.exist?("#{@sandbox}/mortar_plugin/Gemfile").should be_true
111
123
  File.read("#{@sandbox}/mortar_plugin/README").should == "test\n"
124
+
125
+ Plugin.load!
126
+ PluginTest.should be_true
112
127
  end
113
128
 
114
129
  it "should fail to install plugin with bad dependencies" do
data/spec/spec_helper.rb CHANGED
@@ -249,6 +249,44 @@ def git_create_conflict(git, project)
249
249
  filename
250
250
  end
251
251
 
252
+ def create_fake_gem(path)
253
+ mortar_fake_gem = <<-EOS
254
+ Gem::Specification.new do |s|
255
+ s.name = "mortar_fake_gem"
256
+ s.version = "0.0.1"
257
+ s.summary = "mortar_fake_gem is the best"
258
+ s.files = [
259
+ "lib/mortar_fake_gem.rb"
260
+ ]
261
+ s.require_paths = ["lib"]
262
+ end
263
+ EOS
264
+
265
+ mortar_fake_gem_rb = <<-EOS
266
+ module MortarFakeGem
267
+ class WhoIs
268
+ def self.awesome?
269
+ return true
270
+ end
271
+ end
272
+ end
273
+ EOS
274
+
275
+ files = {
276
+ "mortar_fake_gem.gemspec" => mortar_fake_gem,
277
+ "lib/mortar_fake_gem.rb" => mortar_fake_gem_rb,
278
+ }
279
+
280
+ FileUtils.mkdir_p(File.join(path, "mortar_fake_gem/lib"))
281
+ files.each { |file_name, contents|
282
+ File.open(File.join(path, "/mortar_fake_gem/#{file_name}"), 'w') do |f|
283
+ f.puts contents
284
+ end
285
+ }
286
+
287
+ return File.join(path, "mortar_fake_gem")
288
+
289
+ end
252
290
 
253
291
  def git_add_file(git, project)
254
292
  # add a new file
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: 57
4
+ hash: 63
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 1
10
- version: 0.9.1
9
+ - 2
10
+ version: 0.9.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-07-08 00:00:00 Z
18
+ date: 2013-07-16 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: mortar-api-ruby
@@ -210,12 +210,16 @@ files:
210
210
  - lib/mortar/templates/pigscript/python_udf.py
211
211
  - lib/mortar/templates/project/README.md
212
212
  - lib/mortar/templates/project/controlscripts/lib/__init__.py
213
+ - lib/mortar/templates/project/controlscripts/lib/characterize_control.py
213
214
  - lib/mortar/templates/project/fixtures/gitkeep
214
215
  - lib/mortar/templates/project/gitignore
216
+ - lib/mortar/templates/project/macros/characterize_macro.pig
215
217
  - lib/mortar/templates/project/macros/gitkeep
218
+ - lib/mortar/templates/project/pigscripts/characterize.pig
216
219
  - lib/mortar/templates/project/pigscripts/pigscript.pig
217
220
  - lib/mortar/templates/project/udfs/java/gitkeep
218
221
  - lib/mortar/templates/project/udfs/jython/gitkeep
222
+ - lib/mortar/templates/project/udfs/jython/top_5_tuple.py
219
223
  - lib/mortar/templates/project/udfs/python/python_udf.py
220
224
  - lib/mortar/templates/project/vendor/controlscripts/lib/__init__.py
221
225
  - lib/mortar/templates/project/vendor/macros/gitkeep
@@ -289,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
293
  requirements: []
290
294
 
291
295
  rubyforge_project:
292
- rubygems_version: 1.8.24
296
+ rubygems_version: 1.8.25
293
297
  signing_key:
294
298
  specification_version: 3
295
299
  summary: Client library and CLI to interact with the Mortar service.