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,4 @@
1
+ .*.sw[pon]
2
+ .rvmrc
3
+ Gemfile.lock
4
+ pkg
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - ruby-head
5
+ - ree
6
+ - rbx
7
+ - jruby
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ source :rubygems
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2010 Florian Frank
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X
16
+ CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
17
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ = Tins - Useful tools library in Ruby
2
+
3
+ == Description
4
+
5
+ Non yet.
6
+
7
+ == Download
8
+
9
+ The homepage of this library is located at
10
+
11
+ * http://flori.github.com/tins
12
+
13
+ == Author
14
+
15
+ Florian Frank mailto:flori@ping.de
16
+
17
+ == License
18
+
19
+ This software is licensed under the X11 (or MIT) license:
20
+ http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3
@@ -0,0 +1,28 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ require 'gem_hadar'
4
+
5
+ GemHadar do
6
+ name 'tins'
7
+ author 'Florian Frank'
8
+ email 'flori@ping.de'
9
+ homepage "http://flori.github.com/#{name}"
10
+ summary 'Useful stuff.'
11
+ description 'All the stuff that isn\'t good/big enough for a real library.'
12
+ test_dir 'tests'
13
+ ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.rvmrc'
14
+ readme 'README.rdoc'
15
+ development_dependency 'test-unit', '~>2.3'
16
+
17
+ install_library do
18
+ libdir = CONFIG["sitelibdir"]
19
+ cd 'lib' do
20
+ for file in Dir['**/*.rb']
21
+ dst = File.join(libdir, file)
22
+ mkdir_p File.dirname(dst)
23
+ install file, dst
24
+ end
25
+ end
26
+ install 'bin/enum', File.join(CONFIG['bindir'], 'enum')
27
+ end
28
+ end
data/TODO ADDED
@@ -0,0 +1 @@
1
+ - Ruby1.9 has File.write method now, that conflicts with Tins::Write module's and has to be fixed in some way
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1 @@
1
+ require 'tins/alias'
@@ -0,0 +1,34 @@
1
+ module Tins
2
+ require 'tins/attempt'
3
+ require 'tins/bijection'
4
+ require 'tins/count_by'
5
+ require 'tins/deep_dup'
6
+ require 'tins/file_binary'
7
+ require 'tins/generator'
8
+ require 'tins/go'
9
+ require 'tins/hash_symbolize_keys_recursive'
10
+ require 'tins/hash_union'
11
+ require 'tins/limited'
12
+ require 'tins/lines_file'
13
+ require 'tins/memoize'
14
+ require 'tins/minimize'
15
+ require 'tins/module_group'
16
+ require 'tins/null'
17
+ require 'tins/once'
18
+ require 'tins/p'
19
+ require 'tins/partial_application'
20
+ require 'tins/range_plus'
21
+ require 'tins/round'
22
+ require 'tins/secure_write'
23
+ require 'tins/shuffle'
24
+ require 'tins/string_camelize'
25
+ require 'tins/string_underscore'
26
+ require 'tins/string_version'
27
+ require 'tins/subhash'
28
+ require 'tins/time_dummy'
29
+ require 'tins/to_proc'
30
+ require 'tins/uniq_by'
31
+ require 'tins/version'
32
+ require 'tins/write'
33
+ end
34
+ require 'tins/alias'
@@ -0,0 +1 @@
1
+ Spruz = Tins
@@ -0,0 +1,51 @@
1
+ module Tins
2
+ module Attempt
3
+ def attempt(opts = {}, &block)
4
+ sleep = nil
5
+ exception_class = StandardError
6
+ if Numeric === opts
7
+ attempts = opts
8
+ else
9
+ attempts = opts[:attempts] || 1
10
+ exception_class = opts[:exception_class] if opts.key?(:exception_class)
11
+ sleep = opts[:sleep]
12
+ end
13
+ return if attempts <= 0
14
+ count = 0
15
+ if exception_class.nil?
16
+ begin
17
+ count += 1
18
+ if block.call(count)
19
+ return true
20
+ elsif count < attempts
21
+ sleep_duration(sleep, count)
22
+ end
23
+ end until count == attempts
24
+ false
25
+ else
26
+ begin
27
+ count += 1
28
+ block.call(count)
29
+ true
30
+ rescue exception_class
31
+ if count < attempts
32
+ sleep_duration(sleep, count)
33
+ retry
34
+ end
35
+ false
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def sleep_duration(duration, count)
43
+ case duration
44
+ when Numeric
45
+ sleep duration
46
+ when Proc
47
+ sleep duration.call(count)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,46 @@
1
+ module Tins
2
+ class Bijection < Hash
3
+ def self.[](*pairs)
4
+ pairs.size % 2 == 0 or
5
+ raise ArgumentError, "odd number of arguments for #{self}"
6
+ new.fill do |obj|
7
+ (pairs.size / 2).times do |i|
8
+ j = 2 * i
9
+ key = pairs[j]
10
+ value = pairs[j + 1]
11
+ obj.key?(key) and raise ArgumentError, "duplicate key #{key.inspect} for #{self}"
12
+ obj.inverted.key?(value) and raise ArgumentError, "duplicate value #{value.inspect} for #{self}"
13
+ obj[pairs[j]] = pairs[j + 1]
14
+ end
15
+ end
16
+ end
17
+
18
+ def initialize(inverted = Bijection.new(self))
19
+ @inverted = inverted
20
+ end
21
+
22
+ def fill
23
+ if empty?
24
+ yield self
25
+ freeze
26
+ end
27
+ self
28
+ end
29
+
30
+ def freeze
31
+ r = super
32
+ unless @inverted.frozen?
33
+ @inverted.freeze
34
+ end
35
+ r
36
+ end
37
+
38
+ def []=(key, value)
39
+ key?(key) and return
40
+ super
41
+ @inverted[value] = key
42
+ end
43
+
44
+ attr_reader :inverted
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ module Tins
2
+ module CountBy
3
+ def count_by(&b)
4
+ b ||= lambda { |x| true }
5
+ inject(0) { |s, e| s += 1 if b[e]; s }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Tins
2
+ module DeepDup
3
+ def deep_dup
4
+ Marshal.load(Marshal.dump(self))
5
+ rescue TypeError
6
+ return self
7
+ end
8
+ end
9
+ end
10
+
11
+ require 'tins/alias'
@@ -0,0 +1,85 @@
1
+ require 'tins/xt/hash_union'
2
+
3
+ module Tins
4
+ module FileBinary
5
+ module Constants
6
+ SEEK_SET = ::File::SEEK_SET
7
+
8
+ ZERO = "\x00"
9
+ BINARY = "\x01-\x1f\x7f-\xff"
10
+
11
+ if defined?(::Encoding)
12
+ ZERO.force_encoding(Encoding::ASCII_8BIT)
13
+ BINARY.force_encoding(Encoding::ASCII_8BIT)
14
+ end
15
+ end
16
+
17
+ class << self
18
+ # Default options can be queried/set via this hash.
19
+ attr_accessor :default_options
20
+ end
21
+ self.default_options = {
22
+ :offset => 0,
23
+ :buffer_size => 2 ** 13,
24
+ :percentage_binary => 30.0,
25
+ :percentage_zeros => 0.0,
26
+ }
27
+
28
+ # Returns true if this file is considered to be binary, false if it is not
29
+ # considered to be binary, and nil if it was empty.
30
+ #
31
+ # A file is considered to be binary if the percentage of zeros exceeds
32
+ # <tt>options[:percentage_zeros]</tt> or the percentage of binary bytes
33
+ # (8-th bit is 1) exceeds <tt>options[:percentage_binary]</tt> in the
34
+ # buffer of size <tt>options[:buffer_size]</tt> that is checked (beginning
35
+ # from offset <tt>options[:offset]</tt>). If an option isn't given the one
36
+ # from FileBinary.default_options is used instead.
37
+ def binary?(options = {})
38
+ options |= FileBinary.default_options
39
+ old_pos = tell
40
+ seek options[:offset], Constants::SEEK_SET
41
+ data = read options[:buffer_size]
42
+ !data or data.empty? and return nil
43
+ data_size = data.size
44
+ data.count(Constants::ZERO).to_f / data_size >
45
+ options[:percentage_zeros] / 100.0 and return true
46
+ data.count(Constants::BINARY).to_f / data_size >
47
+ options[:percentage_binary] / 100.0
48
+ ensure
49
+ old_pos and seek old_pos, Constants::SEEK_SET
50
+ end
51
+
52
+ # Returns true if FileBinary#binary? returns false, false if
53
+ # FileBinary#binary? returns true, and nil otherwise. For an explanation of
54
+ # +options+, see FileBinary#binary?.
55
+ def ascii?(options = {})
56
+ case binary?(options)
57
+ when true then false
58
+ when false then true
59
+ end
60
+ end
61
+
62
+ def self.included(modul)
63
+ modul.instance_eval do
64
+ extend ClassMethods
65
+ end
66
+ super
67
+ end
68
+
69
+ module ClassMethods
70
+ # Returns true if the file with name +name+ is considered to be binary
71
+ # using the FileBinary#binary? method.
72
+ def binary?(name, options = {})
73
+ open(name, 'rb') { |f| f.binary?(options) }
74
+ end
75
+
76
+ # Returns true if the file with name +name+ is considered to be ascii
77
+ # using the FileBinary#ascii? method.
78
+ def ascii?(name, options = {})
79
+ open(name, 'rb') { |f| f.ascii?(options) }
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ require 'tins/alias'
@@ -0,0 +1,68 @@
1
+ module Tins
2
+ # This class can create generator objects, that can produce all tuples, that
3
+ # would be created by as many for-loops as dimensions were given.
4
+ #
5
+ # The generator
6
+ # g = Tins::Generator[1..2, %w[a b c]]
7
+ # produces
8
+ # g.to_a # => [[1, "a"], [1, "b"], [1, "c"], [2, "a"], [2, "b"], [2, "c"]]
9
+ #
10
+ # The 'each' method can be used to iterate over the tuples
11
+ # g.each { |a, b| puts "#{a} #{b}" }
12
+ # and Tins::Generator includes the Enumerable module, so
13
+ # Enumerable.instance_methods can be used as well:
14
+ # g.select { |a, b| %w[a c].include? b } # => [[1, "a"], [1, "c"], [2, "a"], [2, "c"]]
15
+ #
16
+ class Generator
17
+ include Enumerable
18
+
19
+ # Create a new Generator object from the enumberables _enums_.
20
+ def self.[](*enums)
21
+ new(enums)
22
+ end
23
+
24
+ # Create a new Generator instance. Use the objects in the Array _enums_
25
+ # as dimensions. The should all respond to the :each method (see module
26
+ # Enumerable in the core ruby library).
27
+ def initialize(enums)
28
+ @enums, @iterators, @n = [], [], 0
29
+ enums.each { |e| add_dimension(e) }
30
+ end
31
+
32
+ # Iterate over all tuples produced by this generator and yield to them.
33
+ def each(&block) # :yield: tuple
34
+ recurse(&block)
35
+ self
36
+ end
37
+
38
+ def recurse(tuple = [ nil ] * @n, i = 0, &block)
39
+ if i < @n - 1 then
40
+ @enums[i].__send__(@iterators[i]) do |x|
41
+ tuple[i] = x
42
+ recurse(tuple, i + 1, &block)
43
+ end
44
+ else
45
+ @enums[i].__send__(@iterators[i]) do |x|
46
+ tuple[i] = x
47
+ yield tuple.dup
48
+ end
49
+ end
50
+ end
51
+ private :recurse
52
+
53
+ # Add another dimension to this generator. _enum_ is an object, that ought
54
+ # to respond to the _iterator_ method (defaults to :each).
55
+ def add_dimension(enum, iterator = :each)
56
+ @enums << enum
57
+ @iterators << iterator
58
+ @n += 1
59
+ end
60
+
61
+ # Return the size of this generator, that is the number of its dimensions.
62
+ def size
63
+ @enums.size
64
+ end
65
+ end
66
+ end
67
+
68
+ require 'tins/alias'
@@ -0,0 +1,43 @@
1
+ module Tins
2
+ module GO
3
+ module_function
4
+
5
+ # Parses the argument array _args_, according to the pattern _s_, to
6
+ # retrieve the single character command line options from it. If _s_ is
7
+ # 'xy:' an option '-x' without an option argument is searched, and an
8
+ # option '-y foo' with an option argument ('foo').
9
+ #
10
+ # An option hash is returned with all found options set to true or the
11
+ # found option argument.
12
+ def go(s, args = ARGV)
13
+ b,v = s.scan(/(.)(:?)/).inject([{},{}]) { |t,(o,a)|
14
+ a = a == ':'
15
+ t[a ? 1 : 0][o] = a ? nil : false
16
+ t
17
+ }
18
+ while a = args.shift
19
+ a !~ /\A-(.+)/ and args.unshift a and break
20
+ p = $1
21
+ until p == ''
22
+ o = p.slice!(0, 1)
23
+ if v.key?(o)
24
+ if p == '' then
25
+ v[o] = args.shift or break 1
26
+ else
27
+ v[0] = p
28
+ end
29
+ break
30
+ elsif b.key?(o)
31
+ b[o] = true
32
+ else
33
+ args.unshift a
34
+ break 1
35
+ end
36
+ end and break
37
+ end
38
+ b.merge(v)
39
+ end
40
+ end
41
+ end
42
+
43
+ require 'tins/alias'