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.
- checksums.yaml +4 -4
- data/.contexts/code_comment.rb +5 -8
- data/.contexts/lib.rb +0 -2
- data/CHANGES.md +12 -0
- data/README.md +158 -6
- data/Rakefile +19 -16
- data/examples/let.rb +8 -40
- data/examples/mail.rb +0 -1
- data/examples/turing.rb +3 -1
- data/lib/tins/alias.rb +1 -0
- data/lib/tins/annotate.rb +37 -27
- data/lib/tins/ask_and_send.rb +41 -0
- data/lib/tins/attempt.rb +39 -0
- data/lib/tins/bijection.rb +34 -0
- data/lib/tins/case_predicate.rb +21 -0
- data/lib/tins/complete.rb +16 -0
- data/lib/tins/concern.rb +64 -0
- data/lib/tins/date_dummy.rb +36 -4
- data/lib/tins/date_time_dummy.rb +34 -2
- data/lib/tins/deep_dup.rb +9 -2
- data/lib/tins/deprecate.rb +12 -0
- data/lib/tins/dslkit.rb +559 -83
- data/lib/tins/duration.rb +120 -5
- data/lib/tins/expose.rb +54 -5
- data/lib/tins/extract_last_argument_options.rb +9 -0
- data/lib/tins/file_binary.rb +104 -21
- data/lib/tins/find.rb +114 -11
- data/lib/tins/generator.rb +10 -2
- data/lib/tins/go.rb +81 -4
- data/lib/tins/hash_bfs.rb +4 -2
- data/lib/tins/hash_symbolize_keys_recursive.rb +62 -4
- data/lib/tins/hash_union.rb +47 -2
- data/lib/tins/if_predicate.rb +31 -0
- data/lib/tins/implement.rb +50 -0
- data/lib/tins/limited.rb +54 -5
- data/lib/tins/lines_file.rb +81 -2
- data/lib/tins/lru_cache.rb +54 -17
- data/lib/tins/memoize.rb +86 -58
- data/lib/tins/method_description.rb +87 -4
- data/lib/tins/minimize.rb +39 -11
- data/lib/tins/module_group.rb +27 -2
- data/lib/tins/named_set.rb +20 -0
- data/lib/tins/null.rb +86 -15
- data/lib/tins/once.rb +61 -4
- data/lib/tins/p.rb +44 -8
- data/lib/tins/partial_application.rb +66 -7
- data/lib/tins/proc_compose.rb +58 -1
- data/lib/tins/proc_prelude.rb +97 -10
- data/lib/tins/range_plus.rb +30 -2
- data/lib/tins/require_maybe.rb +36 -0
- data/lib/tins/responding.rb +39 -0
- data/lib/tins/secure_write.rb +24 -4
- data/lib/tins/sexy_singleton.rb +45 -48
- data/lib/tins/string_byte_order_mark.rb +33 -2
- data/lib/tins/string_camelize.rb +31 -2
- data/lib/tins/string_underscore.rb +33 -2
- data/lib/tins/string_version.rb +179 -10
- data/lib/tins/subhash.rb +35 -10
- data/lib/tins/temp_io.rb +7 -0
- data/lib/tins/temp_io_enum.rb +19 -0
- data/lib/tins/terminal.rb +31 -9
- data/lib/tins/thread_local.rb +67 -5
- data/lib/tins/time_dummy.rb +46 -21
- data/lib/tins/to.rb +15 -0
- data/lib/tins/to_proc.rb +17 -4
- data/lib/tins/token.rb +56 -1
- data/lib/tins/unit.rb +288 -149
- data/lib/tins/version.rb +1 -1
- data/lib/tins/write.rb +14 -3
- data/lib/tins/xt/blank.rb +81 -2
- data/lib/tins/xt/concern.rb +51 -0
- data/lib/tins/xt/full.rb +56 -11
- data/lib/tins/xt/irb.rb +46 -2
- data/lib/tins/xt/method_description.rb +0 -12
- data/lib/tins/xt/minimize.rb +7 -0
- data/lib/tins/xt/named.rb +71 -16
- data/lib/tins/xt/proc_compose.rb +4 -0
- data/lib/tins/xt/subhash.rb +11 -0
- data/lib/tins/xt/time_freezer.rb +43 -6
- data/lib/tins/xt.rb +1 -3
- data/lib/tins.rb +16 -3
- data/tests/duration_test.rb +4 -0
- data/tests/from_module_test.rb +30 -2
- data/tests/implement_test.rb +6 -8
- data/tests/lines_file_test.rb +2 -0
- data/tests/lru_cache_test.rb +12 -0
- data/tests/method_description_test.rb +14 -20
- data/tests/partial_application_test.rb +4 -0
- data/tests/proc_prelude_test.rb +1 -1
- data/tests/scope_test.rb +1 -1
- data/tests/string_version_test.rb +2 -0
- data/tests/to_test.rb +6 -6
- data/tins.gemspec +9 -9
- metadata +23 -41
- data/lib/tins/count_by.rb +0 -21
- data/lib/tins/deep_const_get.rb +0 -64
- data/lib/tins/timed_cache.rb +0 -51
- data/lib/tins/uniq_by.rb +0 -23
- data/lib/tins/xt/count_by.rb +0 -7
- data/lib/tins/xt/deep_const_get.rb +0 -7
- data/lib/tins/xt/uniq_by.rb +0 -25
- data/tests/count_by_test.rb +0 -17
- data/tests/deep_const_get_test.rb +0 -37
- data/tests/uniq_by_test.rb +0 -31
- /data/{COPYING → LICENSE} +0 -0
data/lib/tins/time_dummy.rb
CHANGED
@@ -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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
#
|
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
|
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
|