tins 0.3.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.
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