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,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'