vex 0.2

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.
Files changed (114) hide show
  1. data/Manifest +112 -0
  2. data/Rakefile +53 -0
  3. data/VERSION +1 -0
  4. data/config/README +2 -0
  5. data/config/dependencies.rb +10 -0
  6. data/config/gem.yml +7 -0
  7. data/init.rb +36 -0
  8. data/lib/nokogiri/nokogiri_ext.rb +96 -0
  9. data/lib/vex.rb +5 -0
  10. data/lib/vex/action_controller.rb +4 -0
  11. data/lib/vex/action_controller/verify_action.rb +97 -0
  12. data/lib/vex/action_controller/whitelisted_actions.rb +45 -0
  13. data/lib/vex/active_record.rb +3 -0
  14. data/lib/vex/active_record/__init__.rb +0 -0
  15. data/lib/vex/active_record/advisory_lock.rb +11 -0
  16. data/lib/vex/active_record/advisory_lock/mysql_adapter.rb +16 -0
  17. data/lib/vex/active_record/advisory_lock/sqlite_adapter.rb +78 -0
  18. data/lib/vex/active_record/belongs_to_many.rb +143 -0
  19. data/lib/vex/active_record/find_by_extension.rb +70 -0
  20. data/lib/vex/active_record/gem.rb +8 -0
  21. data/lib/vex/active_record/lite_table.rb +139 -0
  22. data/lib/vex/active_record/lite_view.rb +140 -0
  23. data/lib/vex/active_record/mass_load.rb +65 -0
  24. data/lib/vex/active_record/mysql_backup.rb +21 -0
  25. data/lib/vex/active_record/plugins/default_value_for/LICENSE.TXT +19 -0
  26. data/lib/vex/active_record/plugins/default_value_for/README.rdoc +421 -0
  27. data/lib/vex/active_record/plugins/default_value_for/Rakefile +6 -0
  28. data/lib/vex/active_record/plugins/default_value_for/init.rb +91 -0
  29. data/lib/vex/active_record/plugins/default_value_for/test.rb +279 -0
  30. data/lib/vex/active_record/plugins/default_value_for/test.sqlite3 +0 -0
  31. data/lib/vex/active_record/random_id.rb +56 -0
  32. data/lib/vex/active_record/resolver.rb +49 -0
  33. data/lib/vex/active_record/serialize_hash.rb +125 -0
  34. data/lib/vex/active_record/to_html.rb +53 -0
  35. data/lib/vex/active_record/validate.rb +76 -0
  36. data/lib/vex/active_record/validation_error_ext.rb +68 -0
  37. data/lib/vex/base.rb +2 -0
  38. data/lib/vex/base/app.rb +75 -0
  39. data/lib/vex/base/array/at_random.rb +17 -0
  40. data/lib/vex/base/array/cross.rb +26 -0
  41. data/lib/vex/base/array/each_batch.rb +32 -0
  42. data/lib/vex/base/array/parallel_map.rb +98 -0
  43. data/lib/vex/base/deprecation.rb +41 -0
  44. data/lib/vex/base/enumerable/deep.rb +95 -0
  45. data/lib/vex/base/enumerable/enumerable_ext.rb +59 -0
  46. data/lib/vex/base/enumerable/progress.rb +71 -0
  47. data/lib/vex/base/filesystem/fast_copy.rb +61 -0
  48. data/lib/vex/base/filesystem/grep.rb +34 -0
  49. data/lib/vex/base/filesystem/lock.rb +43 -0
  50. data/lib/vex/base/filesystem/lock.rb.test.lck +0 -0
  51. data/lib/vex/base/filesystem/lock.rb.test.pid +1 -0
  52. data/lib/vex/base/filesystem/make_dirs.rb +94 -0
  53. data/lib/vex/base/filesystem/parse_filename.rb +36 -0
  54. data/lib/vex/base/filesystem/tmp_file.rb +87 -0
  55. data/lib/vex/base/filesystem/write.rb +43 -0
  56. data/lib/vex/base/hash/compact.rb +38 -0
  57. data/lib/vex/base/hash/cross.rb +117 -0
  58. data/lib/vex/base/hash/easy_access.rb +141 -0
  59. data/lib/vex/base/hash/ensure_keys.rb +18 -0
  60. data/lib/vex/base/hash/extract.rb +71 -0
  61. data/lib/vex/base/hash/extras.rb +62 -0
  62. data/lib/vex/base/hash/inspect.rb +17 -0
  63. data/lib/vex/base/hash/simple_access_methods.rb +74 -0
  64. data/lib/vex/base/invalid_argument/invalid_argument.rb +97 -0
  65. data/lib/vex/base/local_conf.rb +35 -0
  66. data/lib/vex/base/net/http_ext.rb +227 -0
  67. data/lib/vex/base/net/socket_ext.rb +43 -0
  68. data/lib/vex/base/object/insp.rb +123 -0
  69. data/lib/vex/base/object/multiple_attributes.rb +58 -0
  70. data/lib/vex/base/object/singleton_methods.rb +23 -0
  71. data/lib/vex/base/object/with_benchmark.rb +110 -0
  72. data/lib/vex/base/range_array.rb +40 -0
  73. data/lib/vex/base/range_ext.rb +28 -0
  74. data/lib/vex/base/safe_token.rb +156 -0
  75. data/lib/vex/base/string/string_ext.rb +136 -0
  76. data/lib/vex/base/thread/deferred.rb +52 -0
  77. data/lib/vex/base/thread/sleep.rb +11 -0
  78. data/lib/vex/base/time/date_ext.rb +12 -0
  79. data/lib/vex/boot.rb +40 -0
  80. data/lib/vex/boot/array.rb +22 -0
  81. data/lib/vex/boot/blank.rb +41 -0
  82. data/lib/vex/boot/string.rb +60 -0
  83. data/migration/create_request_log.rb +28 -0
  84. data/r.rb +35 -0
  85. data/script/console +19 -0
  86. data/script/rebuild +7 -0
  87. data/tasks/echoe.rake +52 -0
  88. data/tasks/validate_db.rake +14 -0
  89. data/test/ar.rb +30 -0
  90. data/test/auto.rb +31 -0
  91. data/test/base-tests/local_conf.rb +25 -0
  92. data/test/base.rb +2 -0
  93. data/test/boot.rb +3 -0
  94. data/test/config/local.defaults.yml +4 -0
  95. data/test/config/local.yml +8 -0
  96. data/test/test.sqlite3 +0 -0
  97. data/test/test.sqlite3.Class#create.lck +0 -0
  98. data/test/test.sqlite3.Class#create.lck.lck +0 -0
  99. data/test/test.sqlite3.Class#create.lck.pid +1 -0
  100. data/test/test.sqlite3.Class#create.pid +1 -0
  101. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck +0 -0
  102. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.lck +0 -0
  103. data/test/test.sqlite3.LiteView.make.holders__view_dummy.lck.pid +1 -0
  104. data/test/test.sqlite3.LiteView.make.holders__view_dummy.pid +1 -0
  105. data/test/test.sqlite3.vex.lck +0 -0
  106. data/test/test_helper.rb +49 -0
  107. data/test/tmp/copy.dat +1 -0
  108. data/test/tmp/lock.sqlite3 +0 -0
  109. data/test/tmp/lock.sqlite3.etest.lck +0 -0
  110. data/test/tmp/lock.sqlite3.etest.pid +1 -0
  111. data/test/tmp/somedata.dat +61 -0
  112. data/vex.gemspec +49 -0
  113. data/vex.tmproj +186 -0
  114. metadata +305 -0
@@ -0,0 +1,32 @@
1
+ module Array::EachBatch
2
+ def each_batch(batch_size = 1000, &block)
3
+ raise "Invalid parameter #{batch_size.inspect}, must be a Fixnum" unless batch_size.is_a?(Fixnum)
4
+
5
+ data = dup
6
+ begin
7
+ batch = data.slice!(0..(batch_size-1))
8
+ yield batch
9
+ end until data.empty?
10
+ self
11
+ end
12
+ end
13
+
14
+ Array.send :include, Array::EachBatch
15
+
16
+ module Array::Cross::Etest
17
+ def test_each_batch
18
+ r = []
19
+ [1,2,3,4,5,6,7,8,9].each_batch 3 do |batch|
20
+ r << batch
21
+ end
22
+
23
+ assert_equal( [[1,2,3],[4,5,6],[7,8,9]], r)
24
+
25
+ r = []
26
+ [1,2,3,4,5,6,7].each_batch 3 do |batch|
27
+ r << batch
28
+ end
29
+
30
+ assert_equal( [[1,2,3],[4,5,6],[7]], r)
31
+ end
32
+ end if VEX_TEST == "base"
@@ -0,0 +1,98 @@
1
+ require "timeout"
2
+
3
+ #
4
+ # a simple (really really simple) map-in-parallel multithreaded mapper.
5
+ module Array::ParallelMap
6
+
7
+ def self.timeout(opts, &block)
8
+ return yield unless opts[:timeout]
9
+ begin
10
+ Timeout.timeout(opts[:timeout], &block)
11
+ rescue Timeout::Error
12
+ end
13
+ end
14
+
15
+ def peach_with_index(opts = {}, &block)
16
+ return [] if empty?
17
+
18
+ threads = []
19
+
20
+ each_with_index do |data, index|
21
+ threads << Thread.new {
22
+ Array::ParallelMap.timeout(opts) { yield(data, index) }
23
+ }
24
+ end
25
+
26
+ threads.each do |thread| thread.join end
27
+ self
28
+ end
29
+
30
+ def peach(opts = {}, &block)
31
+ peach_with_index(opts) do |data, index|
32
+ yield(data)
33
+ end
34
+ end
35
+
36
+ def pmap(opts = {}, &block)
37
+ semaphore = Mutex.new
38
+
39
+ results = []
40
+
41
+ peach_with_index(opts) do |data, index|
42
+ r = yield(data)
43
+ semaphore.synchronize { results[index] = r }
44
+ end
45
+
46
+ results
47
+ end
48
+ end
49
+
50
+ Array.send :include, Array::ParallelMap
51
+
52
+ module Array::ParallelMap::Etest
53
+ MAX = 1000
54
+
55
+ def calculate(repeat, method)
56
+ (1..repeat).to_a.send(method) do |p|
57
+ (1..MAX).inject(0) do |sum, i|
58
+ sum + p * i
59
+ end
60
+ end
61
+ end
62
+
63
+ def calculate_serial(repeat)
64
+ calculate(repeat, :map)
65
+ end
66
+
67
+ def calculate_parallel(repeat)
68
+ calculate(repeat, :pmap)
69
+ end
70
+
71
+ def test_pmap
72
+ serial = calculate_serial(4)
73
+ parallel = calculate_parallel(4)
74
+ assert_equal(serial, parallel)
75
+ end
76
+
77
+ def test_peach
78
+ semaphore = Mutex.new
79
+
80
+ results = []
81
+
82
+ array = [ 1, 2, 3, 4]
83
+ r = array.peach do |p|
84
+ semaphore.synchronize { results << p }
85
+ end
86
+ assert_equal(array, results.sort)
87
+ assert_equal(array, r)
88
+ end
89
+
90
+ def test_pmap_timeout
91
+ r = [1, 2].pmap(:timeout => 0.1) do |p|
92
+ sleep 0.2
93
+ p * p
94
+ end
95
+
96
+ assert_equal([], r)
97
+ end
98
+ end if VEX_TEST == "base"
@@ -0,0 +1,41 @@
1
+ #
2
+ # short inspect method on all objects.
3
+ #
4
+ # "abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop".insp
5
+ # -> "abcdefghijklmnopabcdefghijk..."
6
+ # Model.find(1).insp
7
+ # -> "<Model#1>"
8
+
9
+ module Deprecation
10
+ def self.quiet
11
+ @quiet = true
12
+ yield
13
+ ensure
14
+ @quiet = false
15
+ end
16
+
17
+ def self.seen
18
+ @seen ||= {}
19
+ end
20
+
21
+ def self.report(msg, instead=nil)
22
+ return if App.env == "production"
23
+ return if @quiet
24
+ return if seen[[msg, instead]]
25
+
26
+ seen[[msg, instead]] = true
27
+
28
+ msg = "#{msg} is deprecated"
29
+ msg += "; use #{instead} instead" if instead
30
+ msg += ". From\n\t" + caller[1,4].join("\n\t")
31
+ STDERR.puts msg
32
+ end
33
+ end
34
+
35
+ module Deprecation::Etest
36
+ def test_report
37
+ STDERR.expects(:puts)
38
+ Deprecation.report "Hey"
39
+ Deprecation.report "Hey"
40
+ end
41
+ end if VEX_TEST == "base"
@@ -0,0 +1,95 @@
1
+ module Deep
2
+ KEYS = 0x01
3
+ VALUES = 0x02
4
+
5
+ #
6
+ # deep mapping
7
+ def self.map(o, mode, &block)
8
+ case o
9
+ when Hash
10
+ o.inject({}) do |hash, (k,v)|
11
+ k = yield(k) if (mode & KEYS) != 0
12
+ v = map(v, mode, &block)
13
+ hash.update k => v
14
+ hash
15
+ end
16
+ when Array
17
+ if mode & VALUES
18
+ o.map do |v|
19
+ map(v, mode, &block)
20
+ end
21
+ else
22
+ o.dup
23
+ end
24
+ else
25
+ if (mode & VALUES) != 0
26
+ yield o
27
+ else
28
+ o
29
+ end
30
+ end
31
+ end
32
+
33
+ #
34
+ # deep reject
35
+ def self.reject(o, mode, &block)
36
+ case o
37
+ when Hash
38
+ o.inject({}) do |hash, (k,v)|
39
+ next hash if (mode & KEYS) && yield(k)
40
+ v = reject v, mode, &block
41
+ next hash if (mode & VALUES) && yield(v)
42
+ hash.update k => v
43
+ hash
44
+ end
45
+ when Array
46
+ if mode & VALUES
47
+ o.inject([]) do |r, v|
48
+ v = reject(v, mode, &block)
49
+ r << v unless yield(v)
50
+ end
51
+ else
52
+ o.dup
53
+ end
54
+ else
55
+ o
56
+ end
57
+ end
58
+ end
59
+
60
+ module Enumerable
61
+ KEYS = Deep::KEYS
62
+ VALUES = Deep::VALUES
63
+
64
+ def reject_blanks
65
+ Deep.reject(self, KEYS | VALUES) do |s|
66
+ s.blank?
67
+ end
68
+ end
69
+
70
+ def camelize
71
+ Deep.map(self, KEYS) do |s|
72
+ s.to_s.camelize
73
+ end
74
+ end
75
+ end
76
+
77
+ module Deep::Etest
78
+ def test_reject_blanks
79
+ h = { :a => "a", :b_c => { :d => nil, :video_test => "video_test "}, "x" => nil, "y" => [] }
80
+ expected = { :a=>"a", :b_c => { :video_test => "video_test " }}
81
+ assert_equal(expected, h.reject_blanks)
82
+ end
83
+
84
+ def test_camelized_keys
85
+ h = { :a => "a", :b_c => { :d => "dd", :video_test => "video_test "}}
86
+ expected = { "A"=>"a", "BC" => { "VideoTest" => "video_test ", "D" => "dd" }}
87
+ assert_equal(expected, h.camelize)
88
+ end
89
+
90
+ def test_missin_block
91
+ assert_raise(LocalJumpError) {
92
+ Deep.reject(%w(1 2), 3)
93
+ }
94
+ end
95
+ end if VEX_TEST == "base"
@@ -0,0 +1,59 @@
1
+ module Enumerable
2
+ def any_not?(&block)
3
+ not all? { |e| yield(e) }
4
+ end
5
+
6
+ def none?(&block)
7
+ not any? { |e| yield(e) }
8
+ end
9
+
10
+ def stable_sort_by
11
+ # NOTE: if soort_by wouldn't enumerate the array members from
12
+ # the beginning this would fail.
13
+ i=0
14
+ sort_by { |x| [ yield(x), i+=1 ] }
15
+ end
16
+
17
+ def hmap(&block)
18
+ inject({}) { |hash, obj| hash[obj] = yield(obj); hash }
19
+ end
20
+ end
21
+
22
+ module Enumerable::Etest
23
+ def test_stable_sort_by
24
+ data = [[1, 'b'], [1, 'c'], [0, 'b'], [0, 'a']]
25
+
26
+ # This might or might not fail, but is not guaranteed to do so:
27
+ # assert_equal [[0, 'b'], [0, 'a'], [ 1, 'b'], [1, 'c']], data.stable_sort_by { |t| t[0] }
28
+ assert_equal [[0, 'b'], [0, 'a'], [ 1, 'b'], [1, 'c']], data.stable_sort_by { |t| t[0] }
29
+ end
30
+
31
+ def test_any_none(&block)
32
+ assert_equal(false, [ 1, 2, true, false ].any?(&:nil?))
33
+ assert_equal(true, [ 1, 2, true, false ].none?(&:nil?))
34
+ assert_equal(true, [ 1, 2, true, false, nil ].any?(&:nil?))
35
+ assert_equal(false, [ 1, 2, true, false, nil ].none?(&:nil?))
36
+
37
+ assert_equal(true, [ nil ].any?(&:nil?))
38
+ assert_equal(false, [ 1 ].any?(&:nil?))
39
+ assert_equal(false, [ ].any?(&:nil?))
40
+
41
+ assert_equal(false, [ nil ].none?(&:nil?))
42
+ assert_equal(true, [ 1 ].none?(&:nil?))
43
+ assert_equal(true, [ ].none?(&:nil?))
44
+ end
45
+
46
+ def test_any_not_all(&block)
47
+ assert_equal(true, [ 1, 2, true, false ].any_not?(&:nil?))
48
+ assert_equal(true, [ 1, 2, nil ].any_not?(&:nil?))
49
+ assert_equal(false, [ nil ].any_not?(&:nil?))
50
+ assert_equal(true, [ 1 ].any_not?(&:nil?))
51
+ assert_equal(false, [ ].any_not?(&:nil?))
52
+ end
53
+
54
+ def test_hmap
55
+ h = %w(1 2 3)
56
+
57
+ assert_equal({ "1" => 1, "2" => 4, "3" => 9}, h.hmap do |line| line.to_i * line.to_i end)
58
+ end
59
+ end if VEX_TEST == "base"
@@ -0,0 +1,71 @@
1
+ module Enumerable
2
+ class Progress
3
+ def initialize(base, count=nil)
4
+ @base = base
5
+ @idx = 0
6
+ @count = count
7
+ @count ||= base.is_a?(Range) ? (base.max - base.min + 1) : length
8
+ end
9
+
10
+ def method_missing(sym, *args)
11
+ return @base.send(sym, *args) unless block_given?
12
+
13
+ r = @base.send sym, *args do |*args|
14
+ begin
15
+ yield *args
16
+ ensure
17
+ @idx += 1
18
+ on_progress(@idx, @count)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ class ConsoleProgress < Progress
25
+ def initialize(base, count=nil)
26
+ @start, @last = Time.now, nil
27
+ super
28
+ end
29
+
30
+ private
31
+
32
+ def print_line(s)
33
+ print s
34
+ end
35
+
36
+ def on_progress(idx, count)
37
+ if idx == count
38
+ print_line("\r#{"%.1f%%" % 100}#{" " * 40}\n")
39
+ return
40
+ end
41
+
42
+ now = Time.now
43
+ return if @last && now - @last <= 1
44
+
45
+ @last = now
46
+ span = @last - @start
47
+ remaining = ((count * 1.0 / idx) - 1) * span
48
+
49
+ print_line "\r#{"%.1f%%" % ((100.0 * idx) / count)}\t#{" %.1f secs remaining " % remaining}"
50
+ end
51
+ end
52
+
53
+ class Progress
54
+ IMPLEMENTATIONS = {
55
+ :console => ConsoleProgress
56
+ }
57
+ end
58
+
59
+ def with_progress(impl = :console)
60
+ Progress::IMPLEMENTATIONS[impl].new(self)
61
+ end
62
+ end
63
+
64
+ module Enumerable::Etest
65
+ def test_with_progress
66
+ Enumerable::ConsoleProgress.any_instance.stubs(:print_line).returns(nil)
67
+
68
+ r = [ 1, 2 ].with_progress.map do |s| s * s end
69
+ assert_equal( [ 1, 4], r)
70
+ end
71
+ end if VEX_TEST == "base"
@@ -0,0 +1,61 @@
1
+ module FileUtils::FastCopy
2
+ # fast_copy a file: This hardlinks the source file to the destfile,
3
+ # if possible. src must refer to a file; dest must refer to a file
4
+ # or not exist at all.
5
+ def fast_copy(src, dest)
6
+ src_stat = File.stat(src)
7
+ invalid_argument!(src) unless src_stat.file?
8
+
9
+ dest_stat = begin
10
+ File.stat(dest)
11
+ rescue Errno::ENOENT
12
+ end
13
+
14
+ invalid_argument!(dest) unless !dest_stat || dest_stat.file?
15
+
16
+ dest_dev = dest_stat ? dest_stat.dev : begin
17
+ dest_dir = File.dirname(File.expand_path(dest))
18
+ File.stat(dest_dir).dev
19
+ end
20
+
21
+ if src_stat.dev == dest_dev
22
+ File.unlink(dest) if File.exists?(dest)
23
+ File.link src, dest
24
+ else
25
+ FileUtils.copy src, dest
26
+ end
27
+ end
28
+ end
29
+
30
+ FileUtils.extend FileUtils::FastCopy
31
+
32
+ module FileUtils::FastCopy::Etest
33
+ def test_fast_copy
34
+ assert File.exist?(__FILE__)
35
+ File.unlink("tmp/somedata.dat") if File.exist?("tmp/somedata.dat")
36
+
37
+ assert !File.exist?("tmp/somedata.dat")
38
+ FileUtils.fast_copy __FILE__, "tmp/somedata.dat"
39
+ assert_equal File.read("tmp/somedata.dat"), File.read(__FILE__)
40
+
41
+ File.unlink("tmp/somedata.dat")
42
+ File.touch("tmp/somedata.dat")
43
+ assert_not_equal File.size("tmp/somedata.dat"), File.size(__FILE__)
44
+ FileUtils.fast_copy __FILE__, "tmp/somedata.dat"
45
+ assert_equal File.size("tmp/somedata.dat"), File.size(__FILE__)
46
+ end
47
+
48
+ def test_fast_copy_failures
49
+ assert_raise(Errno::ENOENT) {
50
+ FileUtils.fast_copy "fixtures/somedata.dat.nonexisting", "tmp/somedata.dat"
51
+ }
52
+
53
+ assert_raise(Errno::ENOENT) {
54
+ FileUtils.fast_copy "fixtures/somedata.dat.nonexisting", "tmp"
55
+ }
56
+
57
+ assert_raise(Errno::ENOENT) {
58
+ FileUtils.fast_copy __FILE__, "tmp/nonexisting/dir"
59
+ }
60
+ end
61
+ end if VEX_TEST == "base"