computable 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9d62c2956d0f777bd65d7fc308e035505a1a1912
4
+ data.tar.gz: d18de2360da33738fe19adee655774055472825e
5
+ SHA512:
6
+ metadata.gz: d18be4067d65ea266bcc2d461a595e50392af48686f48145c4578107cc1a84bf6a2255b1cfc0b3aaf999d9f6cd4947d88f7359f49791b9b990f0479cae331225
7
+ data.tar.gz: 0aabd0dac09732d5a000c68c051173cd4f1eb8485603e03d469d6568221eda485512e2974c95e536879a3926a430b805f52d96b45ea4742dbfc619e9727b758b
@@ -0,0 +1,2 @@
1
+ |��2_8��è��R���R����dx�/剿��rU�ȕ��?$W�{ɂ���_�B����ه��"�G�s�m������5JA��bt�>��#%���n����{��%!.;cn�m6*f]�.�W����i/?������W�`�~�f(+�}=��r��^�9�܅&���H>�Hƥ��9�>9� �i-IʦDz����K3���
2
+ l��h�y;�u���&��o�5��0!*��ORҚ��xK�w�x_
Binary file
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in computable.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Lars Kanis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Computable
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'computable'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install computable
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :gem => :build
4
+
5
+ task :test do
6
+ sh "ruby -w -W2 -I. -Ilib -e \"#{Dir["test/test_*.rb"].map{|f| "require '#{f}';"}.join}\" -- -v"
7
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'computable/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "computable"
8
+ spec.version = Computable::VERSION
9
+ spec.authors = ["Lars Kanis"]
10
+ spec.email = ["lars@greiz-reinsdorf.de"]
11
+ spec.description = %q{Define computation tasks with automatic caching and dependency tracking.}
12
+ spec.summary = %q{Define computation tasks with automatic caching and dependency tracking.}
13
+ spec.homepage = "https://github.com/larskanis/computable"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.4"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,202 @@
1
+ # -*- coding: UTF-8 -*-
2
+ require "computable/version"
3
+
4
+ class Computable
5
+ class Error < RuntimeError; end
6
+ class UndefinedValue < Error; end
7
+ class InvalidFormat < Error; end
8
+ class RecursionDetected < Error; end
9
+
10
+ # This is a special value to mark a variable to be computed.
11
+ Unknown = Object.new
12
+ class << Unknown
13
+ def inspect
14
+ "<Computable::Unknown>"
15
+ end
16
+ end
17
+
18
+ class Variable
19
+ attr_accessor :name, :calc_method, :used_for, :expired_from, :value, :value_calced, :count
20
+ def initialize(name, calc_method)
21
+ @name = name
22
+ @calc_method = calc_method
23
+ @used_for = {}
24
+ @expired_from = {}
25
+ @count = 0
26
+ @value = Unknown
27
+ end
28
+
29
+ def inspect
30
+ "<Variable #{name} used_for:#{used_for.keys} expired_from:#{expired_from.keys} has value:#{value==Unknown} value_calced:#{value_calced.inspect}>"
31
+ end
32
+
33
+ def calc!
34
+ self.count += 1
35
+ calc_method.call(self)
36
+ end
37
+
38
+ def expire_value
39
+ return if used_for.empty?
40
+
41
+ puts "expire #{inspect}" if Computable.computable_debug
42
+ used_for.each do |name2, v2|
43
+ if v2.value_calced && !v2.expired_from[name]
44
+ v2.expire_value
45
+ v2.expired_from[name] = self
46
+ end
47
+ end
48
+ end
49
+
50
+ def revoke_expire
51
+ return if used_for.empty?
52
+
53
+ puts "revoke expire #{inspect}" if Computable.computable_debug
54
+ used_for.each do |name2, v2|
55
+ if v2.value_calced && v2.expired_from.delete(name) && v2.expired_from.empty?
56
+ v2.revoke_expire
57
+ end
58
+ end
59
+ end
60
+
61
+ def recalc_value
62
+ return if !value_calced || expired_from.empty?
63
+
64
+ puts "recalc #{inspect}" if Computable.computable_debug
65
+ expired_from.each do |name2, v2|
66
+ v2.recalc_value
67
+ end
68
+
69
+ unless expired_from.empty?
70
+ recalced_value = self.calc!
71
+ if self.value == recalced_value
72
+ revoke_expire
73
+ else
74
+ self.value = recalced_value
75
+ used_for.clear
76
+ end
77
+ expired_from.clear
78
+ end
79
+ end
80
+ end
81
+
82
+ @@debug = false
83
+ def self.computable_debug=(v)
84
+ @@debug = v
85
+ end
86
+ def self.computable_debug
87
+ @@debug
88
+ end
89
+
90
+ def computable_display_dot(params={})
91
+ IO.popen("dot -Tpng | display -", "w") do |fd|
92
+ fd.puts computable_to_dot(params)
93
+ end
94
+ end
95
+
96
+ def computable_to_dot(params={})
97
+ rankdir = params.delete(:rankdir){ "TB" }
98
+ multiline = params.delete(:multiline){ true }
99
+ raise ArgumentError, "invalid params #{params.inspect}" unless params.empty?
100
+
101
+ dot = "digraph #{self.class.name.inspect} {\n"
102
+ dot << "graph [ dpi = 45, rankdir=#{rankdir} ];\n"
103
+ @variables.each do |name, v|
104
+ col = case
105
+ when !v.value_calced then "color = red,"
106
+ when !v.used_for.empty? then "color = green,"
107
+ else "color = blue,"
108
+ end
109
+ label = if multiline
110
+ "#{name.to_s.gsub("_","\n")}\n(#{v.count})"
111
+ else
112
+ "#{name.to_s} (#{v.count})"
113
+ end
114
+ dot << "#{name.to_s.inspect} [#{col} label=#{label.inspect}];\n"
115
+ v.used_for.each do |name2, v2|
116
+ dot << "#{name.to_s.inspect} -> #{name2.to_s.inspect};\n"
117
+ end
118
+ end
119
+ dot << "}\n"
120
+ end
121
+
122
+ def initialize
123
+ @variables = {}
124
+ @caller = nil
125
+ end
126
+
127
+
128
+ def self.verify_format(name, value, format)
129
+ if format && value!=Unknown && !(format === value)
130
+ raise InvalidFormat, "variable '#{name}': value #{value.inspect} is not in format #{format.inspect}"
131
+ end
132
+ end
133
+
134
+ def self.calc_value name, format=nil, params={}, &block
135
+ freeze = params.delete(:freeze){ true }
136
+ raise ArgumentError, "invalid params #{params.inspect}" unless params.empty?
137
+
138
+ calc_method_id = "calc_#{name}".intern
139
+ define_method(calc_method_id, &block)
140
+
141
+ calc_method2_id = "calc_#{name}_with_tracking".intern
142
+ define_method(calc_method2_id) do |v|
143
+ begin
144
+ v.value_calced = true
145
+ @caller, old_caller = v, @caller
146
+ begin
147
+ puts "do calc #{v.inspect}" if @@debug
148
+ res = send(calc_method_id)
149
+ Computable.verify_format(name, res, format)
150
+ res.freeze if freeze
151
+ res
152
+ ensure
153
+ @caller = old_caller
154
+ end
155
+ end
156
+ end
157
+
158
+ define_method("#{name}=") do |value|
159
+ Computable.verify_format(name, value, format)
160
+ v = @variables[name]
161
+ puts "set #{name}: #{value.inspect} #{v.inspect}" if @@debug
162
+ v = @variables[name] = Variable.new(name, method(calc_method2_id)) unless v
163
+
164
+ unless v.value == value
165
+ v.expire_value
166
+ v.expired_from.clear
167
+ v.used_for.clear
168
+ value.freeze if freeze
169
+ v.value = value
170
+ end
171
+ v.value_calced = false
172
+ end
173
+
174
+ define_method(name) do
175
+ v = @variables[name]
176
+ puts "called #{name} #{v.inspect}" if @@debug
177
+ v = @variables[name] = Variable.new(name, method(calc_method2_id)) unless v
178
+
179
+ if @caller
180
+ v2 = v.used_for[@caller.name]
181
+ if v2
182
+ if v.value==Unknown && v2.value==Unknown && v.value_calced && v2.value_calced
183
+ raise RecursionDetected, "#{v2.name} depends on #{name}, but #{name} could not be computed without #{v2.name}"
184
+ end
185
+ else
186
+ v.used_for[@caller.name] = @caller
187
+ end
188
+ end
189
+
190
+ v.recalc_value
191
+
192
+ v.value = v.calc! if v.value==Unknown
193
+ v.value
194
+ end
195
+ end
196
+
197
+ def self.input_value name, format=nil, params={}
198
+ calc_value name, format, params do
199
+ raise UndefinedValue, "input variable '#{name}' is not assigned"
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,3 @@
1
+ class Computable
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,104 @@
1
+ require 'minitest/autorun'
2
+ require 'computable'
3
+
4
+ class TestCandy < MiniTest::Unit::TestCase
5
+ class MyBuilder < Computable
6
+ attr_reader :counters
7
+
8
+ def initialize *args
9
+ super
10
+ @counters = {}
11
+ end
12
+
13
+ def self.counted_value name, format=nil, params={}, &block
14
+ define_method "#{name}_counted", &block
15
+ calc_value name, format do
16
+ @counters[name] ||= 0
17
+ @counters[name] += 1
18
+ send "#{name}_counted"
19
+ end
20
+ end
21
+
22
+ input_value :il, String
23
+ input_value :ir, String
24
+
25
+ counted_value :top do
26
+ i = il + ir
27
+ p = i.length / 2
28
+ i[p] = i[p].upcase
29
+ i
30
+ end
31
+
32
+ counted_value :l0 do
33
+ i = top.dup
34
+ p = 0
35
+ i[p] = i[p].upcase
36
+ i
37
+ end
38
+ counted_value :l1 do
39
+ i = l0.dup
40
+ p = 1
41
+ i[p] = i[p].upcase
42
+ i
43
+ end
44
+
45
+ counted_value :r0 do
46
+ i = top.dup
47
+ p = -1
48
+ i[p] = i[p].upcase
49
+ i
50
+ end
51
+ counted_value :r1 do
52
+ i = r0.dup
53
+ p = -2
54
+ i[p] = i[p].upcase
55
+ i
56
+ end
57
+
58
+ counted_value :bot do
59
+ l1 + r1
60
+ end
61
+
62
+ counted_value :fl do
63
+ i = bot.dup
64
+ p = (i.length-1) / 2
65
+ i[p] = i[p].upcase
66
+ i
67
+ end
68
+
69
+ counted_value :fr do
70
+ i = bot.dup
71
+ p = i.length / 2
72
+ i[p] = i[p].upcase
73
+ i
74
+ end
75
+ end
76
+
77
+ def setup
78
+ @b = MyBuilder.new
79
+ @b.il, @b.ir = "abc", "def"
80
+ end
81
+
82
+ def teardown
83
+ # @b.computable_display_dot
84
+ end
85
+
86
+ def test_full_calc
87
+ assert_equal "ABcDeFabcDEF", @b.fl
88
+ assert_equal "ABcDefAbcDEF", @b.fr
89
+ assert_equal [1]*8, @b.counters.values_at(:top, :l0, :r0, :l1, :r1, :bot, :fl, :fr)
90
+
91
+ @b.il = "abC"
92
+ assert_equal "ABCDeFabCDEF", @b.fl
93
+ assert_equal "ABCDefAbCDEF", @b.fr
94
+ assert_equal [2]*8, @b.counters.values_at(:top, :l0, :r0, :l1, :r1, :bot, :fl, :fr)
95
+ end
96
+
97
+ def test_partial_1
98
+ @b.fl
99
+ @b.il = "Abc"
100
+ assert_equal [1,1,1,1,1,1,1,nil], @b.counters.values_at(:top, :l0, :r0, :l1, :r1, :bot, :fl, :fr)
101
+ @b.fr
102
+ assert_equal [2,2,2,1,2,2,1,1], @b.counters.values_at(:top, :l0, :r0, :l1, :r1, :bot, :fl, :fr)
103
+ end
104
+ end
@@ -0,0 +1,68 @@
1
+ require 'minitest/autorun'
2
+ require 'computable'
3
+
4
+ class TestFormat < MiniTest::Unit::TestCase
5
+ class MyBuilder < Computable
6
+ def self.verify_uniq_array(a)
7
+ a.uniq.length == a.length
8
+ end
9
+
10
+ input_value :any
11
+ input_value :integer, Integer
12
+ input_value :string4, /\A.{4}\z/
13
+ input_value :uniq_array, method(:verify_uniq_array).to_proc
14
+
15
+ calc_value :sqrt, Numeric do
16
+ Math.sqrt(integer) if integer>=0
17
+ end
18
+ end
19
+
20
+ def setup
21
+ @b = MyBuilder.new
22
+ end
23
+
24
+ def teardown
25
+ # @b.computable_display_dot
26
+ end
27
+
28
+ def test_any
29
+ @b.any = "string"
30
+ @b.any = []
31
+ @b.any = 123
32
+ end
33
+
34
+ def test_check_by_class
35
+ assert_raises(Computable::UndefinedValue){ @b.integer }
36
+ @b.integer = 3
37
+
38
+ assert_raises(Computable::InvalidFormat){ @b.integer = :test }
39
+
40
+ assert_equal 3, @b.integer
41
+ end
42
+
43
+ def test_check_by_regexp
44
+ @b.string4 = "abcd"
45
+ assert_equal "abcd", @b.string4
46
+
47
+ assert_raises(Computable::InvalidFormat){ @b.string4 = 4 }
48
+ assert_raises(Computable::InvalidFormat){ @b.string4 = "abcde" }
49
+
50
+ @b.string4 = :abcd
51
+ assert_equal :abcd, @b.string4
52
+ end
53
+
54
+ def test_check_by_method
55
+ @b.uniq_array = %w[ a b c d ]
56
+ assert_equal %w[ a b c d ], @b.uniq_array
57
+
58
+ assert_raises(Computable::InvalidFormat){ @b.uniq_array = %w[ a b c a ] }
59
+ end
60
+
61
+ def test_check_calc_value
62
+ @b.integer = 4
63
+ assert_equal 2, @b.sqrt
64
+
65
+ @b.integer = -4
66
+ assert_raises(Computable::InvalidFormat){ @b.sqrt }
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ require 'minitest/autorun'
2
+ require 'computable'
3
+
4
+ class TestFreeze < MiniTest::Unit::TestCase
5
+ class MyBuilder < Computable
6
+ input_value :no_freeze1, String, freeze: false
7
+ calc_value :no_freeze2, String, freeze: false do
8
+ no_freeze1 * 2
9
+ end
10
+
11
+ input_value :freeze1, String
12
+ calc_value :freeze2, String do
13
+ freeze1 * 2
14
+ end
15
+ end
16
+
17
+ def setup
18
+ @b = MyBuilder.new
19
+ end
20
+
21
+ def teardown
22
+ # @b.computable_display_dot
23
+ end
24
+
25
+ def test_no_freeze
26
+ @b.no_freeze1 = "abc"
27
+ assert !@b.no_freeze1.frozen?, "shouldn't be frozen"
28
+ assert !@b.no_freeze2.frozen?, "shouldn't be frozen"
29
+ end
30
+
31
+ def test_freeze
32
+ @b.freeze1 = "def"
33
+ assert @b.freeze1.frozen?, "should be frozen"
34
+ assert @b.freeze2.frozen?, "should be frozen"
35
+ end
36
+ end
@@ -0,0 +1,48 @@
1
+ require 'minitest/autorun'
2
+ require 'computable'
3
+
4
+ class TestInputValue < MiniTest::Unit::TestCase
5
+ class MyBuilder < Computable
6
+ input_value :i
7
+
8
+ calc_value :o do
9
+ i * 2
10
+ end
11
+ end
12
+
13
+ def setup
14
+ @b = MyBuilder.new
15
+ end
16
+
17
+ def teardown
18
+ # @b.computable_display_dot
19
+ end
20
+
21
+ def test_undefined_input
22
+ assert_raises(Computable::UndefinedValue){ @b.i }
23
+ assert_raises(Computable::UndefinedValue){ @b.o }
24
+
25
+ @b.i = 3
26
+ assert_equal 3, @b.i
27
+ assert_equal 6, @b.o
28
+
29
+ @b.i = Computable::Unknown
30
+ assert_raises(Computable::UndefinedValue){ @b.o }
31
+ assert_raises(Computable::UndefinedValue){ @b.i }
32
+
33
+ @b.i = 3
34
+ assert_equal 6, @b.o
35
+ assert_equal 3, @b.i
36
+ end
37
+
38
+ def test_define_calc_value
39
+ @b.o = 5
40
+ assert_equal 5, @b.o
41
+
42
+ @b.o = Computable::Unknown
43
+ assert_raises(Computable::UndefinedValue){ @b.o }
44
+
45
+ @b.i = 3
46
+ assert_equal 6, @b.o
47
+ end
48
+ end
@@ -0,0 +1,36 @@
1
+ require 'minitest/autorun'
2
+ require 'computable'
3
+
4
+ class TestRecursionDetection < MiniTest::Unit::TestCase
5
+ class MyBuilder < Computable
6
+ calc_value :recursion1 do
7
+ recursion1
8
+ end
9
+
10
+ calc_value :recursion2 do
11
+ recursion3
12
+ end
13
+ calc_value :recursion3 do
14
+ recursion4
15
+ end
16
+ calc_value :recursion4 do
17
+ recursion2
18
+ end
19
+ end
20
+
21
+ def setup
22
+ @b = MyBuilder.new
23
+ end
24
+
25
+ def teardown
26
+ # @b.computable_display_dot
27
+ end
28
+
29
+ def test_recursion1
30
+ assert_raises(Computable::RecursionDetected){ @b.recursion1 }
31
+ end
32
+
33
+ def test_recursion2
34
+ assert_raises(Computable::RecursionDetected){ @b.recursion2 }
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: computable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lars Kanis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDaDCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADA9MQ4wDAYDVQQDDAVrYW5p
14
+ czEXMBUGCgmSJomT8ixkARkWB2NvbWNhcmQxEjAQBgoJkiaJk/IsZAEZFgJkZTAe
15
+ Fw0xMzAyMjYwODQ1NTlaFw0xNDAyMjYwODQ1NTlaMD0xDjAMBgNVBAMMBWthbmlz
16
+ MRcwFQYKCZImiZPyLGQBGRYHY29tY2FyZDESMBAGCgmSJomT8ixkARkWAmRlMIIB
17
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApop+rNmg35bzRugZ21VMGqI6
18
+ HGzPLO4VHYncWn/xmgPU/ZMcZdfj6MzIaZJ/czXyt4eHpBk1r8QOV3gBXnRXEjVW
19
+ 9xi+EdVOkTV2/AVFKThcbTAQGiF/bT1n2M+B1GTybRzMg6hyhOJeGPqIhLfJEpxn
20
+ lJi4+ENAVT4MpqHEAGB8yFoPC0GqiOHQsdHxQV3P3c2OZqG+yJey74QtwA2tLcLn
21
+ Q53c63+VLGsOjODl1yPn/2ejyq8qWu6ahfTxiIlSar2UbwtaQGBDFdb2CXgEufXT
22
+ L7oaPxlmj+Q2oLOfOnInd2Oxop59HoJCQPsg8f921J43NCQGA8VHK6paxIRDLQID
23
+ AQABo3MwcTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUvgTdT7fe
24
+ x17ugO3IOsjEJwW7KP4wGwYDVR0RBBQwEoEQa2FuaXNAY29tY2FyZC5kZTAbBgNV
25
+ HRIEFDASgRBrYW5pc0Bjb21jYXJkLmRlMA0GCSqGSIb3DQEBBQUAA4IBAQCa3ThZ
26
+ 9qjyuFXe0kN4IwgHTTSqob3zPOyXAxAq1k65w1/hI/6e4HxCSH7Ds+dKj/xhScEu
27
+ K5gaya1D69Fo+JTnzLvuSt2X8+mEHclduC9j++oSGc+szd7LKdeEQ7J4RefJjhD+
28
+ vWI6lqglL4PijN0nOWtm0ygzXEELDcGYpb2WJ++KKNVLIU6pkiWpZUmGcFB7NclV
29
+ I64m9iNdgWnDwedgUlqSMfVCUUB9S1Y5jI+doxYloPvIB6+6VsI4cmN2LcK0rQO6
30
+ N3pmmsS0N5772vAmRMyNl8PV1OzCLIMhgPgdeLpfU7LUSYWj67q5VuyjAaH5h68g
31
+ MlGgwc//cCsBG8sa
32
+ -----END CERTIFICATE-----
33
+ date: 2014-02-12 00:00:00.000000000 Z
34
+ dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: bundler
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.4'
42
+ type: :development
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.4'
49
+ - !ruby/object:Gem::Dependency
50
+ name: rake
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ description: Define computation tasks with automatic caching and dependency tracking.
64
+ email:
65
+ - lars@greiz-reinsdorf.de
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - ".gitignore"
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - computable.gemspec
76
+ - lib/computable.rb
77
+ - lib/computable/version.rb
78
+ - test/test_candy.rb
79
+ - test/test_format.rb
80
+ - test/test_freeze.rb
81
+ - test/test_input_value.rb
82
+ - test/test_recursion_detection.rb
83
+ homepage: https://github.com/larskanis/computable
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.2.0
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Define computation tasks with automatic caching and dependency tracking.
107
+ test_files:
108
+ - test/test_candy.rb
109
+ - test/test_format.rb
110
+ - test/test_freeze.rb
111
+ - test/test_input_value.rb
112
+ - test/test_recursion_detection.rb
@@ -0,0 +1 @@
1
+ n�BӪ��c����5�\F*�,6����Ti#$N3#Tt�m������9\��P5"��))ƈ��Q�W���Z1;&��#Zu�I'SR�%]���Y 㧱�1'E��U�����=�J���i��>����D��R�u�hֽ�%�ZL����� g��2�� %�”6�v;F��}�\ue��]^>�"D�4�9S�ɺ�ƺOKC`/H�ݙ�k���)s�TX��Ҽk�ݢÂ�����ׂT��o��kK��