opm 1.0.1

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.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2007-07-26
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 FIXME full name
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/opm.rb
7
+ lib/opm/version.rb
8
+ setup.rb
@@ -0,0 +1,3 @@
1
+ README for opm
2
+ ==============
3
+
@@ -0,0 +1,123 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+
12
+ include FileUtils
13
+ require File.join(File.dirname(__FILE__), 'lib', 'opm', 'version')
14
+
15
+ AUTHOR = 'Papp Laszlo' # can also be an array of Authors
16
+ EMAIL = "pappl@inf.elte.hu"
17
+ DESCRIPTION = "OPM support for Ruby"
18
+ GEM_NAME = 'opm' # what ppl will type to install your gem
19
+
20
+ @config_file = "~/.rubyforge/user-config.yml"
21
+ @config = nil
22
+ def rubyforge_username
23
+ unless @config
24
+ begin
25
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
26
+ rescue
27
+ puts <<-EOS
28
+ ERROR: No rubyforge config file found: #{@config_file}"
29
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
30
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
31
+ EOS
32
+ exit
33
+ end
34
+ end
35
+ @rubyforge_username ||= @config["username"]
36
+ end
37
+
38
+ RUBYFORGE_PROJECT = 'opm' # The unix name for your project
39
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
40
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
41
+
42
+ NAME = "opm"
43
+ REV = nil
44
+ # UNCOMMENT IF REQUIRED:
45
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
46
+ VERS = Opm::VERSION::STRING + (REV ? ".#{REV}" : "")
47
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
48
+ RDOC_OPTS = ['--quiet', '--title', 'opm documentation',
49
+ "--opname", "index.html",
50
+ "--line-numbers",
51
+ "--main", "README",
52
+ "--inline-source"]
53
+
54
+ class Hoe
55
+ def extra_deps
56
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
57
+ end
58
+ end
59
+
60
+ # Generate all the Rake tasks
61
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
62
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
63
+ p.author = AUTHOR
64
+ p.description = DESCRIPTION
65
+ p.email = EMAIL
66
+ p.summary = DESCRIPTION
67
+ p.url = HOMEPATH
68
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
69
+ p.test_globs = ["test/**/test_*.rb"]
70
+ p.clean_globs |= CLEAN #An array of file patterns to delete on clean.
71
+
72
+ # == Optional
73
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
74
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
75
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
76
+ end
77
+
78
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\n\n")
79
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
80
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
81
+
82
+ desc 'Generate website files'
83
+ task :website_generate do
84
+ Dir['website/**/*.txt'].each do |txt|
85
+ sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
86
+ end
87
+ end
88
+
89
+ desc 'Upload website files to rubyforge'
90
+ task :website_upload do
91
+ host = "#{rubyforge_username}@rubyforge.org"
92
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
93
+ local_dir = 'website'
94
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
95
+ end
96
+
97
+ desc 'Generate and upload website files'
98
+ task :website => [:website_generate, :website_upload, :publish_docs]
99
+
100
+ desc 'Release the website and new gem version'
101
+ task :deploy => [:check_version, :website, :release] do
102
+ puts "Remember to create SVN tag:"
103
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
104
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
105
+ puts "Suggested comment:"
106
+ puts "Tagging release #{CHANGES}"
107
+ end
108
+
109
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
110
+ task :local_deploy => [:website_generate, :install_gem]
111
+
112
+ task :check_version do
113
+ unless ENV['VERSION']
114
+ puts 'Must pass a VERSION=x.y.z release version'
115
+ exit
116
+ end
117
+ unless ENV['VERSION'] == VERS
118
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
119
+ exit
120
+ end
121
+ end
122
+
123
+
@@ -0,0 +1,379 @@
1
+ #
2
+ # Copyright (c) 2007 Papp Laszlo (pappl@inf.elte.hu)
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ require 'opm/version'
22
+ require 'thread'
23
+ require 'drb'
24
+
25
+ module Opm
26
+
27
+ # A Temporary Object, if the process is working while we want reach the instance variable,
28
+ # it attaches the running process, and variable name for in the future we can get the value.
29
+ class TemporaryProcessObject
30
+
31
+ # The process, which working on the object
32
+ attr_reader :process
33
+
34
+ # Name of the object
35
+ attr_reader :variable
36
+
37
+ def initialize( process, var )
38
+ @process = process
39
+ @variable = var
40
+ end
41
+ end
42
+
43
+ module OpmException
44
+
45
+ class ProcessException < Exception
46
+ attr_reader :process
47
+
48
+ def initialize(process)
49
+ @process = process
50
+ end
51
+
52
+ end
53
+
54
+ class NoInput < ProcessException
55
+ end
56
+
57
+ class BeforeFilterFailed < ProcessException
58
+ end
59
+
60
+ class AfterFilterFailed < ProcessException
61
+ end
62
+
63
+ end
64
+
65
+ # For OPM States.. It contains only states, and only one active
66
+ #
67
+ # class LoggedIn < OpmStatus
68
+ # states :logged, :logout
69
+ # end
70
+ #
71
+ # stat = LoggedIn.status :logged
72
+ # stat.status #:logged
73
+ #
74
+ # stat.logout
75
+ # stat.status #:logout
76
+ #
77
+ class OpmStatus
78
+ class << self
79
+ #attr_accessor :statuses
80
+ end
81
+
82
+ protected
83
+ def self.states(*args)
84
+ @statuses ||= []
85
+ @statuses += args
86
+ end
87
+
88
+ public
89
+
90
+ # For generate a status object
91
+ # @param status: The initializer status
92
+ def self.status( status )
93
+ object = new(status)
94
+ @statuses.each do |stat|
95
+ class_eval %(class << object
96
+ def #{stat}
97
+ @status = :#{stat}
98
+ end
99
+ end
100
+ )
101
+ end
102
+ return object
103
+ end
104
+
105
+ private
106
+
107
+ def self.inherited(subclass)
108
+ begin
109
+ self.statuses.each do |stat|
110
+ subclass.states(stat)
111
+ end
112
+ rescue
113
+ end
114
+ end
115
+
116
+ protected
117
+ def initialize(status)
118
+ @status = status
119
+ end
120
+
121
+ public
122
+ # The current status. Returns symbol!
123
+ def status
124
+ return @status
125
+ end
126
+
127
+ # The same as status method.
128
+ def to_s
129
+ return @status
130
+ end
131
+ end
132
+
133
+ # Main process class
134
+ #
135
+ # class Sum < OpmProcess
136
+ # input :input1, :input2
137
+ # output :output1
138
+ #
139
+ # def run
140
+ # @output1 = @input1 + @input2
141
+ # end
142
+ # end
143
+ #
144
+ # proc = Sum.process :input1 => 1, :input2 => 12
145
+ # proc.wait
146
+ # puts proc.output1 # 13
147
+ class OpmProcess
148
+
149
+ class << self
150
+ #attr_accessor :input_arguments
151
+ #attr_accessor :output_arguments
152
+ #attr_accessor :remote
153
+ end
154
+
155
+ public
156
+
157
+ # Define input variables. In the process if you use
158
+ #
159
+ # include :foo, :bar
160
+ #
161
+ # then you can use them as @foo, @bar
162
+ #
163
+ def self.input(*args)
164
+ @input_arguments ||= []
165
+ @input_arguments += args
166
+ args.each do |arg|
167
+ instance_variable_set("@#{arg}", nil)
168
+ end
169
+ end
170
+
171
+ # Outputs of the process
172
+ #
173
+ # class SampleProcess < OpmProcess
174
+ # input :input
175
+ # output :foo
176
+ # ...
177
+ # end
178
+ #
179
+ # bar = SampleProcess.process :input => "something"
180
+ # puts bar.foo
181
+ #
182
+ def self.output(*args)
183
+ @output_arguments ||= []
184
+ @output_arguments += args
185
+ args.each do |arg|
186
+ instance_variable_set("@#{arg}", nil)
187
+ class_eval %(class << self; attr_reader :#{arg} end)
188
+ end
189
+ end
190
+
191
+ def self.remote(args) #:nodoc:
192
+ @remote = args
193
+ end
194
+
195
+ # Start the process
196
+ # @args => Parameters for input variables
197
+ #
198
+ def self.process(args={})
199
+
200
+ if @remote != nil
201
+ #It's not okay yet
202
+ object = DRb::DRbObject.new object, "druby://#{@remote[:host]}:#{@remote[:port]}"
203
+ else
204
+ object = new
205
+ end
206
+
207
+ @input_arguments.each do |arg|
208
+ # throw OpmException::NoInput.new(object) unless args.has_key? arg
209
+ if args[arg].class == TemporaryProcessObject
210
+ object.underProcessing = [arg, args[arg]]
211
+ next
212
+ end
213
+ object.instance_variable_set("@#{arg}", args[arg])
214
+ end
215
+
216
+ @output_arguments.each do |arg|
217
+ object.instance_variable_set("@#{arg}", args[arg])
218
+ object.outputsForWait = arg
219
+ class_eval %( class << object; def #{arg}
220
+ return @#{arg} unless running?
221
+ return TemporaryProcessObject.new(self, "#{arg}")
222
+ end
223
+ end
224
+ )
225
+ end
226
+ object.start_process
227
+ return object
228
+ end
229
+
230
+
231
+ # Inherits from base class the input arguments
232
+ #
233
+ private
234
+ def self.inherited(subclass)
235
+ begin
236
+ self.input_arguments.each do |arg|
237
+ subclass.input(arg)
238
+ end
239
+
240
+ self.output_arguments.each do |arg|
241
+ subclass.output(arg)
242
+ end
243
+ rescue
244
+ # This branch is running when @input_arguments == nil
245
+ end
246
+ end
247
+
248
+ protected
249
+ def initialize
250
+ @underProcessing = []
251
+ @outputsForWait = []
252
+
253
+ @thread = Thread.new do
254
+ Thread.stop
255
+ @underProcessing.each do |p|
256
+ while p[1].process.running?
257
+ end
258
+ instance_variable_set("@#{p[0]}", p[1].process.instance_eval("@#{p[1].variable}"))
259
+ end
260
+
261
+ begin
262
+
263
+ if not before
264
+ @error = OpmException::BeforeFilterFailed.new(self)
265
+ raise @error
266
+ end
267
+
268
+ # Run the body of the process
269
+ run
270
+
271
+ if not after
272
+ @error = OpmException::AfterFilterFailed.new(self)
273
+ raise @error
274
+ end
275
+
276
+ # Wait for the outputs become active
277
+ wait_output_done
278
+ rescue OpmException::BeforeFilterFailed => before
279
+ onBeforeError
280
+ Thread.exit
281
+ rescue OpmException::AfterFilterFailed => after
282
+ onAfterError
283
+ Thread.exit
284
+ end
285
+ end
286
+ end
287
+
288
+ public
289
+ # Before filter for process. It's a logical function. If the function returns fault,
290
+ # the process calls the onBeforeError, where we can set the parameters. For more
291
+ # information about the cause of the error, use @error variable in onBeforeError.
292
+ #
293
+ def before
294
+ true
295
+ end
296
+
297
+ # Similar to before, but this is checking the result of the process
298
+ #
299
+ def after
300
+ true
301
+ end
302
+
303
+ # Callback function. It will signaled if before is false
304
+ #
305
+ def onBeforeError
306
+ end
307
+
308
+ # Look: onBeforeError.
309
+ #
310
+ def onAfterError
311
+ end
312
+
313
+ # Secure only one process be running in a block.
314
+ #
315
+ def onlyOne(args, &block)
316
+ @@Mutex ||= Hash.new
317
+ @@Mutex[args] = Mutex.new if @@Mutex[args] == nil
318
+ @@Mutex[args].synchronize do
319
+ yield
320
+ end
321
+ end
322
+
323
+ def underProcessing=( val ) #:nodoc:
324
+ @underProcessing << val
325
+ end
326
+
327
+
328
+ # For set the output attributes, for wait_output_done
329
+ def outputsForWait=( val ) #:nodoc:
330
+ @outputsForWait << val
331
+ end
332
+
333
+ def start_process #:nodoc:
334
+ @thread.run
335
+ end
336
+
337
+ private
338
+ # If a process contains another one, then the main process have to wait
339
+ # the inner process, because the output will be incosistent
340
+ #
341
+ def wait_output_done
342
+ # For all output arguments
343
+ @outputsForWait.each do |val|
344
+ # Get the value
345
+ output = instance_variable_get("@#{val}")
346
+
347
+ # We use exception handler, if output is not TemporaryProcessObject
348
+ begin
349
+ # While not active the object
350
+ #while output.process.running?
351
+ #end
352
+ output.process.wait
353
+
354
+ # Get the new value of the output
355
+ var = eval("output.process.#{val}")
356
+
357
+ # Set the instance variable
358
+ instance_variable_set("@#{val}", var)
359
+ rescue
360
+ # if output.process not defined, because output is not a TemporaryProcessObject
361
+ end
362
+ end
363
+ end
364
+
365
+ public
366
+
367
+ # Check thread is running
368
+ def running?
369
+ return @thread.alive?
370
+ end
371
+
372
+ def wait
373
+ @thread.join
374
+ end
375
+
376
+ end
377
+ end
378
+
379
+