rantly 1.2.0 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79dd7dec8dc33c88121e8f18e937c066730f92d190e34657742245d5d2ad39ce
4
- data.tar.gz: 0d0a1435d25e7ad2d1948d45040a6524b79425011289331484b35b0387d7d750
3
+ metadata.gz: 13f1bd6f943416c68aff13d50f505ff92485c1613c4c01b52d8cbc78eb027b66
4
+ data.tar.gz: af1de15faf3be9d3984c1343eb59b65081d0d8c12916c07434e0353ee37a4204
5
5
  SHA512:
6
- metadata.gz: 7f652b90718f7d9f32c1e88995d85371cd87af8d247b7def676a171b58f170cb08d0d29f54cb68259a7f4f42c64299d7c1b8f1741095c9dc174e4208904535b0
7
- data.tar.gz: 54a9a7f6c94741379d58268fb56a0fb47e8787868e5f8610904a2c551d65041e6042470a3a3514acd0a585a2e75859b26f73605b0a55e5352f0a913a83b4742c
6
+ metadata.gz: 2f24ffc2cb269a377fb0b5c0e40897ba417ef991d5e219c0a0423458b8b5e760102ba1f32c157190f982419da8f8e6a32e628e1012a0d070d36045609e0a7255
7
+ data.tar.gz: bb6c3265fbfcd2a0d339dbdf87d6f38afb9e71c5f4f58531c92ce99d784ad5e66405f0a26b6caf6aed9a7cc86bebe6b4194273c389073041b7890abb79f51c03
@@ -4,10 +4,13 @@ cache: bundler
4
4
  after_success:
5
5
  - coveralls
6
6
  rvm:
7
- - 2.0.0
8
- - 2.1.9
9
- - 2.2.6
10
- - 2.3.3
11
7
  - 2.4.0
12
- - jruby-1.7.26
13
- - jruby-9.1.7.0
8
+ - 2.5.1
9
+ - ruby-head
10
+ - jruby-9.2.0.0
11
+ - jruby-head
12
+
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: jruby-head
16
+ - rvm: ruby-head
@@ -3,6 +3,38 @@ All notable changes to rantly will be documented in this file. The curated log b
3
3
 
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [Master](https://github.com/rantly-rb/rantly/compare/2.0.0...master) (unreleased)
7
+
8
+ ### New features
9
+
10
+ ### Bug fixes
11
+
12
+ ### Changes
13
+
14
+
15
+ ## [2.0.0](https://github.com/rantly-rb/rantly/compare/1.2.0...2.0.0) - 2019-01-08
16
+
17
+ ### New features
18
+ - Add support for float ranges to `range` generator
19
+ - [Issue #60](https://github.com/rantly-rb/rantly/issues/60)
20
+ - thanks [Trevor Brown][Trevor Brown]
21
+
22
+ ### Bug fixes
23
+ - `range` generator returns `nil` for invalid ranges
24
+ - [Issue #60](https://github.com/rantly-rb/rantly/issues/60)
25
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
26
+ - `choose` generator returns `nil` when no values are given
27
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
28
+
29
+ ### Changes
30
+ - Only support for Ruby >= 2.4 and JRuby >= 9.2
31
+ - [Issue #42](https://github.com/rantly-rb/rantly/issues/42) and [issue #37](https://github.com/rantly-rb/rantly/issues/37)
32
+ - Do not render all shrinking levels, only the failing case and the minimal failed data.
33
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
34
+ - Improve failure/success messages
35
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
36
+
37
+
6
38
  ## [1.2.0](https://github.com/abargnesi/rantly/compare/1.1.0...1.2.0) - 2018-08-29
7
39
  ### New features
8
40
  - Allow to generate floats using Gaussian distribution
@@ -59,3 +91,4 @@ This project adheres to [Semantic Versioning](http://semver.org/).
59
91
  [Oleksii Fedorov]: https://github.com/waterlink
60
92
  [Ana María Martínez Gómez]: https://github.com/Ana06
61
93
  [Víctor Gallego]: https://github.com/vicgalle
94
+ [Trevor Brown]: https://github.com/Stratus3D
data/Gemfile CHANGED
@@ -1,8 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :development, :test do
4
- gem 'rake', '~> 12.0.0'
4
+ gem 'coveralls', '>= 0', require: false
5
5
  gem 'minitest', '~> 5.10.0'
6
+ gem 'rake', '~> 12.0.0'
6
7
  gem 'simplecov', '>= 0'
7
- gem 'coveralls', '>= 0', :require => false
8
+
9
+ gem 'rubocop'
8
10
  end
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem version](https://badge.fury.io/rb/rantly.svg)](https://badge.fury.io/rb/rantly)
2
2
  [![Build Status](https://travis-ci.org/rantly-rb/rantly.svg?branch=master)](https://travis-ci.org/rantly-rb/rantly)
3
+ [![Coverage Status](https://coveralls.io/repos/github/rantly-rb/rantly/badge.svg?branch=master)](https://coveralls.io/github/rantly-rb/rantly?branch=master)
3
4
 
4
5
  # Imperative Random Data Generator and Quickcheck
5
6
 
@@ -9,13 +10,19 @@ Rantly is basically a recursive descent interpreter, each of its method returns
9
10
 
10
11
  Its implementation has no alien mathematics inside. Completely side-effect-free-free.
11
12
 
13
+ ![img](/logo/Rantly.png)
14
+
12
15
 
13
16
  # Install
14
17
 
18
+ Rantly requires Ruby 2.4 or higher. To install Rantly add it to your Gemfile or run:
19
+
15
20
  ```ruby
16
21
  $ gem install rantly
17
22
  ```
18
23
 
24
+ You can try it in the console by running:
25
+
19
26
  ```ruby
20
27
  $ irb -rrantly
21
28
  > Rantly { [integer,float] } # same as Rantly.value { integer }
@@ -401,8 +408,10 @@ Normal arrays or hashes are not shrinked.
401
408
 
402
409
  Thanks to [all contributors](https://github.com/rantly-rb/rantly/graphs/contributors). :cupid: New contributors are welcome! :wink:
403
410
 
411
+ [Logotype](/logo) designed by: [@Richardbmx](https://github.com/richardbmx)
412
+
404
413
 
405
414
  # License
406
415
 
407
- Code published under MIT License, Copyright (c) 2009 Howard Yeh. See [LICENSE](https://github.com/abargnesi/rantly/LICENSE).
416
+ Code published under MIT License, Copyright (c) 2009 Howard Yeh. See [LICENSE](/LICENSE).
408
417
 
data/Rakefile CHANGED
@@ -1,22 +1,35 @@
1
1
  require 'rake'
2
2
 
3
+ task default: %i[test rubocop]
4
+
3
5
  require 'rake/testtask'
6
+
4
7
  Rake::TestTask.new(:test) do |test|
5
8
  test.libs << 'lib' << 'test'
6
9
  test.pattern = 'test/**/*_test.rb'
7
10
  test.verbose = true
8
11
  end
9
12
 
10
- task :default => :test
13
+ require 'rubocop/rake_task'
14
+
15
+ desc 'Run RuboCop'
16
+ RuboCop::RakeTask.new(:rubocop) do |task|
17
+ task.options = ['--display-cop-names']
18
+ end
19
+
20
+ RuboCop::RakeTask.new('rubocop:auto_gen_config') do |task|
21
+ task.options = ['--display-cop-names', '--auto-gen-config', '--auto-gen-only-exclude']
22
+ end
11
23
 
12
24
  require 'rdoc/task'
25
+
13
26
  Rake::RDocTask.new do |rdoc|
14
27
  require 'yaml'
15
28
  if File.exist?('VERSION.yml')
16
29
  config = YAML.load(File.read('VERSION.yml'))
17
30
  version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
18
31
  else
19
- version = ""
32
+ version = ''
20
33
  end
21
34
 
22
35
  rdoc.rdoc_dir = 'rdoc'
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :build:
3
- :major: 1
4
- :minor: 2
3
+ :major: 2
4
+ :minor: 0
5
5
  :patch: 0
@@ -1,14 +1,14 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__)) unless
2
+ $LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(__dir__)
3
3
 
4
4
  class Rantly
5
5
  end
6
6
 
7
7
  require 'rantly/generator'
8
8
 
9
- def Rantly(n=1,&block)
9
+ def Rantly(n = 1, &block)
10
10
  if n > 1
11
- Rantly.map(n,&block)
11
+ Rantly.map(n, &block)
12
12
  else
13
13
  Rantly.value(&block)
14
14
  end
@@ -1,6 +1,6 @@
1
1
  module Rantly::Data
2
2
  def email
3
- "#{string(:alnum)}@#{string(:alnum)}.#{sized(3){string(:alpha)}}".downcase
3
+ "#{string(:alnum)}@#{string(:alnum)}.#{sized(3) { string(:alpha) }}".downcase
4
4
  end
5
5
 
6
6
  def password
@@ -1,5 +1,4 @@
1
1
  class Rantly
2
-
3
2
  class << self
4
3
  attr_writer :default_size
5
4
  def singleton
@@ -11,20 +10,20 @@ class Rantly
11
10
  @default_size || 6
12
11
  end
13
12
 
14
- def each(n,limit=10,&block)
15
- gen.each(n,limit,&block)
13
+ def each(n, limit = 10, &block)
14
+ gen.each(n, limit, &block)
16
15
  end
17
16
 
18
- def map(n,limit=10,&block)
19
- gen.map(n,limit,&block)
17
+ def map(n, limit = 10, &block)
18
+ gen.map(n, limit, &block)
20
19
  end
21
20
 
22
- def value(limit=10,&block)
23
- gen.value(limit,&block)
21
+ def value(limit = 10, &block)
22
+ gen.value(limit, &block)
24
23
  end
25
24
 
26
25
  def gen
27
- self.singleton
26
+ singleton
28
27
  end
29
28
  end
30
29
 
@@ -32,7 +31,7 @@ class Rantly
32
31
  end
33
32
 
34
33
  class TooManyTries < RuntimeError
35
- def initialize(limit,nfailed)
34
+ def initialize(limit, nfailed)
36
35
  @limit = limit
37
36
  @nfailed = nfailed
38
37
  end
@@ -41,38 +40,37 @@ class Rantly
41
40
  @nfailed
42
41
  end
43
42
 
44
- def to_s
45
- "Exceed gen limit #{@limit}: #{@nfailed} failed guards"
46
- end
43
+ attr_reader :limit
47
44
  end
48
45
 
49
46
  # limit attempts to 10 times of how many things we want to generate
50
- def each(n,limit=10,&block)
51
- generate(n,limit,block)
47
+ def each(n, limit = 10, &block)
48
+ generate(n, limit, block)
52
49
  end
53
50
 
54
- def map(n,limit=10,&block)
51
+ def map(n, limit = 10, &block)
55
52
  acc = []
56
- generate(n,limit,block) do |val|
53
+ generate(n, limit, block) do |val|
57
54
  acc << val
58
55
  end
59
56
  acc
60
57
  end
61
58
 
62
- def value(limit=10,&block)
63
- generate(1,limit,block) do |val|
59
+ def value(limit = 10, &block)
60
+ generate(1, limit, block) do |val|
64
61
  return val
65
62
  end
66
63
  end
67
64
 
68
- def generate(n,limit_arg,gen_block,&handler)
65
+ def generate(n, limit_arg, gen_block, &handler)
69
66
  limit = n * limit_arg
70
67
  nfailed = 0
71
68
  nsuccess = 0
72
69
  while nsuccess < n
73
- raise TooManyTries.new(limit_arg*n,nfailed) if limit < 0
70
+ raise TooManyTries.new(limit_arg * n, nfailed) if limit.zero?
71
+
74
72
  begin
75
- val = self.instance_eval(&gen_block)
73
+ val = instance_eval(&gen_block)
76
74
  rescue GuardFailure
77
75
  nfailed += 1
78
76
  limit -= 1
@@ -80,7 +78,7 @@ class Rantly
80
78
  end
81
79
  nsuccess += 1
82
80
  limit -= 1
83
- handler.call(val) if handler
81
+ yield(val) if handler
84
82
  end
85
83
  end
86
84
 
@@ -100,87 +98,89 @@ class Rantly
100
98
  end
101
99
 
102
100
  def guard(test)
103
- unless test
104
- raise GuardFailure.new
105
- else
106
- true
107
- end
101
+ return true if test
102
+
103
+ raise GuardFailure
108
104
  end
109
105
 
110
106
  def size
111
107
  @size || Rantly.default_size
112
108
  end
113
109
 
114
- def sized(n,&block)
115
- raise "size needs to be greater than zero" if n < 0
110
+ def sized(n, &block)
111
+ raise 'size needs to be greater than zero' if n.negative?
112
+
116
113
  old_size = @size
117
114
  @size = n
118
- r = self.instance_eval(&block)
115
+ r = instance_eval(&block)
119
116
  @size = old_size
120
- return r
117
+ r
121
118
  end
122
119
 
123
120
  # wanna avoid going into Bignum when calling range with these.
124
121
  INTEGER_MAX = (2**(0.size * 8 - 2) - 1) / 2
125
- INTEGER_MIN = -(INTEGER_MAX)
126
- def integer(limit=nil)
122
+ INTEGER_MIN = -INTEGER_MAX
123
+ def integer(limit = nil)
127
124
  case limit
128
125
  when Range
129
126
  hi = limit.end
130
127
  lo = limit.begin
131
128
  when Integer
132
- raise "n should be greater than zero" if limit < 0
133
- hi, lo = limit, -limit
129
+ raise 'n should be greater than zero' if limit.negative?
130
+
131
+ hi = limit
132
+ lo = -limit
134
133
  else
135
- hi, lo = INTEGER_MAX, INTEGER_MIN
134
+ hi = INTEGER_MAX
135
+ lo = INTEGER_MIN
136
136
  end
137
- range(lo,hi)
137
+ range(lo, hi)
138
138
  end
139
139
 
140
140
  def positive_integer
141
141
  range(0)
142
142
  end
143
143
 
144
- def float(distribution=nil, params={})
144
+ def float(distribution = nil, params = {})
145
145
  case distribution
146
146
  when :normal
147
147
  params[:center] ||= 0
148
148
  params[:scale] ||= 1
149
- raise "The distribution scale should be greater than zero" unless params[:scale] > 0
149
+ raise 'The distribution scale should be greater than zero' if params[:scale].negative?
150
+
150
151
  # Sum of 6 draws from a uniform distribution give as a draw of a normal
151
152
  # distribution centered in 3 (central limit theorem).
152
- ([rand, rand, rand, rand, rand, rand].reduce(0, :+) - 3) * params[:scale] + params[:center]
153
+ ([rand, rand, rand, rand, rand, rand].sum - 3) * params[:scale] + params[:center]
153
154
  else
154
155
  rand
155
156
  end
156
157
  end
157
158
 
158
- def range(lo=nil,hi=nil)
159
- lo ||= INTEGER_MIN
160
- hi ||= INTEGER_MAX
161
- rand(hi+1-lo) + lo
159
+ def range(lo = INTEGER_MIN, hi = INTEGER_MAX)
160
+ rand(lo..hi)
162
161
  end
163
162
 
164
- def call(gen,*args)
163
+ def call(gen, *args)
165
164
  case gen
166
165
  when Symbol
167
- return self.send(gen,*args)
166
+ send(gen, *args)
168
167
  when Array
169
- raise "empty array" if gen.empty?
170
- return self.send(gen[0],*gen[1..-1])
168
+ raise 'empty array' if gen.empty?
169
+
170
+ send(gen[0], *gen[1..-1])
171
171
  when Proc
172
- return self.instance_eval(&gen)
172
+ instance_eval(&gen)
173
173
  else
174
174
  raise "don't know how to call type: #{gen}"
175
175
  end
176
176
  end
177
177
 
178
178
  def branch(*gens)
179
- self.call(choose(*gens))
179
+ call(choose(*gens))
180
180
  end
181
181
 
182
182
  def choose(*vals)
183
- vals[range(0,vals.length-1)]
183
+ vals[range(0, vals.length - 1)] if vals.length.positive?
184
184
  end
185
185
 
186
186
  def literal(value)
@@ -188,52 +188,50 @@ class Rantly
188
188
  end
189
189
 
190
190
  def boolean
191
- range(0,1) == 0 ? true : false
191
+ range(0, 1).zero?
192
192
  end
193
193
 
194
194
  def freq(*pairs)
195
195
  pairs = pairs.map do |pair|
196
196
  case pair
197
197
  when Symbol, String, Proc
198
- [1,pair]
198
+ [1, pair]
199
199
  when Array
200
- unless pair.first.is_a?(Integer)
201
- [1] + pair
202
- else
200
+ if pair.first.is_a?(Integer)
203
201
  pair
202
+ else
203
+ [1] + pair
204
204
  end
205
205
  end
206
206
  end
207
- total = pairs.inject(0) { |sum,p| sum + p.first }
208
- raise(RuntimeError, "Illegal frequency:#{pairs.inspect}") if total == 0
209
- pos = range(1,total)
207
+ total = pairs.inject(0) { |sum, p| sum + p.first }
208
+ raise("Illegal frequency:#{pairs.inspect}") if total.zero?
209
+
210
+ pos = range(1, total)
210
211
  pairs.each do |p|
211
212
  weight, gen, *args = p
212
- if pos <= p[0]
213
- return self.call(gen,*args)
214
- else
215
- pos -= weight
216
- end
213
+ return call(gen, *args) if pos <= p[0]
214
+
215
+ pos -= weight
217
216
  end
218
217
  end
219
218
 
220
- def array(n=self.size,&block)
221
- n.times.map { self.instance_eval(&block) }
219
+ def array(n = size, &block)
220
+ n.times.map { instance_eval(&block) }
222
221
  end
223
222
 
224
- def dict(n=self.size,&block)
223
+ def dict(n = size, &block)
225
224
  h = {}
226
225
  each(n) do
227
- k,v = instance_eval(&block)
228
- h[k] = v if guard(!h.has_key?(k))
226
+ k, v = instance_eval(&block)
227
+ h[k] = v if guard(!h.key?(k))
229
228
  end
230
229
  h
231
230
  end
232
231
 
233
232
  module Chars
234
-
235
233
  class << self
236
- ASCII = (0..127).to_a.each_with_object("") { |i, obj| obj << i }
234
+ ASCII = (0..127).to_a.each_with_object('') { |i, obj| obj << i }
237
235
 
238
236
  def of(regexp)
239
237
  ASCII.scan(regexp).to_a.map! { |char| char[0].ord }
@@ -254,41 +252,35 @@ class Rantly
254
252
  XDIGIT = Chars.of(/[[:xdigit:]]/)
255
253
  ASCII = Chars.of(/./)
256
254
 
257
-
258
255
  CLASSES = {
259
- :alnum => ALNUM,
260
- :alpha => ALPHA,
261
- :blank => BLANK,
262
- :cntrl => CNTRL,
263
- :digit => DIGIT,
264
- :graph => GRAPH,
265
- :lower => LOWER,
266
- :print => PRINT,
267
- :punct => PUNCT,
268
- :space => SPACE,
269
- :upper => UPPER,
270
- :xdigit => XDIGIT,
271
- :ascii => ASCII,
272
- }
273
-
256
+ alnum: ALNUM,
257
+ alpha: ALPHA,
258
+ blank: BLANK,
259
+ cntrl: CNTRL,
260
+ digit: DIGIT,
261
+ graph: GRAPH,
262
+ lower: LOWER,
263
+ print: PRINT,
264
+ punct: PUNCT,
265
+ space: SPACE,
266
+ upper: UPPER,
267
+ xdigit: XDIGIT,
268
+ ascii: ASCII
269
+ }.freeze
274
270
  end
275
271
 
276
- def string(char_class=:print)
272
+ def string(char_class = :print)
277
273
  chars = case char_class
278
274
  when Regexp
279
275
  Chars.of(char_class)
280
276
  when Symbol
281
277
  Chars::CLASSES[char_class]
282
278
  end
283
- raise "bad arg" unless chars
279
+ raise 'bad arg' unless chars
284
280
 
285
- char_strings = chars.map { |c| c.chr }
281
+ char_strings = chars.map(&:chr)
286
282
  str = Array.new(size)
287
- current_index = 0
288
- while current_index < size
289
- str[current_index] = char_strings.sample
290
- current_index += 1
291
- end
283
+ size.times { |i| str[i] = char_strings.sample }
292
284
  str.join
293
285
  end
294
286
  end