palsy 0.0.3 → 0.0.4
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 +7 -0
- data/CHANGELOG.md +3 -0
- data/lib/palsy.rb +62 -3
- data/lib/palsy/basic/list.rb +20 -11
- data/lib/palsy/basic/map.rb +23 -4
- data/lib/palsy/basic/object.rb +11 -3
- data/lib/palsy/basic/set.rb +10 -6
- data/lib/palsy/version.rb +1 -1
- data/test/helper.rb +1 -0
- data/test/test_init.rb +15 -0
- data/test/test_list.rb +40 -0
- data/test/test_map.rb +53 -0
- data/test/test_object.rb +35 -0
- data/test/test_set.rb +55 -0
- metadata +15 -39
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 60fb2ba51b992f7b83ce4d94f0999bbdd57ba8a7
|
4
|
+
data.tar.gz: b52c06df6875bade0c18b0261c19ee2c1c27c51a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ba0b46d264bd49e24ed3780827705ab7a17a7cf1145a6e81beb903ec2fcfcd79f986ea7c5e564b48b5ac26fc8183cd2f2b8d42a7bccb2a83cb4fce63d395a84a
|
7
|
+
data.tar.gz: aa00113a932da3527a871e940493d099698c42d025b8d6093f27ccb1b1a95397c67705465c649964494ce5c44354e6cbdb3781a66aed4973eaf2b9b4d16abdf9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
* 0.0.4 - April 6, 2013
|
2
|
+
* This takes the changes in 0.0.3 and improves robustness over high-volume
|
3
|
+
concurrency and improves transaction isolation for single operations.
|
1
4
|
* 0.0.3 - April 2, 2013
|
2
5
|
* Ensure exclusive transactions are being used for all operations. This
|
3
6
|
should make it a little more viable for non-MRI things.
|
data/lib/palsy.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'sqlite3'
|
2
2
|
require 'singleton'
|
3
3
|
require 'delegate'
|
4
|
+
require 'thread'
|
4
5
|
require "palsy/version"
|
5
6
|
|
6
7
|
# Present ruby core data structures in a manner similar to perl's tie backed by a
|
@@ -67,6 +68,7 @@ class Palsy < DelegateClass(SQLite3::Database)
|
|
67
68
|
# working with the rest of the library.
|
68
69
|
#
|
69
70
|
def initialize
|
71
|
+
@palsy_lock = Mutex.new
|
70
72
|
super(connect)
|
71
73
|
end
|
72
74
|
|
@@ -88,15 +90,72 @@ class Palsy < DelegateClass(SQLite3::Database)
|
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
93
|
+
# Override the explicit lock for the current thread. For things that generate
|
94
|
+
# queries, will not attempt to acquire a mutex, will not attempt to run a
|
95
|
+
# transaction. Will just run the block. See #with_t for information on lock
|
96
|
+
# semantics.
|
97
|
+
#
|
98
|
+
# For Ruby 2.0 users and above: If you wrap your palsy operations in #no_lock
|
99
|
+
# on the current thread, #with_t will not try to use a mutex lock or
|
100
|
+
# transaction.
|
101
|
+
#
|
102
|
+
# This is useful if you want to use palsy in a signal handler:
|
103
|
+
#
|
104
|
+
# trap("INFO") do
|
105
|
+
# Palsy.instance.no_lock do
|
106
|
+
# some_palsy_thing
|
107
|
+
# end
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# The caveat is that any writes done in this region will not be isolated and
|
111
|
+
# will likely cause problems.
|
112
|
+
#
|
113
|
+
def no_lock
|
114
|
+
retval = nil
|
115
|
+
Thread.current[:palsy_no_lock] = true
|
116
|
+
retval = yield
|
117
|
+
Thread.current[:palsy_no_lock] = false
|
118
|
+
return retval
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Start a mutex-wrapped exclusive transaction, then execute the block. If
|
123
|
+
# we're already the owner of the transaction, just execute.
|
124
|
+
#
|
125
|
+
# This is used by most things in Palsy. If you want to step around the lock
|
126
|
+
# (necessary for specific situations, and has certain caveats), take a look
|
127
|
+
# at #no_lock.
|
128
|
+
#
|
129
|
+
def with_t
|
130
|
+
result = nil
|
131
|
+
tc = Thread.current
|
132
|
+
|
133
|
+
if tc[:lock] or tc[:palsy_no_lock]
|
134
|
+
result = yield
|
135
|
+
else
|
136
|
+
@palsy_lock.synchronize do
|
137
|
+
begin
|
138
|
+
tc[:lock] = @palsy_lock
|
139
|
+
transaction(:exclusive) { result = yield }
|
140
|
+
rescue StandardError => e
|
141
|
+
rollback if transaction_active?
|
142
|
+
raise e
|
143
|
+
ensure
|
144
|
+
tc[:lock] = nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
return result
|
150
|
+
end
|
151
|
+
|
91
152
|
#
|
92
153
|
# Execute this query in an exclusive transaction.
|
93
154
|
#
|
94
155
|
def execute_t(query, args=[], &block)
|
95
156
|
result = nil
|
96
157
|
|
97
|
-
|
98
|
-
result = execute(query, args, &block)
|
99
|
-
end
|
158
|
+
with_t { result = execute(query, args, &block) }
|
100
159
|
|
101
160
|
return result
|
102
161
|
end
|
data/lib/palsy/basic/list.rb
CHANGED
@@ -49,16 +49,23 @@ class Palsy
|
|
49
49
|
# Add a value to the head of the list.
|
50
50
|
#
|
51
51
|
def unshift(val)
|
52
|
-
|
52
|
+
@db.with_t do
|
53
|
+
replace([val] + to_a)
|
54
|
+
end
|
53
55
|
end
|
54
56
|
|
55
57
|
#
|
56
58
|
# Helper method for mutators.
|
57
59
|
#
|
58
60
|
def mutate(meth)
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
val = nil
|
62
|
+
|
63
|
+
@db.with_t do
|
64
|
+
a = to_a
|
65
|
+
val = a.send(meth)
|
66
|
+
replace(a)
|
67
|
+
end
|
68
|
+
|
62
69
|
return val
|
63
70
|
end
|
64
71
|
|
@@ -81,15 +88,17 @@ class Palsy
|
|
81
88
|
# like an Enumerable.
|
82
89
|
#
|
83
90
|
def replace(ary)
|
84
|
-
|
85
|
-
|
91
|
+
@db.with_t do
|
92
|
+
clear
|
93
|
+
return if ary.count == 0
|
86
94
|
|
87
|
-
|
95
|
+
value_string = ("(?, ?)," * ary.count).chop
|
88
96
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
97
|
+
@db.execute_t(
|
98
|
+
"insert into #{@table_name} (name, value) values #{value_string}",
|
99
|
+
ary.map { |x| [@object_name, Marshal.dump(x)] }.flatten
|
100
|
+
)
|
101
|
+
end
|
93
102
|
end
|
94
103
|
|
95
104
|
#
|
data/lib/palsy/basic/map.rb
CHANGED
@@ -49,18 +49,37 @@ class Palsy
|
|
49
49
|
# database before attempting to write the new pair.
|
50
50
|
#
|
51
51
|
def []=(key, value)
|
52
|
-
|
53
|
-
|
52
|
+
@db.with_t do
|
53
|
+
delete(key)
|
54
|
+
@db.execute_t("insert into #{@table_name} (name, key, value) values (?, ?, ?)", [@object_name, Marshal.dump(key), Marshal.dump(value)])
|
55
|
+
end
|
54
56
|
value
|
55
57
|
end
|
56
58
|
|
59
|
+
#
|
60
|
+
# replace this map with the contents of a Hash.
|
61
|
+
#
|
62
|
+
def replace(hash)
|
63
|
+
@db.with_t do
|
64
|
+
clear
|
65
|
+
|
66
|
+
return if hash.keys.empty?
|
67
|
+
|
68
|
+
value_string = ("(?, ?, ?)," * hash.keys.count).chop
|
69
|
+
|
70
|
+
@db.execute_t("insert into #{@table_name} (name, key, value) values #{value_string}", hash.map { |key, value| [@object_name, Marshal.dump(key), Marshal.dump(value)] }.flatten)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
57
74
|
#
|
58
75
|
# Successively yields key and value for each item in the map. Modifications
|
59
76
|
# to either the key or value yielded will not persist.
|
60
77
|
#
|
61
78
|
def each
|
62
|
-
|
63
|
-
|
79
|
+
@db.with_t do
|
80
|
+
keys.each do |key|
|
81
|
+
yield key, self[key]
|
82
|
+
end
|
64
83
|
end
|
65
84
|
end
|
66
85
|
|
data/lib/palsy/basic/object.rb
CHANGED
@@ -27,7 +27,13 @@ class Palsy
|
|
27
27
|
# Get an object by referencing its key. Returns nil unless it exists.
|
28
28
|
#
|
29
29
|
def [](key)
|
30
|
-
value =
|
30
|
+
value = begin
|
31
|
+
ret = @db.execute_t("select value from #{@table_name} where key=?", [key])
|
32
|
+
(ret && ret.first) ? ret.first.first : nil
|
33
|
+
rescue SQLite3::Exception
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
31
37
|
return value && Marshal.load(value)
|
32
38
|
end
|
33
39
|
|
@@ -35,8 +41,10 @@ class Palsy
|
|
35
41
|
# Set an object. Returns the object. The object must be able to be Marshalled.
|
36
42
|
#
|
37
43
|
def []=(key, value)
|
38
|
-
|
39
|
-
|
44
|
+
@db.with_t do
|
45
|
+
delete(key)
|
46
|
+
@db.execute_t("insert into #{@table_name} (key, value) values (?, ?)", [key, Marshal.dump(value)])
|
47
|
+
end
|
40
48
|
value
|
41
49
|
end
|
42
50
|
|
data/lib/palsy/basic/set.rb
CHANGED
@@ -41,8 +41,10 @@ class Palsy
|
|
41
41
|
# avoid raising a constraint from sqlite.
|
42
42
|
#
|
43
43
|
def add(key)
|
44
|
-
|
45
|
-
|
44
|
+
@db.with_t do
|
45
|
+
delete(key)
|
46
|
+
@db.execute_t("insert into #{@table_name} (name, key) values (?, ?)", [@object_name, Marshal.dump(key)])
|
47
|
+
end
|
46
48
|
end
|
47
49
|
|
48
50
|
#
|
@@ -73,13 +75,15 @@ class Palsy
|
|
73
75
|
# set, or any Enumerable that has a set of unique values.
|
74
76
|
#
|
75
77
|
def replace(set)
|
76
|
-
|
78
|
+
@db.with_t do
|
79
|
+
clear
|
77
80
|
|
78
|
-
|
81
|
+
return if set.empty?
|
79
82
|
|
80
|
-
|
83
|
+
value_string = ("(?, ?)," * set.count).chop
|
81
84
|
|
82
|
-
|
85
|
+
@db.execute_t("insert into #{@table_name} (name, key) values #{value_string}", set.map { |x| [@object_name, Marshal.dump(x)] }.flatten)
|
86
|
+
end
|
83
87
|
end
|
84
88
|
|
85
89
|
#
|
data/lib/palsy/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
PalsyVersion = "0.0.
|
1
|
+
PalsyVersion = "0.0.4"
|
data/test/helper.rb
CHANGED
data/test/test_init.rb
CHANGED
@@ -38,4 +38,19 @@ class TestInit < MiniTest::Unit::TestCase
|
|
38
38
|
Palsy.reconnect
|
39
39
|
assert_raises(NoMethodError) { Palsy.instance.closed? }
|
40
40
|
end
|
41
|
+
|
42
|
+
def test_with_t
|
43
|
+
dbfile = new_dbfile
|
44
|
+
Palsy.change_db(dbfile.path)
|
45
|
+
|
46
|
+
(0..2).map do
|
47
|
+
Thread.new do
|
48
|
+
assert_raises(ArgumentError) do
|
49
|
+
Palsy.instance.with_t do
|
50
|
+
raise ArgumentError
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end.map(&:join)
|
55
|
+
end
|
41
56
|
end
|
data/test/test_list.rb
CHANGED
@@ -15,6 +15,46 @@ class TestList < PalsyTypeTest
|
|
15
15
|
t.each(&:join)
|
16
16
|
|
17
17
|
assert_equal(syms.sort, @list.to_a.sort)
|
18
|
+
|
19
|
+
writer = Thread.new { loop { @list.push(rand.to_i) } }
|
20
|
+
reader = Thread.new { loop { @list.shift } }
|
21
|
+
|
22
|
+
begin
|
23
|
+
Timeout.timeout(10) do
|
24
|
+
writer.join
|
25
|
+
reader.join
|
26
|
+
end
|
27
|
+
rescue TimeoutError
|
28
|
+
pass "push and shift competed for 10 seconds without any exceptions"
|
29
|
+
writer.raise
|
30
|
+
reader.raise
|
31
|
+
writer.join rescue nil
|
32
|
+
reader.join rescue nil
|
33
|
+
end
|
34
|
+
|
35
|
+
replacer = Thread.new { loop { @list.replace(Set[1,2,3]) } }
|
36
|
+
clearer = Thread.new { loop { @list.clear } }
|
37
|
+
|
38
|
+
begin
|
39
|
+
Timeout.timeout(10) do
|
40
|
+
replacer.join
|
41
|
+
clearer.join
|
42
|
+
end
|
43
|
+
rescue TimeoutError
|
44
|
+
pass "replace and clear competed for 10 seconds without any exceptions"
|
45
|
+
replacer.raise
|
46
|
+
clearer.raise
|
47
|
+
replacer.join rescue nil
|
48
|
+
clearer.join rescue nil
|
49
|
+
end
|
50
|
+
|
51
|
+
refute(@list.db.transaction_active?)
|
52
|
+
|
53
|
+
# XXX there's no solid way of knowing what'll be in here without inserting
|
54
|
+
# locks which will actually defeat the point of the test. Check the type,
|
55
|
+
# which will cause an execution and ensure we don't have a stale
|
56
|
+
# transaction.
|
57
|
+
assert_kind_of(Array, @list.to_a)
|
18
58
|
end
|
19
59
|
|
20
60
|
def test_semantics
|
data/test/test_map.rb
CHANGED
@@ -16,6 +16,46 @@ class TestMap < PalsyTypeTest
|
|
16
16
|
t.each(&:join)
|
17
17
|
|
18
18
|
assert_equal(@map.to_hash, args)
|
19
|
+
|
20
|
+
writer = Thread.new { loop { @map[rand.to_i] = 1 } }
|
21
|
+
reader = Thread.new { loop { @map.keys } }
|
22
|
+
|
23
|
+
begin
|
24
|
+
Timeout.timeout(10) do
|
25
|
+
writer.join
|
26
|
+
reader.join
|
27
|
+
end
|
28
|
+
rescue TimeoutError
|
29
|
+
pass "[] and keys competed for 10 seconds without any exceptions"
|
30
|
+
writer.raise
|
31
|
+
reader.raise
|
32
|
+
writer.join rescue nil
|
33
|
+
reader.join rescue nil
|
34
|
+
end
|
35
|
+
|
36
|
+
replacer = Thread.new { loop { @map.replace(Hash[[1,2,3].zip([2,3,4])]) } }
|
37
|
+
clearer = Thread.new { loop { @map.clear } }
|
38
|
+
|
39
|
+
begin
|
40
|
+
Timeout.timeout(10) do
|
41
|
+
replacer.join
|
42
|
+
clearer.join
|
43
|
+
end
|
44
|
+
rescue TimeoutError
|
45
|
+
pass "replace and clear competed for 10 seconds without any exceptions"
|
46
|
+
replacer.raise
|
47
|
+
clearer.raise
|
48
|
+
replacer.join rescue nil
|
49
|
+
clearer.join rescue nil
|
50
|
+
end
|
51
|
+
|
52
|
+
refute(@map.db.transaction_active?)
|
53
|
+
|
54
|
+
# XXX there's no solid way of knowing what'll be in here without inserting
|
55
|
+
# locks which will actually defeat the point of the test. Check the type,
|
56
|
+
# which will cause an execution and ensure we don't have a stale
|
57
|
+
# transaction.
|
58
|
+
assert_kind_of(Hash, @map.to_hash)
|
19
59
|
end
|
20
60
|
|
21
61
|
def test_inherits
|
@@ -86,4 +126,17 @@ class TestMap < PalsyTypeTest
|
|
86
126
|
assert_equal(@map[k], v, "#each yields each value")
|
87
127
|
end
|
88
128
|
end
|
129
|
+
|
130
|
+
def test_replace
|
131
|
+
@map[1] = "foo"
|
132
|
+
assert_equal("foo", @map[1])
|
133
|
+
|
134
|
+
hash = {2 => "bar", 3 => "foo"}
|
135
|
+
|
136
|
+
@map.replace(hash)
|
137
|
+
refute_equal("foo", @map[1])
|
138
|
+
assert_equal("bar", @map[2])
|
139
|
+
assert_equal("foo", @map[3])
|
140
|
+
assert_equal(hash, @map.to_hash)
|
141
|
+
end
|
89
142
|
end
|
data/test/test_object.rb
CHANGED
@@ -14,6 +14,41 @@ class TestObject < PalsyTypeTest
|
|
14
14
|
args.each do |k,v|
|
15
15
|
assert_equal(obj[k], args[k])
|
16
16
|
end
|
17
|
+
|
18
|
+
writer = Thread.new { loop { obj["1"] = "1" } }
|
19
|
+
reader = Thread.new { loop { obj["1"] } }
|
20
|
+
|
21
|
+
begin
|
22
|
+
Timeout.timeout(10) do
|
23
|
+
writer.join
|
24
|
+
reader.join
|
25
|
+
end
|
26
|
+
rescue TimeoutError
|
27
|
+
pass "[]= and [] competed for 10 seconds without any exceptions"
|
28
|
+
writer.raise
|
29
|
+
reader.raise
|
30
|
+
writer.join rescue nil
|
31
|
+
reader.join rescue nil
|
32
|
+
end
|
33
|
+
|
34
|
+
replacer = Thread.new { loop { obj[1] = 1 } }
|
35
|
+
clearer = Thread.new { loop { obj.delete(1) } }
|
36
|
+
|
37
|
+
begin
|
38
|
+
Timeout.timeout(10) do
|
39
|
+
replacer.join
|
40
|
+
clearer.join
|
41
|
+
end
|
42
|
+
rescue TimeoutError
|
43
|
+
pass "[]= and delete competed for 10 seconds without any exceptions"
|
44
|
+
replacer.raise
|
45
|
+
clearer.raise
|
46
|
+
replacer.join rescue nil
|
47
|
+
clearer.join rescue nil
|
48
|
+
end
|
49
|
+
|
50
|
+
refute(obj.db.transaction_active?)
|
51
|
+
obj.delete(1)
|
17
52
|
end
|
18
53
|
|
19
54
|
def test_index
|
data/test/test_set.rb
CHANGED
@@ -15,6 +15,61 @@ class TestSet < PalsyTypeTest
|
|
15
15
|
t.each(&:join)
|
16
16
|
|
17
17
|
assert_equal(syms.sort, @set.to_a.sort)
|
18
|
+
|
19
|
+
writer = Thread.new { loop { @set.add(rand.to_i) } }
|
20
|
+
reader = Thread.new { loop { @set.keys } }
|
21
|
+
|
22
|
+
begin
|
23
|
+
Timeout.timeout(10) do
|
24
|
+
writer.join
|
25
|
+
reader.join
|
26
|
+
end
|
27
|
+
rescue TimeoutError
|
28
|
+
pass "add and keys competed for 10 seconds without any exceptions"
|
29
|
+
writer.raise
|
30
|
+
reader.raise
|
31
|
+
writer.join rescue nil
|
32
|
+
reader.join rescue nil
|
33
|
+
end
|
34
|
+
|
35
|
+
replacer = Thread.new { loop { @set.replace(Set[1,2,3]) } }
|
36
|
+
clearer = Thread.new { loop { @set.clear } }
|
37
|
+
|
38
|
+
begin
|
39
|
+
Timeout.timeout(10) do
|
40
|
+
replacer.join
|
41
|
+
clearer.join
|
42
|
+
end
|
43
|
+
rescue TimeoutError
|
44
|
+
pass "replace and clear competed for 10 seconds without any exceptions"
|
45
|
+
replacer.raise
|
46
|
+
clearer.raise
|
47
|
+
replacer.join rescue nil
|
48
|
+
clearer.join rescue nil
|
49
|
+
end
|
50
|
+
|
51
|
+
refute(@set.db.transaction_active?)
|
52
|
+
|
53
|
+
# XXX there's no solid way of knowing what'll be in here without inserting
|
54
|
+
# locks which will actually defeat the point of the test. Check the type,
|
55
|
+
# which will cause an execution and ensure we don't have a stale
|
56
|
+
# transaction.
|
57
|
+
assert_kind_of(Set, @set.to_set)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_enumerable_freebies
|
61
|
+
(0..10).each { |x| @set.add(x) }
|
62
|
+
real_set = @set.to_set
|
63
|
+
assert_kind_of(Set, real_set)
|
64
|
+
assert_equal(Set[*(0..10).to_a], real_set)
|
65
|
+
array = @set.to_a
|
66
|
+
assert_kind_of(Array, array)
|
67
|
+
assert_equal((0..10).to_a, array.sort)
|
68
|
+
|
69
|
+
t = (0..2).map { Thread.new { @set.to_set } }
|
70
|
+
t.each(&:join)
|
71
|
+
|
72
|
+
t = (0..2).map { Thread.new { @set.to_a } }
|
18
73
|
end
|
19
74
|
|
20
75
|
def test_semantics
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: palsy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Erik Hollensbe
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-06 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: sqlite3
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: minitest
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,23 +41,20 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rake
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: rdoc
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ~>
|
68
60
|
- !ruby/object:Gem::Version
|
@@ -70,7 +62,6 @@ dependencies:
|
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - ~>
|
76
67
|
- !ruby/object:Gem::Version
|
@@ -78,39 +69,34 @@ dependencies:
|
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: simplecov
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: guard-minitest
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - '>='
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - '>='
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: guard-rake
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
101
|
- - ~>
|
116
102
|
- !ruby/object:Gem::Version
|
@@ -118,7 +104,6 @@ dependencies:
|
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
108
|
- - ~>
|
124
109
|
- !ruby/object:Gem::Version
|
@@ -126,17 +111,15 @@ dependencies:
|
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: rb-fsevent
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
|
-
- -
|
115
|
+
- - '>='
|
132
116
|
- !ruby/object:Gem::Version
|
133
117
|
version: '0'
|
134
118
|
type: :development
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
|
-
- -
|
122
|
+
- - '>='
|
140
123
|
- !ruby/object:Gem::Version
|
141
124
|
version: '0'
|
142
125
|
description: An extremely simple marshalling persistence layer for SQLite based on
|
@@ -174,33 +157,26 @@ files:
|
|
174
157
|
- test/test_set.rb
|
175
158
|
homepage: ''
|
176
159
|
licenses: []
|
160
|
+
metadata: {}
|
177
161
|
post_install_message:
|
178
162
|
rdoc_options: []
|
179
163
|
require_paths:
|
180
164
|
- lib
|
181
165
|
required_ruby_version: !ruby/object:Gem::Requirement
|
182
|
-
none: false
|
183
166
|
requirements:
|
184
|
-
- -
|
167
|
+
- - '>='
|
185
168
|
- !ruby/object:Gem::Version
|
186
169
|
version: '0'
|
187
|
-
segments:
|
188
|
-
- 0
|
189
|
-
hash: 3156010217290385344
|
190
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
-
none: false
|
192
171
|
requirements:
|
193
|
-
- -
|
172
|
+
- - '>='
|
194
173
|
- !ruby/object:Gem::Version
|
195
174
|
version: '0'
|
196
|
-
segments:
|
197
|
-
- 0
|
198
|
-
hash: 3156010217290385344
|
199
175
|
requirements: []
|
200
176
|
rubyforge_project:
|
201
|
-
rubygems_version:
|
177
|
+
rubygems_version: 2.0.0
|
202
178
|
signing_key:
|
203
|
-
specification_version:
|
179
|
+
specification_version: 4
|
204
180
|
summary: An extremely simple marshalling persistence layer for SQLite based on perl's
|
205
181
|
tie()
|
206
182
|
test_files:
|