tins 1.43.0 → 1.44.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/.contexts/code_comment.rb +5 -8
  3. data/.contexts/lib.rb +0 -2
  4. data/CHANGES.md +12 -0
  5. data/README.md +158 -6
  6. data/Rakefile +19 -16
  7. data/examples/let.rb +8 -40
  8. data/examples/mail.rb +0 -1
  9. data/examples/turing.rb +3 -1
  10. data/lib/tins/alias.rb +1 -0
  11. data/lib/tins/annotate.rb +37 -27
  12. data/lib/tins/ask_and_send.rb +41 -0
  13. data/lib/tins/attempt.rb +39 -0
  14. data/lib/tins/bijection.rb +34 -0
  15. data/lib/tins/case_predicate.rb +21 -0
  16. data/lib/tins/complete.rb +16 -0
  17. data/lib/tins/concern.rb +64 -0
  18. data/lib/tins/date_dummy.rb +36 -4
  19. data/lib/tins/date_time_dummy.rb +34 -2
  20. data/lib/tins/deep_dup.rb +9 -2
  21. data/lib/tins/deprecate.rb +12 -0
  22. data/lib/tins/dslkit.rb +559 -83
  23. data/lib/tins/duration.rb +120 -5
  24. data/lib/tins/expose.rb +54 -5
  25. data/lib/tins/extract_last_argument_options.rb +9 -0
  26. data/lib/tins/file_binary.rb +104 -21
  27. data/lib/tins/find.rb +114 -11
  28. data/lib/tins/generator.rb +10 -2
  29. data/lib/tins/go.rb +81 -4
  30. data/lib/tins/hash_bfs.rb +4 -2
  31. data/lib/tins/hash_symbolize_keys_recursive.rb +62 -4
  32. data/lib/tins/hash_union.rb +47 -2
  33. data/lib/tins/if_predicate.rb +31 -0
  34. data/lib/tins/implement.rb +50 -0
  35. data/lib/tins/limited.rb +54 -5
  36. data/lib/tins/lines_file.rb +81 -2
  37. data/lib/tins/lru_cache.rb +54 -17
  38. data/lib/tins/memoize.rb +86 -58
  39. data/lib/tins/method_description.rb +87 -4
  40. data/lib/tins/minimize.rb +39 -11
  41. data/lib/tins/module_group.rb +27 -2
  42. data/lib/tins/named_set.rb +20 -0
  43. data/lib/tins/null.rb +86 -15
  44. data/lib/tins/once.rb +61 -4
  45. data/lib/tins/p.rb +44 -8
  46. data/lib/tins/partial_application.rb +66 -7
  47. data/lib/tins/proc_compose.rb +58 -1
  48. data/lib/tins/proc_prelude.rb +97 -10
  49. data/lib/tins/range_plus.rb +30 -2
  50. data/lib/tins/require_maybe.rb +36 -0
  51. data/lib/tins/responding.rb +39 -0
  52. data/lib/tins/secure_write.rb +24 -4
  53. data/lib/tins/sexy_singleton.rb +45 -48
  54. data/lib/tins/string_byte_order_mark.rb +33 -2
  55. data/lib/tins/string_camelize.rb +31 -2
  56. data/lib/tins/string_underscore.rb +33 -2
  57. data/lib/tins/string_version.rb +179 -10
  58. data/lib/tins/subhash.rb +35 -10
  59. data/lib/tins/temp_io.rb +7 -0
  60. data/lib/tins/temp_io_enum.rb +19 -0
  61. data/lib/tins/terminal.rb +31 -9
  62. data/lib/tins/thread_local.rb +67 -5
  63. data/lib/tins/time_dummy.rb +46 -21
  64. data/lib/tins/to.rb +15 -0
  65. data/lib/tins/to_proc.rb +17 -4
  66. data/lib/tins/token.rb +56 -1
  67. data/lib/tins/unit.rb +288 -149
  68. data/lib/tins/version.rb +1 -1
  69. data/lib/tins/write.rb +14 -3
  70. data/lib/tins/xt/blank.rb +81 -2
  71. data/lib/tins/xt/concern.rb +51 -0
  72. data/lib/tins/xt/full.rb +56 -11
  73. data/lib/tins/xt/irb.rb +46 -2
  74. data/lib/tins/xt/method_description.rb +0 -12
  75. data/lib/tins/xt/minimize.rb +7 -0
  76. data/lib/tins/xt/named.rb +71 -16
  77. data/lib/tins/xt/proc_compose.rb +4 -0
  78. data/lib/tins/xt/subhash.rb +11 -0
  79. data/lib/tins/xt/time_freezer.rb +43 -6
  80. data/lib/tins/xt.rb +1 -3
  81. data/lib/tins.rb +16 -3
  82. data/tests/duration_test.rb +4 -0
  83. data/tests/from_module_test.rb +30 -2
  84. data/tests/implement_test.rb +6 -8
  85. data/tests/lines_file_test.rb +2 -0
  86. data/tests/lru_cache_test.rb +12 -0
  87. data/tests/method_description_test.rb +14 -20
  88. data/tests/partial_application_test.rb +4 -0
  89. data/tests/proc_prelude_test.rb +1 -1
  90. data/tests/scope_test.rb +1 -1
  91. data/tests/string_version_test.rb +2 -0
  92. data/tests/to_test.rb +6 -6
  93. data/tins.gemspec +9 -9
  94. metadata +23 -41
  95. data/lib/tins/count_by.rb +0 -21
  96. data/lib/tins/deep_const_get.rb +0 -64
  97. data/lib/tins/timed_cache.rb +0 -51
  98. data/lib/tins/uniq_by.rb +0 -23
  99. data/lib/tins/xt/count_by.rb +0 -7
  100. data/lib/tins/xt/deep_const_get.rb +0 -7
  101. data/lib/tins/xt/uniq_by.rb +0 -25
  102. data/tests/count_by_test.rb +0 -17
  103. data/tests/deep_const_get_test.rb +0 -37
  104. data/tests/uniq_by_test.rb +0 -31
  105. /data/{COPYING → LICENSE} +0 -0
@@ -2,7 +2,22 @@ require 'tins/string_version'
2
2
  require 'time'
3
3
 
4
4
  module Tins
5
+ # A module that provides time dummy functionality for testing and development
6
+ # purposes.
7
+ #
8
+ # This module allows setting a fake current time that can be used in tests or
9
+ # development environments where you want to control the time returned by
10
+ # Time.now.
5
11
  module TimeDummy
12
+ # The included method is a hook that gets called when this module is
13
+ # included in another class or module.
14
+ #
15
+ # It sets up time freezing functionality by extending the including
16
+ # class/module with special time handling methods. The method modifies the
17
+ # including class/module's singleton class to provide dummy time
18
+ # capabilities.
19
+ #
20
+ # @param modul [Object] the class or module that includes this module
6
21
  def self.included(modul)
7
22
  class << modul
8
23
  alias really_new new
@@ -11,6 +26,12 @@ module Tins
11
26
  remove_method :now rescue nil
12
27
  remove_method :new rescue nil
13
28
 
29
+ # Sets the dummy time value for time freezing functionality.
30
+ #
31
+ # This method allows setting a specific time value that will be used
32
+ # as the frozen time when time freezing is enabled.
33
+ #
34
+ # @param value [Time, String] the time value to set as dummy
14
35
  def dummy=(value)
15
36
  if value.respond_to?(:to_str)
16
37
  value = Time.parse(value.to_str)
@@ -20,6 +41,12 @@ module Tins
20
41
  @dummy = value
21
42
  end
22
43
 
44
+ # The dummy method manages a dummy value for testing purposes.
45
+ #
46
+ # @param value [Object] the dummy value to set, or nil to get the current value
47
+ # @return [Object] the current dummy value when value is nil
48
+ # @yield [] executes the block with the dummy value set
49
+ # @return [Object] the return value of the block if a block is given
23
50
  def dummy(value = nil)
24
51
  if value.nil?
25
52
  if defined?(@dummy)
@@ -36,28 +63,28 @@ module Tins
36
63
  end
37
64
  end
38
65
 
39
- if Tins::StringVersion.compare(RUBY_VERSION, :>=, "3.0")
40
- def new(*a, **kw)
41
- if dummy
42
- dummy.dup
43
- elsif caller.first =~ /`now`/
44
- really_now(**kw)
45
- else
46
- really_new(*a, **kw)
47
- end
48
- end
49
- else
50
- def new(*a)
51
- if dummy
52
- dummy.dup
53
- elsif caller.first =~ /`now`/
54
- really_now
55
- else
56
- really_new(*a)
57
- end
66
+ # The new method creates a new time instance, either by duplicating
67
+ # the dummy time or calling the real creation method.
68
+ #
69
+ # @param a [ Array ] the arguments to pass to the real creation
70
+ # method
71
+ # @param kw [ Hash ] the keyword arguments to pass to the real
72
+ # creation method
73
+ #
74
+ # @return [ Time ] the newly created time instance
75
+ def new(*a, **kw)
76
+ if dummy
77
+ dummy.dup
78
+ elsif caller.first =~ /`now`/
79
+ really_now(**kw)
80
+ else
81
+ really_new(*a, **kw)
58
82
  end
59
83
  end
60
84
 
85
+ # The now method returns a new instance of the current class.
86
+ #
87
+ # @return [Object] a new instance of the class this method is called on
61
88
  def now
62
89
  new
63
90
  end
@@ -66,5 +93,3 @@ module Tins
66
93
  end
67
94
  end
68
95
  end
69
-
70
- require 'tins/alias'
data/lib/tins/to.rb CHANGED
@@ -1,5 +1,20 @@
1
1
  module Tins
2
+ # Provides a simple way to remove common leading whitespace from multi-line
3
+ # strings, mostly for to(<<-EOT), if require "tins/xt/to". Today you would
4
+ # probably use <<~EOT in this case.
5
+ #
6
+ # Example usage:
7
+ # doc = to(<<-EOT)
8
+ # hello
9
+ # world
10
+ # end
11
+ # EOT
12
+ # # => "hello\n world\nend"
2
13
  module To
14
+ # Remove common leading whitespace from multi-line strings
15
+ #
16
+ # @param string [String] The multi-line string to deindent
17
+ # @return [String] String with common leading whitespace removed
3
18
  def to(string)
4
19
  shift_width = (string[/\A\s*/]).size
5
20
  string.gsub(/^[^\S\n]{0,#{shift_width}}/, '')
data/lib/tins/to_proc.rb CHANGED
@@ -1,12 +1,25 @@
1
1
  module Tins
2
+ # This module provides a way to convert symbols into procs using the
3
+ # __send__ method for dynamic method invocation. It was necessary before
4
+ # Ruby 1.9's built-in Symbol#to_proc functionality. You still can use
5
+ # it for strings, though.
6
+ #
7
+ # Example Usage:
8
+ # class String
9
+ # include Tins::ToProc
10
+ # end
11
+ #
12
+ # ["hello", "world"].map(&'upcase') # => ["HELLO", "WORLD"]
2
13
  module ToProc
3
- # :nocov:
14
+ # Converts a Symbol into a Proc that sends the symbol's name to its
15
+ # argument
16
+ #
17
+ # @return [ Proc ] a Proc that when called will send the symbol's name as a
18
+ # message to obj with args
4
19
  def to_proc
5
20
  lambda do |obj, *args|
6
- obj.__send__(self, *args[0..-1])
21
+ obj.__send__(self, *args)
7
22
  end
8
23
  end
9
24
  end
10
25
  end
11
-
12
- require 'tins/alias'
data/lib/tins/token.rb CHANGED
@@ -1,26 +1,78 @@
1
1
  require 'securerandom'
2
2
 
3
3
  module Tins
4
+ # A secure token generator that creates cryptographically safe strings
5
+ # using customizable alphabets and random number generators.
6
+ #
7
+ # @example Basic usage
8
+ # token = Tins::Token.new
9
+ # # => "aB3xK9mN2pQ8rS4tU6vW7yZ1"
10
+ #
11
+ # @example Custom length
12
+ # token = Tins::Token.new(length: 20)
13
+ # # => "xYz123AbC456DeF789GhI0jK"
14
+ #
15
+ # @example Custom alphabet
16
+ # token = Tins::Token.new(
17
+ # alphabet: Tins::Token::BASE16_UPPERCASE_ALPHABET,
18
+ # length: 16
19
+ # )
20
+ # # => "A1B2C3D4E5F6G7H8"
21
+ #
22
+ # @example Custom random number generator
23
+ # token = Tins::Token.new(random: Random.new(42))
24
+ # # => "xYz123AbC456DeF789GhI0jK"
4
25
  class Token < String
26
+ # Default alphabet for token generation
5
27
  DEFAULT_ALPHABET =
6
28
  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".freeze
7
29
 
30
+ # Base64 alphabet
8
31
  BASE64_ALPHABET =
9
32
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".freeze
10
33
 
34
+ # URL-safe base64 alphabet
11
35
  BASE64_URL_FILENAME_SAFE_ALPHABET =
12
36
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".freeze
13
37
 
38
+ # Base32 alphabet
14
39
  BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".freeze
15
40
 
41
+ # Extended hex base32 alphabet
16
42
  BASE32_EXTENDED_HEX_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUV".freeze
17
43
 
44
+ # Base16 uppercase alphabet
18
45
  BASE16_UPPERCASE_ALPHABET = "0123456789ABCDEF".freeze
19
46
 
47
+ # Base16 lowercase alphabet
20
48
  BASE16_LOWERCASE_ALPHABET = "0123456789abcdef".freeze
21
49
 
50
+ # Base16 default alphabet (uppercase)
22
51
  BASE16_ALPHABET = BASE16_UPPERCASE_ALPHABET
23
52
 
53
+ # Initializes a new Token instance with specified bit length, length,
54
+ # alphabet, and random number generator.
55
+ #
56
+ # @example Basic initialization
57
+ # token = Tins::Token.new
58
+ # # => "aB3xK9mN2pQ8rS4tU6vW7yZ1"
59
+ #
60
+ # @example Custom parameters
61
+ # token = Tins::Token.new(
62
+ # bits: 256,
63
+ # alphabet: Tins::Token::BASE32_ALPHABET
64
+ # )
65
+ #
66
+ # @param bits [Integer] the number of bits for the token (default: 128)
67
+ # @param length [Integer] the length of the token (optional, mutually exclusive with bits)
68
+ # @param alphabet [String] the alphabet to use for token generation (default: DEFAULT_ALPHABET)
69
+ # @param random [Object] the random number generator to use (default: SecureRandom)
70
+ #
71
+ # @return [Tins::Token] a new Token instance
72
+ #
73
+ # @raise [ArgumentError] if alphabet has fewer than 2 symbols
74
+ # @raise [ArgumentError] if bits is not positive when length is not specified
75
+ # @raise [ArgumentError] if length is not positive when specified
24
76
  def initialize(bits: 128, length: nil, alphabet: DEFAULT_ALPHABET, random: SecureRandom)
25
77
  alphabet.size > 1 or raise ArgumentError, 'need at least 2 symbols in alphabet'
26
78
  if length
@@ -30,11 +82,14 @@ module Tins
30
82
  length = (Math.log(1 << bits) / Math.log(alphabet.size)).ceil
31
83
  end
32
84
  self.bits = (Math.log(alphabet.size ** length) / Math.log(2)).floor
33
- token = ''
85
+ token = +''
34
86
  length.times { token << alphabet[random.random_number(alphabet.size)] }
35
87
  super token
36
88
  end
37
89
 
90
+ # The bit length of the token.
91
+ #
92
+ # @return [Integer] the number of bits of entropy in the token
38
93
  attr_accessor :bits
39
94
  end
40
95
  end