tins 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +7 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +18 -0
  5. data/README.rdoc +20 -0
  6. data/Rakefile +28 -0
  7. data/TODO +1 -0
  8. data/VERSION +1 -0
  9. data/lib/spruz.rb +1 -0
  10. data/lib/tins.rb +34 -0
  11. data/lib/tins/alias.rb +1 -0
  12. data/lib/tins/attempt.rb +51 -0
  13. data/lib/tins/bijection.rb +46 -0
  14. data/lib/tins/count_by.rb +8 -0
  15. data/lib/tins/deep_dup.rb +11 -0
  16. data/lib/tins/file_binary.rb +85 -0
  17. data/lib/tins/generator.rb +68 -0
  18. data/lib/tins/go.rb +43 -0
  19. data/lib/tins/hash_symbolize_keys_recursive.rb +28 -0
  20. data/lib/tins/hash_union.rb +15 -0
  21. data/lib/tins/limited.rb +38 -0
  22. data/lib/tins/lines_file.rb +123 -0
  23. data/lib/tins/memoize.rb +78 -0
  24. data/lib/tins/minimize.rb +55 -0
  25. data/lib/tins/module_group.rb +13 -0
  26. data/lib/tins/null.rb +26 -0
  27. data/lib/tins/once.rb +25 -0
  28. data/lib/tins/p.rb +23 -0
  29. data/lib/tins/partial_application.rb +31 -0
  30. data/lib/tins/range_plus.rb +9 -0
  31. data/lib/tins/round.rb +51 -0
  32. data/lib/tins/secure_write.rb +25 -0
  33. data/lib/tins/shuffle.rb +17 -0
  34. data/lib/tins/string_camelize.rb +16 -0
  35. data/lib/tins/string_underscore.rb +15 -0
  36. data/lib/tins/string_version.rb +105 -0
  37. data/lib/tins/subhash.rb +42 -0
  38. data/lib/tins/time_dummy.rb +31 -0
  39. data/lib/tins/to_proc.rb +11 -0
  40. data/lib/tins/uniq_by.rb +10 -0
  41. data/lib/tins/version.rb +10 -0
  42. data/lib/tins/write.rb +19 -0
  43. data/lib/tins/xt.rb +25 -0
  44. data/lib/tins/xt/attempt.rb +7 -0
  45. data/lib/tins/xt/blank.rb +67 -0
  46. data/lib/tins/xt/count_by.rb +11 -0
  47. data/lib/tins/xt/deep_dup.rb +7 -0
  48. data/lib/tins/xt/file_binary.rb +7 -0
  49. data/lib/tins/xt/full.rb +33 -0
  50. data/lib/tins/xt/hash_symbolize_keys_recursive.rb +7 -0
  51. data/lib/tins/xt/hash_union.rb +11 -0
  52. data/lib/tins/xt/irb.rb +17 -0
  53. data/lib/tins/xt/named.rb +35 -0
  54. data/lib/tins/xt/null.rb +5 -0
  55. data/lib/tins/xt/p.rb +7 -0
  56. data/lib/tins/xt/partial_application.rb +11 -0
  57. data/lib/tins/xt/range_plus.rb +12 -0
  58. data/lib/tins/xt/round.rb +13 -0
  59. data/lib/tins/xt/secure_write.rb +11 -0
  60. data/lib/tins/xt/shuffle.rb +11 -0
  61. data/lib/tins/xt/string.rb +5 -0
  62. data/lib/tins/xt/string_camelize.rb +6 -0
  63. data/lib/tins/xt/string_underscore.rb +6 -0
  64. data/lib/tins/xt/string_version.rb +7 -0
  65. data/lib/tins/xt/subhash.rb +11 -0
  66. data/lib/tins/xt/symbol_to_proc.rb +7 -0
  67. data/lib/tins/xt/time_dummy.rb +7 -0
  68. data/lib/tins/xt/uniq_by.rb +15 -0
  69. data/lib/tins/xt/write.rb +11 -0
  70. data/tests/tins_file_binary_test.rb +67 -0
  71. data/tests/tins_lines_file_test.rb +84 -0
  72. data/tests/tins_memoize_test.rb +52 -0
  73. data/tests/tins_secure_write_test.rb +44 -0
  74. data/tests/tins_test.rb +629 -0
  75. data/tins.gemspec +35 -0
  76. metadata +212 -0
@@ -0,0 +1,9 @@
1
+ module Tins
2
+ module RangePlus
3
+ def +(other)
4
+ to_a + other.to_a
5
+ end
6
+ end
7
+ end
8
+
9
+ require 'tins/alias'
@@ -0,0 +1,51 @@
1
+ module Tins
2
+ # A bit more versatile rounding for Ruby
3
+ module Round
4
+ def self.included(klass)
5
+ if klass.instance_method(:round)
6
+ klass.class_eval do
7
+ begin
8
+ alias_method :__old_round__, :round
9
+ remove_method :round
10
+ rescue NameError
11
+ end
12
+ end
13
+ super
14
+ else
15
+ raise NoMethodError, 'no round method found'
16
+ end
17
+ end
18
+
19
+ def round(places = nil)
20
+ if places == nil || places == 0
21
+ return __old_round__
22
+ elsif places.respond_to?(:to_int)
23
+ places = places.to_int
24
+ else
25
+ raise TypeError, "argument places has to be like an Integer"
26
+ end
27
+ if places < 0
28
+ max_places = -Math.log(self.abs + 1) / Math.log(10)
29
+ raise ArgumentError, "places has to be >= #{max_places.ceil}" if max_places > places
30
+ end
31
+ t = self
32
+ f = 10.0 ** places
33
+ t *= f
34
+ if t.infinite?
35
+ result = self
36
+ else
37
+ if t >= 0.0
38
+ t = (t + 0.5).floor
39
+ elsif t < 0.0
40
+ t = (t - 0.5).ceil
41
+ end
42
+ t /= f
43
+ result = t.nan? ? self : t
44
+ end
45
+ max_places and result = result.to_i # if places < 0
46
+ result
47
+ end
48
+ end
49
+ end
50
+
51
+ require 'tins/alias'
@@ -0,0 +1,25 @@
1
+ module Tins
2
+ module SecureWrite
3
+ # Write to a file atomically
4
+ def secure_write(filename, content = nil, mode = 'w')
5
+ temp = File.new(filename + ".tmp.#$$.#{Time.now.to_f}", mode)
6
+ if content.nil? and block_given?
7
+ yield temp
8
+ elsif !content.nil?
9
+ temp.write content
10
+ else
11
+ raise ArgumentError, "either content or block argument required"
12
+ end
13
+ temp.fsync
14
+ size = temp.stat.size
15
+ temp.close
16
+ File.rename temp.path, filename
17
+ size
18
+ ensure
19
+ temp and !temp.closed? and temp.close
20
+ File.file?(temp.path) and File.unlink temp.path
21
+ end
22
+ end
23
+ end
24
+
25
+ require 'tins/alias'
@@ -0,0 +1,17 @@
1
+ module Tins
2
+ module Shuffle
3
+ def shuffle!
4
+ (size - 1) .downto(1) do |i|
5
+ j = rand(i + 1)
6
+ self[i], self[j] = self[j], self[i]
7
+ end
8
+ self
9
+ end
10
+
11
+ def shuffle
12
+ dup.shuffle!
13
+ end
14
+ end
15
+ end
16
+
17
+ require 'tins/alias'
@@ -0,0 +1,16 @@
1
+ module Tins
2
+ module StringCamelize
3
+ def camelize(first_letter = :upper)
4
+ case first_letter
5
+ when :upper, true
6
+ gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
7
+ when :lower, false
8
+ self[0].chr.downcase + camelize[1..-1]
9
+ end
10
+ end
11
+
12
+ alias camelcase camelize
13
+ end
14
+ end
15
+
16
+ require 'tins/alias'
@@ -0,0 +1,15 @@
1
+ module Tins
2
+ module StringUnderscore
3
+ def underscore
4
+ word = dup
5
+ word.gsub!(/::/, '/')
6
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
7
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
8
+ word.tr!("-", "_")
9
+ word.downcase!
10
+ word
11
+ end
12
+ end
13
+ end
14
+
15
+ require 'tins/alias'
@@ -0,0 +1,105 @@
1
+ require 'tins/xt/symbol_to_proc'
2
+
3
+ module Tins
4
+ module StringVersion
5
+ class Version
6
+ include Comparable
7
+
8
+ def initialize(string)
9
+ string =~ /\A[\.\d]+\Z/ or raise ArgumentError, "#{string.inspect} isn't a version number"
10
+ @version = string.frozen? ? string.dup : string
11
+ end
12
+
13
+ def major
14
+ self[0]
15
+ end
16
+
17
+ def major=(number)
18
+ self[0] = number
19
+ end
20
+
21
+ def minor
22
+ self[1]
23
+ end
24
+
25
+ def minor=(number)
26
+ self[1] = number
27
+ end
28
+
29
+ def build
30
+ self[2]
31
+ end
32
+
33
+ def build=(number)
34
+ self[2] = number
35
+ end
36
+
37
+ def revision
38
+ self[3]
39
+ end
40
+
41
+ def revision=(number)
42
+ self[3] = number
43
+ end
44
+
45
+ def [](index)
46
+ array[index]
47
+ end
48
+
49
+ def []=(index, value)
50
+ value = value.to_i
51
+ value >= 0 or raise ArgumentError, "version numbers can't contain negative numbers like #{value}"
52
+ a = array
53
+ @array = nil
54
+ a[index] = value
55
+ a.map! { |x| x.nil? ? 0 : x }
56
+ @version.replace a * '.'
57
+ end
58
+
59
+ def succ!
60
+ self[-1] += 1
61
+ end
62
+
63
+ def pred!
64
+ self[-1] -= 1
65
+ end
66
+
67
+ def <=>(other)
68
+ pairs = array.zip(other.array)
69
+ pairs.map! { |a, b| [ a.nil? ? 0 : a, b.nil? ? 0 : b ] }
70
+ a, b = pairs.transpose
71
+ a <=> b
72
+ end
73
+
74
+ def ==(other)
75
+ (self <=> other).zero?
76
+ end
77
+
78
+ def array
79
+ @version.split('.').map(&:to_i)
80
+ end
81
+
82
+ alias to_a array
83
+
84
+ def to_s
85
+ @version
86
+ end
87
+
88
+ alias inspect to_s
89
+
90
+ def version
91
+ self
92
+ end
93
+ end
94
+
95
+ def version
96
+ if frozen?
97
+ Version.new(self)
98
+ else
99
+ @version ||= Version.new(self)
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ require 'tins/alias'
@@ -0,0 +1,42 @@
1
+ module Tins
2
+ module Subhash
3
+ # Create a subhash from this hash, that only contains key-value pairs
4
+ # matching +patterns+ and return it. +patterns+ can be for example /^foo/
5
+ # to put 'foobar' and 'foobaz' or 'foo'/:foo to put 'foo' into the subhash.
6
+ #
7
+ # If a block is given this method yields to it after the first pattern
8
+ # matched with a 3-tuple of +(key, value, match_data)+ using the return
9
+ # value of the block as the value of the result hash. +match_data+ is a
10
+ # MatchData instance if the matching pattern was a regular rexpression
11
+ # otherwise it is nil.
12
+ def subhash(*patterns)
13
+ patterns.map! do |pat|
14
+ pat = pat.to_sym.to_s if pat.respond_to?(:to_sym)
15
+ pat.respond_to?(:match) ? pat : pat.to_s
16
+ end
17
+ result =
18
+ if default_proc
19
+ self.class.new(&default_proc)
20
+ else
21
+ self.class.new(default)
22
+ end
23
+ if block_given?
24
+ each do |k, v|
25
+ patterns.each { |pat|
26
+ if pat === k.to_s
27
+ result[k] = yield(k, v, $~)
28
+ break
29
+ end
30
+ }
31
+ end
32
+ else
33
+ each do |k, v|
34
+ result[k] = v if patterns.any? { |pat| pat === k.to_s }
35
+ end
36
+ end
37
+ result
38
+ end
39
+ end
40
+ end
41
+
42
+ require 'tins/alias'
@@ -0,0 +1,31 @@
1
+ module Tins
2
+ module TimeDummy
3
+ def self.included(modul)
4
+ modul.module_eval do
5
+ class << self
6
+ alias really_new new
7
+ remove_method :now rescue nil
8
+ remove_method :new rescue nil
9
+ end
10
+
11
+ extend ClassMethods
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ attr_accessor :dummy
17
+
18
+ def new
19
+ if dummy
20
+ dummy.dup
21
+ else
22
+ really_new
23
+ end
24
+ end
25
+
26
+ alias now new
27
+ end
28
+ end
29
+ end
30
+
31
+ require 'tins/alias'
@@ -0,0 +1,11 @@
1
+ module Tins
2
+ module ToProc
3
+ def to_proc
4
+ lambda do |obj, *args|
5
+ obj.__send__(self, *args[0..-1])
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ require 'tins/alias'
@@ -0,0 +1,10 @@
1
+ module Tins
2
+ module UniqBy
3
+ def uniq_by(&b)
4
+ b ||= lambda { |x| x }
5
+ inject({}) { |h, e| h[b[e]] ||= e; h }.values
6
+ end
7
+ end
8
+ end
9
+
10
+ require 'tins/alias'
@@ -0,0 +1,10 @@
1
+ module Tins
2
+ # Tins version
3
+ VERSION = '0.3.0'
4
+ VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
5
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
+ end
9
+
10
+ require 'tins/alias'
@@ -0,0 +1,19 @@
1
+ require 'tins/secure_write'
2
+
3
+ module Tins
4
+ module Write
5
+ def self.extended(modul)
6
+ modul.extend SecureWrite
7
+ if modul.respond_to?(:write)
8
+ $DEBUG and warn "Skipping inclusion of Tins::Write#write method, include Tins::Write::SecureWrite#secure_write instead"
9
+ else
10
+ class << modul; self; end.instance_eval do
11
+ alias_method :write, :secure_write
12
+ end
13
+ end
14
+ super
15
+ end
16
+ end
17
+ end
18
+
19
+ require 'tins/alias'
@@ -0,0 +1,25 @@
1
+ require 'tins'
2
+
3
+ module Tins
4
+ require 'tins/xt/blank'
5
+ require 'tins/xt/count_by'
6
+ require 'tins/xt/full'
7
+ require 'tins/xt/hash_union'
8
+ require 'tins/xt/irb'
9
+ require 'tins/xt/null'
10
+ require 'tins/xt/round'
11
+ require 'tins/xt/subhash'
12
+ require 'tins/xt/time_dummy'
13
+ require 'tins/xt/uniq_by'
14
+ require 'tins/xt/p'
15
+ require 'tins/xt/symbol_to_proc'
16
+ require 'tins/xt/write'
17
+ require 'tins/xt/secure_write'
18
+ require 'tins/xt/deep_dup'
19
+ require 'tins/xt/attempt'
20
+ require 'tins/xt/hash_symbolize_keys_recursive'
21
+ require 'tins/xt/range_plus'
22
+ require 'tins/xt/named'
23
+ require 'tins/xt/string'
24
+ require 'tins/xt/file_binary'
25
+ end
@@ -0,0 +1,7 @@
1
+ require 'tins/attempt'
2
+
3
+ module Tins
4
+ class ::Object
5
+ include Tins::Attempt
6
+ end
7
+ end
@@ -0,0 +1,67 @@
1
+ module Tins
2
+ module Blank
3
+ module Object
4
+ def blank?
5
+ respond_to?(:empty?) ? empty? : !self
6
+ end
7
+
8
+ def present?
9
+ !blank?
10
+ end
11
+ end
12
+
13
+ module NilClass
14
+ def blank?
15
+ true
16
+ end
17
+ end
18
+
19
+ module FalseClass
20
+ def blank?
21
+ true
22
+ end
23
+ end
24
+
25
+ module TrueClass
26
+ def blank?
27
+ false
28
+ end
29
+ end
30
+
31
+ module Array
32
+ def self.included(modul)
33
+ modul.module_eval do
34
+ alias_method :blank?, :empty?
35
+ end
36
+ end
37
+ end
38
+
39
+ module Hash
40
+ def self.included(modul)
41
+ modul.module_eval do
42
+ alias_method :blank?, :empty?
43
+ end
44
+ end
45
+ end
46
+
47
+ module String
48
+ def blank?
49
+ self !~ /\S/
50
+ end
51
+ end
52
+
53
+ module Numeric
54
+ def blank?
55
+ false
56
+ end
57
+ end
58
+ end
59
+
60
+ unless Object.respond_to?(:blank?)
61
+ for k in Blank.constants
62
+ Object.const_get(k).class_eval do
63
+ include Blank.const_get(k)
64
+ end
65
+ end
66
+ end
67
+ end