grassgis 0.0.1 → 0.2.0

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.
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: