grassgis 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eca4b61ff65ed5f6bb173f1502e27b2f17ccbdfa
4
- data.tar.gz: 65794615e3eb17457e67b055c2f056e43d6b32da
3
+ metadata.gz: 788c22870c881d792c8412e3f2ebbe44015c6e28
4
+ data.tar.gz: 2f4204831ac3bd07ffa8ee5f774777ba5faabae0
5
5
  SHA512:
6
- metadata.gz: af06a15d577d6ebcc835f75cf03a1b42fbdb71229a7b820213ba6c1a62257572981a88fd635197b6a917ebbe9766173aca1fb7f108673eec7c2ae65811a6e986
7
- data.tar.gz: 31def098f90ef421d0e99f47b3dcb62be72bc62d085021632c496c360037de2b0d8839dd3f7d7ea9f3e3f64376de0a6d09fa724afd780b023065f4caa4fc8176
6
+ metadata.gz: c17ad3bc200c2ac699e95d61ca32ab734b03f6bff74e1219ea3c18bd9dbab3fac9d07be77e44a0895efa3d33d8ee2f5acf2eff543c95de326f7b68e7c957adc1
7
+ data.tar.gz: 8e144e6a0de01b5ba6e875284094114164847c76e545527f3e1756572cbe2a4ce1478d26b81e0c7402f8347efead8ef38a0b3030cfd80f575204cb562df33a01
data/README.md CHANGED
@@ -33,12 +33,21 @@ configuration = {
33
33
 
34
34
  GrassGis.session configuration do
35
35
  r.resamp.stats '-n', input: "map1@mapset1", output: "map2"
36
- puts g.list('vect').output
36
+ g.list 'vect'
37
+ puts output # output of last command
37
38
  end
38
39
  ```
39
40
 
40
41
  ## Roadmap
41
42
 
43
+ * Write the executed command history to the location's +.bash_history+
44
+ or to another file specified in the session configuration.
45
+ * Log GRASS command output / error output
46
+ * Method to clean GRASS temporaries ($GISBASE/etc/clean_temp), or do
47
+ it automatically when disposing the session.
48
+
49
+ ### GRASS cooking DSL
50
+
42
51
  Create a DSL to define GRASS processing recipes.
43
52
 
44
53
  It should handle errors gracefully during recipe execution,
@@ -10,12 +10,21 @@ module GrassGis
10
10
  # apply configuration defaults
11
11
  config[:gisdbase] ||= File.join(ENV['HOME'], 'grassdata')
12
12
  config[:mapset] ||= ENV['USER']
13
- config[:version] ||= File.read(File.join(config[:gisbase], 'etc', 'VERSIONNUMBER')).split.first
13
+ unless config[:version]
14
+ version_file = File.join(config[:gisbase], 'etc', 'VERSIONNUMBER')
15
+ if File.exists?(version_file)
16
+ config[:version] = File.read(version_file).split.first
17
+ end
18
+ end
14
19
  config[:message_format] ||= 'plain'
15
20
  config[:true_color] = true unless config.has_key?(:true_color)
16
21
  config[:transparent] = true unless config.has_key?(:transparent)
17
22
  config[:png_auto_write] = true unless config.has_key?(:png_auto_write)
18
23
  config[:gnuplot] ||= 'gnuplot -persist'
24
+ config[:gui] ||= 'wxpython'
25
+
26
+ config[:errors] ||= :raise
27
+
19
28
  @config = config
20
29
 
21
30
  locals = config[:locals] || {}
@@ -24,50 +33,95 @@ module GrassGis
24
33
  end
25
34
  end
26
35
 
27
- def allocate
28
- @gisrc = Tempfile.new('gisrc')
29
- @gisrc.puts "LOCATION_NAME: #{@config[:location]}"
30
- @gisrc.puts "GISDBASE: #{@config[:gisdbase]}"
31
- @gisrc.puts "MAPSET: #{@config[:mapset]}"
32
- @gisrc.close
33
- ENV['GISRC'] = @gisrc.path
34
- ENV['GISBASE'] = @config[:gisbase]
35
- ENV['GRASS_VERSION'] = @config[:version]
36
- ENV['GRASS_MESSAGE_FORMAT'] = @config[:message_format].to_s
37
- ENV['GRASS_TRUECOLOR'] = bool_var(@config[:true_color])
38
- ENV['GRASS_TRANSPARENT'] = bool_var(@config[:transparent])
39
- ENV['GRASS_PNG_AUTO_WRITE'] = bool_var(@config[:png_auto_write])
40
- ENV['GRASS_GNUPLOT'] = @config[:gnuplot]
41
- @path = ENV['PATH']
42
- paths = []
43
- paths << File.join(@config[:gisbase], 'bin')
44
- paths << File.join(@config[:gisbase], 'scripts')
45
- paths << @path
46
- ENV['PATH'] = paths.join(File::PATH_SEPARATOR)
47
- @ld_path = ENV['LD_LIBRARY_PATH']
48
- ld_path = File.join(@config[:gisbase], 'lib')
49
- if @ld_path
50
- ENV['LD_LIBRARY_PATH'] = [ld_path, @ld_path].join(File::PATH_SEPARATOR)
51
- else
52
- ENV['LD_LIBRARY_PATH'] = ld_path
53
- end
54
- ENV['GRASS_LD_LIBRARY_PATH'] = ENV['LD_LIBRARY_PATH']
55
- @man_path = ENV['MANPATH']
56
- man_path = File.join(@config[:gisbase], 'man')
57
- if @man_path
58
- ENV['MANPATH'] = [man_path, @man_path].join(File::PATH_SEPARATOR)
59
- else
60
- ENV['MANPATH'] = man_path
61
- end
62
- end
36
+ # Commands executed in the session are kept in the +history+ array
37
+ #
38
+ # GrassGis.session config do
39
+ # g.region res: 10
40
+ # g.region res: 20
41
+ # g.region res: 30
42
+ # puts history[-3] # => "g.region res=10"
43
+ # puts history[-2] # => "g.region res=20"
44
+ # puts history[-1] # => "g.region res=30"
45
+ # puts history[-2].output
46
+ # end
47
+ #
48
+ attr_reader :history
49
+
50
+ # Last command executed in the session (history[-1])
51
+ def last
52
+ history.last
53
+ end
54
+
55
+ # Array of commands that resulted in error in the session
56
+ def errors
57
+ history.select { |cmd| GrassGis.error?(cmd) }
58
+ end
59
+
60
+ # Did last command exit with error status
61
+ def error?
62
+ GrassGis.error? last
63
+ end
64
+
65
+ def error_info
66
+ GrassGis.error_info last
67
+ end
68
+
69
+ # Output of the last command executed
70
+ def output
71
+ last.output
72
+ end
73
+
74
+ # Standar error output of last command executed
75
+ def error_output
76
+ last.error_output
77
+ end
78
+
79
+ def allocate
80
+ @gisrc = Tempfile.new('gisrc')
81
+ @gisrc.puts "LOCATION_NAME: #{@config[:location]}"
82
+ @gisrc.puts "GISDBASE: #{@config[:gisdbase]}"
83
+ @gisrc.puts "MAPSET: #{@config[:mapset]}"
84
+ @gisrc.puts "GUI: #{@config[:gui]}"
85
+ @gisrc.close
86
+
87
+ @original_env = {}
88
+
89
+ replace_var 'GISRC', @gisrc.path
90
+ replace_var 'GISBASE', @config[:gisbase]
91
+ replace_var 'GRASS_VERSION', @config[:version]
92
+ replace_var 'GRASS_MESSAGE_FORMAT', @config[:message_format].to_s
93
+ replace_var 'GRASS_TRUECOLOR', bool_var(@config[:true_color])
94
+ replace_var 'GRASS_TRANSPARENT', bool_var(@config[:transparent])
95
+ replace_var 'GRASS_PNG_AUTO_WRITE', bool_var(@config[:png_auto_write])
96
+ replace_var 'GRASS_GNUPLOT', @config[:gnuplot]
97
+
98
+ paths = ['bin', 'scripts']
99
+ if OS.windows?
100
+ # paths << 'lib'
101
+ paths.unshift 'lib'
102
+ else
103
+ insert_path 'LD_LIBRARY_PATH', File.join(@config[:gisbase], 'lib')
104
+ ENV['GRASS_LD_LIBRARY_PATH'] = ENV['LD_LIBRARY_PATH']
105
+ end
106
+ paths = paths.map { |path| File.join(@config[:gisbase], path) }
107
+ if OS.windows?
108
+ osgeo4w_dir = ENV['OSGEO4W_ROOT'] || "C:\\OSGeo4W"
109
+ if File.directory?(osgeo4w_dir)
110
+ paths << File.join(osgeo4w_dir, 'bin')
111
+ end
112
+ end
113
+ insert_path 'PATH', *paths
114
+ insert_path 'MANPATH', File.join(@config[:gisbase], 'man')
115
+ @history = @config[:history] = []
116
+ end
63
117
 
64
118
  def dispose
65
119
  @gisrc.unlink if @gisrc
66
120
  @gisrc = nil
67
- ENV['PATH'] = @path if @path
68
- @path = nil
69
- ENV['LD_LIBRARY_PATH'] = @ld_path
70
- ENV['MANPATH'] = @man_path
121
+ @original_env.each do |var, value|
122
+ ENV[var] = value
123
+ end
124
+ @original_env = {}
71
125
  end
72
126
 
73
127
  # setup access to the root modules in the context
@@ -81,12 +135,50 @@ module GrassGis
81
135
  end
82
136
  end
83
137
 
84
- private
138
+ # Evaluate a block of code in the context of a GRASS session
139
+ #
140
+ # Useful to pass a GRASS context around and use it to execute
141
+ # GRASS commands, e.g.:
142
+ #
143
+ # def helper(grass, ...)
144
+ # # can invoke GRASS commands using grass:
145
+ # grass.g.region res: 10
146
+ # # Or use a session block to abbreviate typing:
147
+ # grass.session do
148
+ # g.region res: 10
149
+ # ...
150
+ # end
151
+ # end
152
+ #
153
+ # GrassGis.session ... do
154
+ # helper seld, ...
155
+ # ...
156
+ # end
157
+ #
158
+ def session(&blk)
159
+ instance_eval(&blk)
160
+ end
161
+
162
+ private
85
163
 
86
164
  def bool_var(value)
87
165
  value ? 'TRUE' : 'FALSE'
88
166
  end
89
167
 
168
+ def insert_path(var, *paths)
169
+ @original_env[var] = ENV[var]
170
+ if File::ALT_SEPARATOR
171
+ paths = paths.map { |path| path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) }
172
+ end
173
+ paths << ENV[var] if ENV[var]
174
+ ENV[var] = paths.join(File::PATH_SEPARATOR)
175
+ end
176
+
177
+ def replace_var(var, value)
178
+ @original_env[var] = ENV[var]
179
+ ENV[var] = value
180
+ end
181
+
90
182
  end
91
183
 
92
184
  # Evaluate a block in a GRASS session environment
@@ -127,12 +219,54 @@ module GrassGis
127
219
  # r.resamp.stats '-n', input: this.input, output: context.output
128
220
  # end
129
221
  #
222
+ # Other pararameters:
223
+ #
224
+ # :errors to define the behaviour when a GRASS command fails:
225
+ # * :raise is the default and raises on errors
226
+ # * :console shows standar error output of commands
227
+ # * :quiet error output is retained but not shown
228
+ #
229
+ # If :error is anything other than :raise, it is up to the user
230
+ # to check each command for errors. With the :console option
231
+ # the standar error output of commands is sent to the console
232
+ # and is not accessible through the command's error_output method.
233
+ #
130
234
  def self.session(config, &blk)
131
235
  context = Context.new(config)
132
236
  context.allocate
133
- context.instance_eval(&blk)
237
+ context.session &blk
134
238
  ensure
135
- context.dispose
239
+ context.dispose if context
240
+ end
241
+
242
+ class Error < StandardError
243
+ end
244
+
245
+ def self.error?(command)
246
+ command && (!!command.error || (command.status_value && command.status_value != 0))
247
+ end
248
+
249
+ def error_info(command)
250
+ if command
251
+ if command.error
252
+ command.error.to_s
253
+ elsif (command.status_value && command.status_value != 0)
254
+ info = "Exit code #{command.status_value}\n"
255
+ info << command.error_output if command.error_output
256
+ end
257
+ end
258
+ end
259
+
260
+ def self.error(command, error_mode = :raise)
261
+ if command
262
+ if error_mode == :raise
263
+ if command.error
264
+ raise command.error
265
+ elsif (command.status_value && command.status_value != 0)
266
+ raise Error.new, error_info(command)
267
+ end
268
+ end
269
+ end
136
270
  end
137
271
 
138
272
  end
@@ -15,6 +15,8 @@ module GrassGis
15
15
  @id = id.to_s
16
16
  @parent = options[:parent]
17
17
  @configuration = options[:configuration] || {}
18
+ @history = @configuration[:history] || []
19
+ @errors = @configuration[:errors] || :raise
18
20
  end
19
21
 
20
22
  def name
@@ -40,7 +42,7 @@ module GrassGis
40
42
  when String
41
43
  if value.include?("\n")
42
44
  raise "Cannot pass multiple options through STDIN" if stdin
43
- stdin = value
45
+ stdin = Support.unindent(value)
44
46
  value = "-"
45
47
  input stdin
46
48
  end
@@ -52,7 +54,17 @@ module GrassGis
52
54
  end
53
55
  end
54
56
  end
55
- cmd.run unless @configuration[:dry]
57
+ @history << cmd
58
+ unless @configuration[:dry]
59
+ run_options = {}
60
+ if @errors == :console
61
+ run_options[:error_output] = :console
62
+ else
63
+ run_options[:error_output] = :separate
64
+ end
65
+ cmd.run run_options
66
+ end
67
+ GrassGis.error cmd, @errors
56
68
  cmd
57
69
  end
58
70
 
@@ -0,0 +1,26 @@
1
+ module GrassGis
2
+ module Support
3
+ module_function
4
+
5
+ def unindent(text, indent = nil)
6
+ text = text.gsub(/\t/, ' '*8)
7
+ mx = text.scan(/^ *[^\n\r]/)
8
+ .flatten
9
+ .map{ |s| s[-1,1]==' ' ? nil : (s.size-1) }
10
+ .compact.min
11
+ if mx && mx>0
12
+ text.gsub!(/^ {1,#{mx}}/, "")
13
+ end
14
+ lines = text.split(/\r?\n/)
15
+ if lines.first.strip.empty? || lines.last.strip.empty?
16
+ lines.shift while lines.first.strip.empty?
17
+ lines.pop while lines.last.strip.empty?
18
+ end
19
+ if indent
20
+ indent = ' ' * indent if indent.kind_of?(Numeric)
21
+ lines = lines.map { |line| "#{indent}#{line}" }
22
+ end
23
+ lines.join("\n")
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module GrassGis
2
- VERSION = "0.0.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/grassgis.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'sys_cmd'
2
2
  require 'grassgis/version'
3
+ require 'grassgis/support'
3
4
  require 'grassgis/module'
4
5
  require 'grassgis/context'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grassgis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Javier Goizueta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-21 00:00:00.000000000 Z
11
+ date: 2015-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sys_cmd
@@ -83,6 +83,7 @@ files:
83
83
  - lib/grassgis.rb
84
84
  - lib/grassgis/context.rb
85
85
  - lib/grassgis/module.rb
86
+ - lib/grassgis/support.rb
86
87
  - lib/grassgis/version.rb
87
88
  homepage: https://github.com/jgoizueta/grassgis
88
89
  licenses: