trick_bag 0.66.0 → 0.67.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/README.md +153 -1
- data/RELEASE_NOTES.md +6 -1
- data/lib/trick_bag/{core_types.rb → core_types/core_types.rb} +0 -0
- data/lib/trick_bag/enumerables/endless_last_enumerable.rb +3 -3
- data/lib/trick_bag/enumerables/filtered_enumerable.rb +8 -0
- data/lib/trick_bag/formatters/formatters.rb +2 -1
- data/lib/trick_bag/functional/functional.rb +5 -0
- data/lib/trick_bag/io/temp_files.rb +2 -2
- data/lib/trick_bag/io/text_mode_status_updater.rb +2 -0
- data/lib/trick_bag/numeric/multi_counter.rb +1 -1
- data/lib/trick_bag/numeric/start_and_max.rb +4 -2
- data/lib/trick_bag/timing/timing.rb +3 -1
- data/lib/trick_bag/validations/gem_dependency_script.rb +1 -1
- data/lib/trick_bag/version.rb +1 -1
- data/spec/trick_bag/{core_types_spec.rb → core_types/core_types_spec.rb} +2 -2
- data/spec/trick_bag/functional/functional_spec.rb +11 -9
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f8d5b7a9f77fdc75d8672b5947fd8075cca1ab5
|
4
|
+
data.tar.gz: e61fd4ec8b3d7dc55023e2323e7cf75f853d9389
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50b8e5a3407f1b725598a1f22de963682b5e68f154f575989af03e6a84f4e18c39e17c4975978eb8ea2e32c0f705f05fecd41701619524e7e20c40571342d7b6
|
7
|
+
data.tar.gz: edf428cd0e32c8f282ae0f80c84ba5a274d481e6973ba065ba4f1adeb3ebb5e2a43c70f40ccdde6ac5cfc98741faeab7b8b109519ea0b7bc0725c36129699561
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -21,7 +21,159 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
## Usage
|
23
23
|
|
24
|
-
|
24
|
+
The best ways to understand the usage are to look at a) the unit tests in the spec directory tree,
|
25
|
+
b) the comments in the source files, and c) the source code itself. That said, here is a summary:
|
26
|
+
|
27
|
+
### CollectionAccess
|
28
|
+
|
29
|
+
* `accessor` - returns lambda to simplify access to a deeply nested hash, as in
|
30
|
+
`customer_accessor['contact_info.address.city']`
|
31
|
+
instead of `customer['contact_info']['address']['city']`
|
32
|
+
* `#access` - worker method for above, also publicly available for use; called as:
|
33
|
+
`access(customer, 'contact_info', 'address', 'city')`
|
34
|
+
* `LinkedList` - a linked list implementation in Ruby
|
35
|
+
|
36
|
+
### Enumerables
|
37
|
+
|
38
|
+
* `BufferedEnumerable` - enumerable handling the buffering and the timing of fetching;
|
39
|
+
you provide fetcher and (optionally) fetch notifier callables
|
40
|
+
* `CompoundEnumberable` - an enumerator used to provide all combinations of a set of Enumerables.
|
41
|
+
* `EndlessLastEnumerable` - wraps another enumerable, and after it is exhausted, yields the same value on successive calls
|
42
|
+
* `FileLineReader` - Reads a file containing strings, one on each line, and feeds them
|
43
|
+
in its each() method. Strips all lines' leading and trailing whitespace,
|
44
|
+
and ignores all empty lines and lines beginning with the comment character `#`.
|
45
|
+
Especially useful in reading configuration files.
|
46
|
+
* `FilteredEnumerable` - like `my_enumerable.lazy.select { ... }.lazy`, but supports changing the filter at any time
|
47
|
+
|
48
|
+
### Formatters
|
49
|
+
|
50
|
+
* `BinaryToHexAndAscii` - formats bytes in hex and ASCII, e.g.:
|
51
|
+
```
|
52
|
+
0x 0 00 07 0E 15 | 1C 23 2A 31 | 38 3F 46 4D | 54 5B 62 69 .....#*18?FMT[bi
|
53
|
+
0x 10 70 77 7E 85 | 8C 93 9A A1 | A8 AF B6 BD | C4 CB D2 D9 pw~.............
|
54
|
+
```
|
55
|
+
* `ErbRenderer` - convenience class for ERB rendering; simplifies using a specific set of key/value pairs
|
56
|
+
as opposed to the current binding
|
57
|
+
* `Formatters.duration_to_s` - formats number of seconds to string like `11 d, 13 h, 46 m, 40 s`
|
58
|
+
* `Formatters.end_with_n` - reverse of `String#chomp` -
|
59
|
+
useful for use with utilities like Diffy that complain about lines without line endings.
|
60
|
+
* `Formatters.timestamp` - returns a timestamp string suitable for use in file names
|
61
|
+
in the year-month-day-hour-minute-second form, e.g. `2014-03-24_15-25-57`.
|
62
|
+
* `Formatters.replace_with_timestamp` - replaces a token with the timestamp, as in:
|
63
|
+
`my-app-result-{dt}.txt` => `my-app-result-2014-03-24_15-25-57.txt`
|
64
|
+
Especially useful for generating file names.
|
65
|
+
* `Formatters.dos2unix[!]` - formats a string with Unix line endings
|
66
|
+
* `Formatters.array_diff` - returns a nicely formatted string output of the difference
|
67
|
+
between 2 arrays
|
68
|
+
* `Formatters.string_to_verbose_char_list` - returns a list of chars in a string, 1 per line,
|
69
|
+
with several representations of the values, e.g.:
|
70
|
+
```
|
71
|
+
Index Decimal Hex Binary Character
|
72
|
+
----- ------- --- ------ ---------
|
73
|
+
0 97 61 x 110 0001 b a
|
74
|
+
1 49 31 x 11 0001 b 1
|
75
|
+
```
|
76
|
+
* `Formatters.thousands_separated` - adds thousands separators to an Integer
|
77
|
+
string representation as appropriate
|
78
|
+
|
79
|
+
|
80
|
+
### Functional
|
81
|
+
|
82
|
+
These methods provide a shorthand for testing whether or not an object
|
83
|
+
meets an Enumerable of conditional callables.
|
84
|
+
|
85
|
+
|
86
|
+
### IO
|
87
|
+
|
88
|
+
* `Gitignore` - these methods simulate the results of git's file pattern matching
|
89
|
+
based on the .gitignore file. They can be useful, for example,
|
90
|
+
in determining which files to include in a gem build when git is not present.
|
91
|
+
* `Tempfiles.file_containing` - for the easy creation and deletion of a temp file
|
92
|
+
populated with text, wrapped around the code block you provide.
|
93
|
+
* `TextModeStatusUpdater` - provides an updatable and customizable status/information
|
94
|
+
line in a terminal, typically used to display progress.
|
95
|
+
|
96
|
+
|
97
|
+
### Meta
|
98
|
+
|
99
|
+
* `attr` methods provide cleaner and more concise creation of attribute methods that
|
100
|
+
require control over accessibility (public, protected, private).
|
101
|
+
* `class?` - is this name the name of a class?
|
102
|
+
* `undef_class` - undefines a class; useful for unit testing code that dynamically creates classes.
|
103
|
+
|
104
|
+
|
105
|
+
### Networking
|
106
|
+
|
107
|
+
* `SshOutputReader` - Runs an ssh command, collecting the stdout and stderr produced by it.
|
108
|
+
Optionally a predicate can be specified that, when called with the
|
109
|
+
instance of this class, returns true to close the channel or false to continue
|
110
|
+
(for example, when a certain string appears in the command's output).
|
111
|
+
There are instance methods to return the most recent and all accumulated text
|
112
|
+
for both stdout and stderr, so the predicate can easily inspect the text.
|
113
|
+
|
114
|
+
|
115
|
+
### Numeric
|
116
|
+
|
117
|
+
* `Bitmapping` - methods for converting from binary string and bit array to number and back
|
118
|
+
* `Bitmap` - a simple bitmap implementation, with several initialization methods
|
119
|
+
* `KmgtNumericString` - converts number strings with optional suffixes of [kKmMgGtT] to integers.
|
120
|
+
Upper case letters represent powers of 1024, and lower case letters represent powers of 1000.
|
121
|
+
Also supports ranges, e.g. '1k..5k' will be converted by to_range to (1000..5000).
|
122
|
+
* `Multicounter` - simplifies accumulating counts of multiple objects.
|
123
|
+
* `StartAndMax` - provides an object that will tell you if the number exceeds
|
124
|
+
the starting point and if the number is >= the maximum (or if no maximum has been specified).
|
125
|
+
* `Totals` - provides methods for working with percent of total
|
126
|
+
|
127
|
+
|
128
|
+
### Operators
|
129
|
+
|
130
|
+
* `multi_eq` - returns whether or not _all_ values passed are equal to each other
|
131
|
+
|
132
|
+
|
133
|
+
### Timing
|
134
|
+
|
135
|
+
* `Elapser` - provides ways to specify and test for elapsed state
|
136
|
+
* `retry_until_true_or_timeout` - calls a predicate proc repeatedly,
|
137
|
+
sleeping the specified interval between calls, returning if the predicate returns true,
|
138
|
+
and giving up after the specified number of seconds.
|
139
|
+
Displays elapsed and remaining times on the terminal.
|
140
|
+
* `benchmark` - simplifies the output of benchmarking data with a text caption
|
141
|
+
* `try_with_timeout` - runs the passed block in a new thread, ensuring that its execution time
|
142
|
+
does not exceed the specified duration.
|
143
|
+
|
144
|
+
|
145
|
+
### Validations
|
146
|
+
|
147
|
+
* hash validations - methods to see if any of the specified keys are missing from the hash,
|
148
|
+
and a method to raise an error with descriptive message if so
|
149
|
+
* object validations - method to see if any of the specified instance variables are nil, and another
|
150
|
+
method that raises an error with descriptive message if so
|
151
|
+
* `raise_on_invalid_value` - if the passed value is not in the list of valid values, raise an error
|
152
|
+
with descriptive message
|
153
|
+
* regex validations - for working with multiple regexes and strings with which to match them
|
154
|
+
|
155
|
+
|
156
|
+
### Core Types
|
157
|
+
|
158
|
+
`clone_hash_except` - creates a copy of a hash except for the specified keys (this functionality
|
159
|
+
is already included in Rails, but not in Ruby itself)
|
160
|
+
|
161
|
+
|
162
|
+
## Why?
|
163
|
+
|
164
|
+
This library was born when I was writing a lot of testing tools and data collection and analysis software.
|
165
|
+
At that time I also mentored a team of software testers using Ruby and Cucumber. I saw coding patterns that existed
|
166
|
+
in multiple places, in varying levels of functionality and quality, or sometimes, totally absent when
|
167
|
+
they would have been helpful. Why not implement these patterns once in a shared and tested library?
|
168
|
+
|
169
|
+
Some may be very thin layers over the underlying Ruby implementations (e.g. the _Elapser_ class),
|
170
|
+
and their usefulness may be questioned...but in the calling code, the use of these is more intention-revealing,
|
171
|
+
object oriented, and results in more concise calling code.
|
172
|
+
|
173
|
+
This gem's files, classes, and methods are for the most part isolated from each other and self-contained.
|
174
|
+
This means that if you like you can easily copy single methods or files from the gem and copy them into
|
175
|
+
your code base to eliminate a dependency on this gem. If you do this, then I suggest you include an
|
176
|
+
attribution to this gem so that future developers can consult it for fixes and enhancements.
|
25
177
|
|
26
178
|
|
27
179
|
## Contributing
|
data/RELEASE_NOTES.md
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
+
## v0.67.0
|
2
|
+
|
3
|
+
* Move Functional methods into Functional module.
|
4
|
+
* Improve README, esp. add class/method summaries.
|
5
|
+
|
6
|
+
|
1
7
|
## v0.66.0
|
2
8
|
|
3
9
|
* Add TrickBag::Io::Gitignore.list_ignored_files.
|
4
10
|
|
5
11
|
|
6
|
-
|
7
12
|
## v0.65.1
|
8
13
|
|
9
14
|
* Fix bug in TrickBag::Validations when raise_on_missing_keys was passed an array.
|
File without changes
|
@@ -3,9 +3,9 @@ require 'set'
|
|
3
3
|
module TrickBag
|
4
4
|
module Enumerables
|
5
5
|
|
6
|
-
# Takes an
|
7
|
-
# element in the
|
8
|
-
# the last element every time it's called.
|
6
|
+
# Takes an enumerable or number as input. On successive calls to next, it returns the next
|
7
|
+
# element in the that enumerable until it has been exhausted, and then returns
|
8
|
+
# the last element every time it's called. Especially useful in reading configuration files.
|
9
9
|
#
|
10
10
|
# You can use Ruby's array addition and multiplication features
|
11
11
|
# to provide rich functionality, e.g.:
|
@@ -8,6 +8,14 @@ module Enumerables
|
|
8
8
|
#
|
9
9
|
# The filter is an optional parameter on the constructor, but can
|
10
10
|
# also be set after creation with a mutator.
|
11
|
+
#
|
12
|
+
# If you do not intend to change the filter after it is created,
|
13
|
+
# you should probably just use Ruby's built in lazy enumerators, as in:
|
14
|
+
# e = (1..10000000000000000000000000000).lazy.select { |n| n.even? }.lazy
|
15
|
+
#
|
16
|
+
# This class really comes in handy when the filter needs to be changed during
|
17
|
+
# the enumerator's lifetime.
|
18
|
+
|
11
19
|
class FilteredEnumerable
|
12
20
|
|
13
21
|
include Enumerable
|
@@ -55,6 +55,7 @@ module Formatters
|
|
55
55
|
end
|
56
56
|
|
57
57
|
|
58
|
+
# Reverse of String#chomp.
|
58
59
|
# Convert to string if not already a string.
|
59
60
|
# Append new line to string if the string is not empty and does not already end with one.
|
60
61
|
# This is to disable the Diffy warning message "No newline at end of file"
|
@@ -80,7 +81,7 @@ module Formatters
|
|
80
81
|
# for example:
|
81
82
|
#
|
82
83
|
# replace_with_timestamp('my-app-result-{dt}.txt') => "my-app-result-2014-03-24_15-25-57.txt"
|
83
|
-
|
84
|
+
def replace_with_timestamp(string, marker = '{dt}', datetime = DateTime.now)
|
84
85
|
string.gsub(marker, timestamp(datetime))
|
85
86
|
end
|
86
87
|
|
@@ -1,4 +1,8 @@
|
|
1
1
|
module TrickBag
|
2
|
+
module Functional
|
3
|
+
|
4
|
+
# These methods provide a shorthand for testing whether or not an object
|
5
|
+
# meets an Enumerable of conditional callables.
|
2
6
|
|
3
7
|
module_function
|
4
8
|
|
@@ -23,3 +27,4 @@ module TrickBag
|
|
23
27
|
conditions.any? { |condition| condition.(object) }
|
24
28
|
end
|
25
29
|
end
|
30
|
+
end
|
@@ -6,8 +6,8 @@ module TempFiles
|
|
6
6
|
|
7
7
|
module_function
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# For the easy creation and deletion of a temp file populated with text,
|
10
|
+
# wrapped around the code block you provide.
|
11
11
|
#
|
12
12
|
# @param text the text to write to the temporary file
|
13
13
|
# @param file_prefix optional prefix for the temporary file's name
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module TrickBag
|
2
2
|
module Io
|
3
3
|
|
4
|
+
# Provides an updatable and customizable status/information line in a terminal,
|
5
|
+
# typically used to display progress.
|
4
6
|
# Updates the terminal line with text, erasing the original content and displaying at the same place.
|
5
7
|
# Uses ANSI escape sequences for cursor positioning and clearing
|
6
8
|
# (see http://www.oldlinux.org/Linux.old/Ref-docs/ASCII/ANSI%20Escape%20Sequences.htm).
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module TrickBag
|
2
2
|
module Numeric
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
4
|
+
# Provides an object that will tell you if the number exceeds the starting point
|
5
|
+
# and if the number is >= the maximum (or if no maximum has been specified).
|
6
|
+
# While this functionality can easily be duplicated with more primitive
|
7
|
+
# code, this class provides an object whose use will be simpler and more readable.
|
6
8
|
class StartAndMax
|
7
9
|
|
8
10
|
attr_reader :start_pos, :max_count
|
@@ -9,8 +9,10 @@ module Timing
|
|
9
9
|
|
10
10
|
|
11
11
|
# Calls a predicate proc repeatedly, sleeping the specified interval
|
12
|
-
# between calls,
|
12
|
+
# between calls, returning if the predicate returns true,
|
13
|
+
# and giving up after the specified number of seconds.
|
13
14
|
# Displays elapsed and remaining times on the terminal.
|
15
|
+
# Outputs the time elapsed and the time to go.
|
14
16
|
#
|
15
17
|
# @param predicate something that can be called with .() or .call
|
16
18
|
# that returns a truthy value that indicates no further retries are necessary
|
@@ -5,7 +5,7 @@ module TrickBag
|
|
5
5
|
|
6
6
|
# NOTE! If the gem you are testing defines a .gemspec file,
|
7
7
|
# then this approach may be eliminated by instead
|
8
|
-
# running the following command in the project root (thank you,
|
8
|
+
# running the following command in the project root (thank you, Robb Kidd):
|
9
9
|
|
10
10
|
# bundle exec ruby -e "require 'my_gem_name'"
|
11
11
|
|
data/lib/trick_bag/version.rb
CHANGED
@@ -5,6 +5,7 @@ require 'trick_bag/functional/functional'
|
|
5
5
|
|
6
6
|
|
7
7
|
module TrickBag
|
8
|
+
module Functional
|
8
9
|
|
9
10
|
describe 'Composite predicates' do
|
10
11
|
|
@@ -17,15 +18,15 @@ module TrickBag
|
|
17
18
|
context "none?" do
|
18
19
|
|
19
20
|
specify "returns true when all are false" do
|
20
|
-
expect(TrickBag.none_with_object?(all_false_funcs, 1)).to eq(true)
|
21
|
+
expect(TrickBag::Functional.none_with_object?(all_false_funcs, 1)).to eq(true)
|
21
22
|
end
|
22
23
|
|
23
24
|
specify "returns false when all are true" do
|
24
|
-
expect(TrickBag.none_with_object?(all_true_funcs, 1)).to eq(false)
|
25
|
+
expect(TrickBag::Functional.none_with_object?(all_true_funcs, 1)).to eq(false)
|
25
26
|
end
|
26
27
|
|
27
28
|
specify "returns false when some are false and some are true" do
|
28
|
-
expect(TrickBag.none_with_object?(mixed_true_false_funcs, 1)).to eq(false)
|
29
|
+
expect(TrickBag::Functional.none_with_object?(mixed_true_false_funcs, 1)).to eq(false)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
@@ -33,15 +34,15 @@ module TrickBag
|
|
33
34
|
context "any?" do
|
34
35
|
|
35
36
|
specify "returns false when all are false" do
|
36
|
-
expect(TrickBag.any_with_object?(all_false_funcs, 1)).to eq(false)
|
37
|
+
expect(TrickBag::Functional.any_with_object?(all_false_funcs, 1)).to eq(false)
|
37
38
|
end
|
38
39
|
|
39
40
|
specify "returns true when all are true" do
|
40
|
-
expect(TrickBag.any_with_object?(all_true_funcs, 1)).to eq(true)
|
41
|
+
expect(TrickBag::Functional.any_with_object?(all_true_funcs, 1)).to eq(true)
|
41
42
|
end
|
42
43
|
|
43
44
|
specify "returns true when some are false and some are true" do
|
44
|
-
expect(TrickBag.any_with_object?(mixed_true_false_funcs, 1)).to eq(true)
|
45
|
+
expect(TrickBag::Functional.any_with_object?(mixed_true_false_funcs, 1)).to eq(true)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
@@ -49,16 +50,17 @@ module TrickBag
|
|
49
50
|
context "all?" do
|
50
51
|
|
51
52
|
specify "returns false when all are false" do
|
52
|
-
expect(TrickBag.all_with_object?(all_false_funcs, 1)).to eq(false)
|
53
|
+
expect(TrickBag::Functional.all_with_object?(all_false_funcs, 1)).to eq(false)
|
53
54
|
end
|
54
55
|
|
55
56
|
specify "returns true when all are true" do
|
56
|
-
expect(TrickBag.all_with_object?(all_true_funcs, 1)).to eq(true)
|
57
|
+
expect(TrickBag::Functional.all_with_object?(all_true_funcs, 1)).to eq(true)
|
57
58
|
end
|
58
59
|
|
59
60
|
specify "returns false when some are false and some are true" do
|
60
|
-
expect(TrickBag.all_with_object?(mixed_true_false_funcs, 1)).to eq(false)
|
61
|
+
expect(TrickBag::Functional.all_with_object?(mixed_true_false_funcs, 1)).to eq(false)
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
66
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trick_bag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.67.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Bennett
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: os
|
@@ -140,7 +140,7 @@ files:
|
|
140
140
|
- lib/trick_bag.rb
|
141
141
|
- lib/trick_bag/collections/collection_access.rb
|
142
142
|
- lib/trick_bag/collections/linked_list.rb
|
143
|
-
- lib/trick_bag/core_types.rb
|
143
|
+
- lib/trick_bag/core_types/core_types.rb
|
144
144
|
- lib/trick_bag/enumerables/buffered_enumerable.rb
|
145
145
|
- lib/trick_bag/enumerables/compound_enumerable.rb
|
146
146
|
- lib/trick_bag/enumerables/endless_last_enumerable.rb
|
@@ -174,7 +174,7 @@ files:
|
|
174
174
|
- spec/spec_helper.rb
|
175
175
|
- spec/trick_bag/collections/collection_access_spec.rb
|
176
176
|
- spec/trick_bag/collections/linked_list_spec.rb
|
177
|
-
- spec/trick_bag/core_types_spec.rb
|
177
|
+
- spec/trick_bag/core_types/core_types_spec.rb
|
178
178
|
- spec/trick_bag/enumerables/buffered_enumerable_spec.rb
|
179
179
|
- spec/trick_bag/enumerables/compound_enumerable_spec.rb
|
180
180
|
- spec/trick_bag/enumerables/endless_last_enumerable_spec.rb
|
@@ -231,7 +231,7 @@ test_files:
|
|
231
231
|
- spec/spec_helper.rb
|
232
232
|
- spec/trick_bag/collections/collection_access_spec.rb
|
233
233
|
- spec/trick_bag/collections/linked_list_spec.rb
|
234
|
-
- spec/trick_bag/core_types_spec.rb
|
234
|
+
- spec/trick_bag/core_types/core_types_spec.rb
|
235
235
|
- spec/trick_bag/enumerables/buffered_enumerable_spec.rb
|
236
236
|
- spec/trick_bag/enumerables/compound_enumerable_spec.rb
|
237
237
|
- spec/trick_bag/enumerables/endless_last_enumerable_spec.rb
|