xpflow 0.1b
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/bin/xpflow +96 -0
- data/lib/colorado.rb +198 -0
- data/lib/json/add/core.rb +243 -0
- data/lib/json/add/rails.rb +8 -0
- data/lib/json/common.rb +423 -0
- data/lib/json/editor.rb +1369 -0
- data/lib/json/ext.rb +28 -0
- data/lib/json/pure/generator.rb +442 -0
- data/lib/json/pure/parser.rb +320 -0
- data/lib/json/pure.rb +15 -0
- data/lib/json/version.rb +8 -0
- data/lib/json.rb +62 -0
- data/lib/mime/types.rb +881 -0
- data/lib/mime-types.rb +3 -0
- data/lib/restclient/abstract_response.rb +106 -0
- data/lib/restclient/exceptions.rb +193 -0
- data/lib/restclient/net_http_ext.rb +55 -0
- data/lib/restclient/payload.rb +235 -0
- data/lib/restclient/raw_response.rb +34 -0
- data/lib/restclient/request.rb +316 -0
- data/lib/restclient/resource.rb +169 -0
- data/lib/restclient/response.rb +24 -0
- data/lib/restclient.rb +174 -0
- data/lib/xpflow/bash.rb +341 -0
- data/lib/xpflow/bundle.rb +113 -0
- data/lib/xpflow/cmdline.rb +249 -0
- data/lib/xpflow/collection.rb +122 -0
- data/lib/xpflow/concurrency.rb +79 -0
- data/lib/xpflow/data.rb +393 -0
- data/lib/xpflow/dsl.rb +816 -0
- data/lib/xpflow/engine.rb +574 -0
- data/lib/xpflow/ensemble.rb +135 -0
- data/lib/xpflow/events.rb +56 -0
- data/lib/xpflow/experiment.rb +65 -0
- data/lib/xpflow/exts/facter.rb +30 -0
- data/lib/xpflow/exts/g5k.rb +931 -0
- data/lib/xpflow/exts/g5k_use.rb +50 -0
- data/lib/xpflow/exts/gui.rb +140 -0
- data/lib/xpflow/exts/model.rb +155 -0
- data/lib/xpflow/graph.rb +1603 -0
- data/lib/xpflow/graph_xpflow.rb +251 -0
- data/lib/xpflow/import.rb +196 -0
- data/lib/xpflow/library.rb +349 -0
- data/lib/xpflow/logging.rb +153 -0
- data/lib/xpflow/manager.rb +147 -0
- data/lib/xpflow/nodes.rb +1250 -0
- data/lib/xpflow/runs.rb +773 -0
- data/lib/xpflow/runtime.rb +125 -0
- data/lib/xpflow/scope.rb +168 -0
- data/lib/xpflow/ssh.rb +186 -0
- data/lib/xpflow/stat.rb +50 -0
- data/lib/xpflow/stdlib.rb +381 -0
- data/lib/xpflow/structs.rb +369 -0
- data/lib/xpflow/taktuk.rb +193 -0
- data/lib/xpflow/templates/ssh-config.basic +14 -0
- data/lib/xpflow/templates/ssh-config.inria +18 -0
- data/lib/xpflow/templates/ssh-config.proxy +13 -0
- data/lib/xpflow/templates/taktuk +6590 -0
- data/lib/xpflow/templates/utils/batch +4 -0
- data/lib/xpflow/templates/utils/bootstrap +12 -0
- data/lib/xpflow/templates/utils/hostname +3 -0
- data/lib/xpflow/templates/utils/ping +3 -0
- data/lib/xpflow/templates/utils/rsync +12 -0
- data/lib/xpflow/templates/utils/scp +17 -0
- data/lib/xpflow/templates/utils/scp_many +8 -0
- data/lib/xpflow/templates/utils/ssh +3 -0
- data/lib/xpflow/templates/utils/ssh-interactive +4 -0
- data/lib/xpflow/templates/utils/taktuk +19 -0
- data/lib/xpflow/threads.rb +187 -0
- data/lib/xpflow/utils.rb +569 -0
- data/lib/xpflow/visual.rb +230 -0
- data/lib/xpflow/with_g5k.rb +7 -0
- data/lib/xpflow.rb +349 -0
- metadata +135 -0
data/bin/xpflow
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
# Runs xpflow script
|
4
|
+
|
5
|
+
require('pathname')
|
6
|
+
|
7
|
+
def realpath(x)
|
8
|
+
Pathname.new(x).realpath.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
# code that magically switches ruby interpreter
|
12
|
+
if ENV.key?("__RUBY__")
|
13
|
+
__ruby__ = ENV["__RUBY__"]
|
14
|
+
__here__ = realpath(__FILE__)
|
15
|
+
ENV.delete("__RUBY__") # avoid infinite loop
|
16
|
+
begin
|
17
|
+
exec(__ruby__, __here__, *ARGV)
|
18
|
+
rescue Errno::ENOENT => e
|
19
|
+
puts "Could not launch with custom Ruby (#{e})."
|
20
|
+
end
|
21
|
+
exit 1
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_lib_dir
|
25
|
+
f = __FILE__
|
26
|
+
f = File.readlink(f) if File.symlink?(f)
|
27
|
+
p = Pathname.new(File.dirname(f))
|
28
|
+
lib = File.join(p.realpath, '..', 'lib')
|
29
|
+
return Pathname.new(lib).realpath.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
$:.unshift(get_lib_dir)
|
33
|
+
|
34
|
+
#XSTART
|
35
|
+
require 'xpflow'
|
36
|
+
#XEND
|
37
|
+
|
38
|
+
def usage
|
39
|
+
puts "XPFlow (running on Ruby #{RUBY_VERSION})"
|
40
|
+
puts
|
41
|
+
puts "Usage:"
|
42
|
+
puts " xpflow <cmd> <workflow> [OPTIONS]"
|
43
|
+
puts
|
44
|
+
puts "Standard commands:"
|
45
|
+
puts " xpflow run <workflow> - run a workflow"
|
46
|
+
puts
|
47
|
+
end
|
48
|
+
|
49
|
+
def use(*args)
|
50
|
+
|
51
|
+
# TODO: this should be more sophisticated
|
52
|
+
# for now it's so so
|
53
|
+
|
54
|
+
args.each do |lib|
|
55
|
+
require "xpflow/exts/#{lib.to_s}_use"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if true
|
60
|
+
|
61
|
+
$original_argv = ARGV.clone
|
62
|
+
|
63
|
+
begin
|
64
|
+
$cmdline_options = XPFlow::Options.new(ARGV.dup)
|
65
|
+
$variables = $cmdline_options.vars
|
66
|
+
$engine.init_from_options($cmdline_options)
|
67
|
+
rescue XPFlow::CmdlineError => e
|
68
|
+
if e.ignore?
|
69
|
+
exit 0
|
70
|
+
else
|
71
|
+
Kernel.puts "Error while parsing cmdline: #{e}"
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
$cmdline_options.includes.each do |filename|
|
77
|
+
filename = realpath(filename)
|
78
|
+
require(filename)
|
79
|
+
end
|
80
|
+
|
81
|
+
ok = nil
|
82
|
+
begin
|
83
|
+
XPFlow::TerminalThread.start_thread
|
84
|
+
_, ok = $cmdline_options.dispatch($engine)
|
85
|
+
rescue => e
|
86
|
+
Kernel.puts "Error while running : #{e}."
|
87
|
+
if $cmdline_options.verbose?
|
88
|
+
Kernel.puts "Backtrace:"
|
89
|
+
e.backtrace.each do |line|
|
90
|
+
Kernel.puts(" " + line)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
ok = false
|
94
|
+
end
|
95
|
+
exit(ok ? 0 : 1)
|
96
|
+
end
|
data/lib/colorado.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
|
2
|
+
# This simple library allows you to use
|
3
|
+
# colors with strings
|
4
|
+
|
5
|
+
module Colorado
|
6
|
+
|
7
|
+
COLORS = {
|
8
|
+
:red => 31,
|
9
|
+
:green => 32,
|
10
|
+
:yellow => 33,
|
11
|
+
:blue => 34,
|
12
|
+
:violet => 35,
|
13
|
+
:magenta => 36,
|
14
|
+
:white => 37,
|
15
|
+
:normal => 0
|
16
|
+
}
|
17
|
+
|
18
|
+
KEYS = COLORS.keys + COLORS.keys.map { |c| "#{c}!" }
|
19
|
+
|
20
|
+
module StringMix
|
21
|
+
|
22
|
+
Colorado::KEYS.each do |color|
|
23
|
+
define_method(color) do
|
24
|
+
return Colorado::Str.new(self, color)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
module BaseMix
|
31
|
+
|
32
|
+
Colorado::KEYS.each do |color|
|
33
|
+
define_method(color) do
|
34
|
+
return self.plain.send(:color)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class Color
|
41
|
+
|
42
|
+
attr_reader :bold
|
43
|
+
attr_reader :color
|
44
|
+
|
45
|
+
def initialize(c)
|
46
|
+
@color = (c.is_a?(Color) ? c.color : c)
|
47
|
+
@bold = @color.to_s.end_with?('!')
|
48
|
+
@index = @color.to_s.chomp('!').to_sym
|
49
|
+
end
|
50
|
+
|
51
|
+
def code
|
52
|
+
return COLORS[@index]
|
53
|
+
end
|
54
|
+
|
55
|
+
def prefix
|
56
|
+
return '' if @index == :normal
|
57
|
+
return (@bold ? "\e[#{code};1m" : "\e[#{code}m")
|
58
|
+
end
|
59
|
+
|
60
|
+
def suffix
|
61
|
+
return '' if @index == :normal
|
62
|
+
return "\e[0m"
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_s
|
66
|
+
return @color.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
def normal?
|
70
|
+
return @index == :normal
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class Base
|
76
|
+
|
77
|
+
include BaseMix
|
78
|
+
|
79
|
+
attr_reader :color
|
80
|
+
|
81
|
+
def initialize(color)
|
82
|
+
@color = Color.new(color)
|
83
|
+
end
|
84
|
+
|
85
|
+
def +(s)
|
86
|
+
s = Str.new(s) if s.is_a?(String)
|
87
|
+
return Group.new(self.parts + s.parts)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
class Str < Base
|
93
|
+
|
94
|
+
def initialize(s, color = :normal)
|
95
|
+
super(color)
|
96
|
+
raise "Already colorized: #{s}" if Colorado.colorized(s)
|
97
|
+
@s = s.to_s
|
98
|
+
end
|
99
|
+
|
100
|
+
def inspect
|
101
|
+
"<'#{@s}' in #{@color}>"
|
102
|
+
end
|
103
|
+
|
104
|
+
def plain
|
105
|
+
return @s
|
106
|
+
end
|
107
|
+
|
108
|
+
def parts
|
109
|
+
return [ self ]
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
return "#{color.prefix}#{@s}#{color.suffix}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Group < Base
|
118
|
+
|
119
|
+
def initialize(array)
|
120
|
+
super(:normal)
|
121
|
+
@array = array
|
122
|
+
end
|
123
|
+
|
124
|
+
def exec(method)
|
125
|
+
return @array.map { |it| it.send(method) }
|
126
|
+
end
|
127
|
+
|
128
|
+
def parts
|
129
|
+
return exec(:parts).reduce(:+)
|
130
|
+
end
|
131
|
+
|
132
|
+
def plain
|
133
|
+
return exec(:plain).reduce(:+)
|
134
|
+
end
|
135
|
+
|
136
|
+
def inspect
|
137
|
+
return parts.inspect
|
138
|
+
end
|
139
|
+
|
140
|
+
def to_s
|
141
|
+
return exec(:to_s).reduce(:+)
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.substitute(fmt, array)
|
147
|
+
parts = fmt.split(/%(.)/)
|
148
|
+
strings = []
|
149
|
+
idx = 0
|
150
|
+
parts.each_index do |i|
|
151
|
+
s = parts[i]
|
152
|
+
if i.even? # normal string
|
153
|
+
next if s == ''
|
154
|
+
strings.push(Str.new(s))
|
155
|
+
else
|
156
|
+
if s == 's'
|
157
|
+
strings.push(fix(array[idx]))
|
158
|
+
idx += 1
|
159
|
+
elsif s == '%'
|
160
|
+
strings.push(fix('%'))
|
161
|
+
else
|
162
|
+
raise "Error!"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
return Group.new(strings)
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.fix(x)
|
170
|
+
return x if x.is_a?(Base)
|
171
|
+
return Str.new(x.to_s)
|
172
|
+
end
|
173
|
+
|
174
|
+
def self.colorized(s)
|
175
|
+
return (!s.is_a?(Base) && s.to_s.include?("\e"))
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
class String
|
181
|
+
|
182
|
+
include Colorado::StringMix
|
183
|
+
|
184
|
+
alias old_addition :+
|
185
|
+
alias old_modulo :%
|
186
|
+
|
187
|
+
def +(x)
|
188
|
+
return Colorado::Str.new(self) + x if x.is_a?(Colorado::Base)
|
189
|
+
return old_addition(x)
|
190
|
+
end
|
191
|
+
|
192
|
+
def %(x)
|
193
|
+
return Colorado.substitute(self, [x]) if x.is_a?(Colorado::Base)
|
194
|
+
return Colorado.substitute(self, x) if (x.is_a?(Array) && x.any? { |el| el.is_a?(Colorado::Base) } )
|
195
|
+
return old_modulo(x)
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
# This file contains implementations of ruby core's custom objects for
|
2
|
+
# serialisation/deserialisation.
|
3
|
+
|
4
|
+
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
5
|
+
require 'json'
|
6
|
+
end
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
# Symbol serialization/deserialization
|
10
|
+
class Symbol
|
11
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
12
|
+
# object.
|
13
|
+
def as_json(*)
|
14
|
+
{
|
15
|
+
JSON.create_id => self.class.name,
|
16
|
+
's' => to_s,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Stores class name (Symbol) with String representation of Symbol as a JSON string.
|
21
|
+
def to_json(*a)
|
22
|
+
as_json.to_json(*a)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
|
26
|
+
def self.json_create(o)
|
27
|
+
o['s'].to_sym
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Time serialization/deserialization
|
32
|
+
class Time
|
33
|
+
|
34
|
+
# Deserializes JSON string by converting time since epoch to Time
|
35
|
+
def self.json_create(object)
|
36
|
+
if usec = object.delete('u') # used to be tv_usec -> tv_nsec
|
37
|
+
object['n'] = usec * 1000
|
38
|
+
end
|
39
|
+
if respond_to?(:tv_nsec)
|
40
|
+
at(*object.values_at('s', 'n'))
|
41
|
+
else
|
42
|
+
at(object['s'], object['n'] / 1000)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
47
|
+
# object.
|
48
|
+
def as_json(*)
|
49
|
+
{
|
50
|
+
JSON.create_id => self.class.name,
|
51
|
+
's' => tv_sec,
|
52
|
+
'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
# Stores class name (Time) with number of seconds since epoch and number of
|
57
|
+
# microseconds for Time as JSON string
|
58
|
+
def to_json(*args)
|
59
|
+
as_json.to_json(*args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Date serialization/deserialization
|
64
|
+
class Date
|
65
|
+
|
66
|
+
# Deserializes JSON string by converting Julian year <tt>y</tt>, month
|
67
|
+
# <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
|
68
|
+
def self.json_create(object)
|
69
|
+
civil(*object.values_at('y', 'm', 'd', 'sg'))
|
70
|
+
end
|
71
|
+
|
72
|
+
alias start sg unless method_defined?(:start)
|
73
|
+
|
74
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
75
|
+
# object.
|
76
|
+
def as_json(*)
|
77
|
+
{
|
78
|
+
JSON.create_id => self.class.name,
|
79
|
+
'y' => year,
|
80
|
+
'm' => month,
|
81
|
+
'd' => day,
|
82
|
+
'sg' => start,
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
# Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
|
87
|
+
# <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
|
88
|
+
def to_json(*args)
|
89
|
+
as_json.to_json(*args)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# DateTime serialization/deserialization
|
94
|
+
class DateTime
|
95
|
+
|
96
|
+
# Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
|
97
|
+
# day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
|
98
|
+
# offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
|
99
|
+
def self.json_create(object)
|
100
|
+
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
|
101
|
+
of_a, of_b = object['of'].split('/')
|
102
|
+
if of_b and of_b != '0'
|
103
|
+
args << Rational(of_a.to_i, of_b.to_i)
|
104
|
+
else
|
105
|
+
args << of_a
|
106
|
+
end
|
107
|
+
args << object['sg']
|
108
|
+
civil(*args)
|
109
|
+
end
|
110
|
+
|
111
|
+
alias start sg unless method_defined?(:start)
|
112
|
+
|
113
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
114
|
+
# object.
|
115
|
+
def as_json(*)
|
116
|
+
{
|
117
|
+
JSON.create_id => self.class.name,
|
118
|
+
'y' => year,
|
119
|
+
'm' => month,
|
120
|
+
'd' => day,
|
121
|
+
'H' => hour,
|
122
|
+
'M' => min,
|
123
|
+
'S' => sec,
|
124
|
+
'of' => offset.to_s,
|
125
|
+
'sg' => start,
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
# Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
|
130
|
+
# day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
|
131
|
+
# offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
|
132
|
+
def to_json(*args)
|
133
|
+
as_json.to_json(*args)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Range serialization/deserialization
|
138
|
+
class Range
|
139
|
+
|
140
|
+
# Deserializes JSON string by constructing new Range object with arguments
|
141
|
+
# <tt>a</tt> serialized by <tt>to_json</tt>.
|
142
|
+
def self.json_create(object)
|
143
|
+
new(*object['a'])
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
147
|
+
# object.
|
148
|
+
def as_json(*)
|
149
|
+
{
|
150
|
+
JSON.create_id => self.class.name,
|
151
|
+
'a' => [ first, last, exclude_end? ]
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
# Stores class name (Range) with JSON array of arguments <tt>a</tt> which
|
156
|
+
# include <tt>first</tt> (integer), <tt>last</tt> (integer), and
|
157
|
+
# <tt>exclude_end?</tt> (boolean) as JSON string.
|
158
|
+
def to_json(*args)
|
159
|
+
as_json.to_json(*args)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Struct serialization/deserialization
|
164
|
+
class Struct
|
165
|
+
|
166
|
+
# Deserializes JSON string by constructing new Struct object with values
|
167
|
+
# <tt>v</tt> serialized by <tt>to_json</tt>.
|
168
|
+
def self.json_create(object)
|
169
|
+
new(*object['v'])
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
173
|
+
# object.
|
174
|
+
def as_json(*)
|
175
|
+
klass = self.class.name
|
176
|
+
klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
|
177
|
+
{
|
178
|
+
JSON.create_id => klass,
|
179
|
+
'v' => values,
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
# Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string.
|
184
|
+
# Only named structs are supported.
|
185
|
+
def to_json(*args)
|
186
|
+
as_json.to_json(*args)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Exception serialization/deserialization
|
191
|
+
class Exception
|
192
|
+
|
193
|
+
# Deserializes JSON string by constructing new Exception object with message
|
194
|
+
# <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt>
|
195
|
+
def self.json_create(object)
|
196
|
+
result = new(object['m'])
|
197
|
+
result.set_backtrace object['b']
|
198
|
+
result
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
202
|
+
# object.
|
203
|
+
def as_json(*)
|
204
|
+
{
|
205
|
+
JSON.create_id => self.class.name,
|
206
|
+
'm' => message,
|
207
|
+
'b' => backtrace,
|
208
|
+
}
|
209
|
+
end
|
210
|
+
|
211
|
+
# Stores class name (Exception) with message <tt>m</tt> and backtrace array
|
212
|
+
# <tt>b</tt> as JSON string
|
213
|
+
def to_json(*args)
|
214
|
+
as_json.to_json(*args)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Regexp serialization/deserialization
|
219
|
+
class Regexp
|
220
|
+
|
221
|
+
# Deserializes JSON string by constructing new Regexp object with source
|
222
|
+
# <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by
|
223
|
+
# <tt>to_json</tt>
|
224
|
+
def self.json_create(object)
|
225
|
+
new(object['s'], object['o'])
|
226
|
+
end
|
227
|
+
|
228
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
229
|
+
# object.
|
230
|
+
def as_json(*)
|
231
|
+
{
|
232
|
+
JSON.create_id => self.class.name,
|
233
|
+
'o' => options,
|
234
|
+
's' => source,
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
# Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
|
239
|
+
# (Regexp or String) as JSON string
|
240
|
+
def to_json(*)
|
241
|
+
as_json.to_json
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# This file used to implementations of rails custom objects for
|
2
|
+
# serialisation/deserialisation and is obsoleted now.
|
3
|
+
|
4
|
+
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
|
5
|
+
require 'json'
|
6
|
+
end
|
7
|
+
|
8
|
+
$DEBUG and warn "required json/add/rails which is obsolete now!"
|