fugit 1.10.1 → 1.11.1

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: dfedcc6bdc1657d09a8c7a4dc23ad0cdb7abe7a78d5ec007477794361f678aaf
4
- data.tar.gz: 617b8fb21468bb4a6c17294a9c856b2975dd67f5cb6add6569047545a92305ee
3
+ metadata.gz: da93feee9bdfd44a793ce2b45b81109c0f7cd08ff9a930d15629a29c6a381e07
4
+ data.tar.gz: 32d9b447734805d3b58ae64c70a6699b931ef4fb4e6a76d8f279e66d4b5cb7df
5
5
  SHA512:
6
- metadata.gz: c22968c95e4986b091ed498a848a1f18800cb3217af2e1a1a999ac15a979c8fce8243672f33704e125e09c4dde1adb38b33c0ee3c639f355003d00e734e097a1
7
- data.tar.gz: 99f6e2170a616663f536ddf9d1b627130ff0e4f20277a2b7011b24ecaa50e43ad2a9ce944c51ace296a6151df71583d7f6e921023a91e9aa82c7820389b39abb
6
+ metadata.gz: e7ac7afec4cfdcfdac22e5d2113892a0c7cb1f790d205bc32ecaea75c30f6ceb73af811824712c6781b480831f2a09479a6344af0d9b3c0ee92ae5cff7ef6c38
7
+ data.tar.gz: d87ecc490a49f19680891a82979903987843b5853ecfdc9ebee57d0b047fa4dffa96dfbbde43ef5d3011dbd07d492ac8f7a151fa6354478050c18efae9b911e4
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## fugit 1.11.1 released 2024-08-15
6
+
7
+ * Prevent nat parsing chocking on long input (> 256 chars), gh-104
8
+
9
+
10
+ ## fugit 1.11.0 released 2024-04-24
11
+
12
+ * Revert gh-86 ban on `every 27 hours` / `* */27 * * *` for gh-103
13
+
14
+
5
15
  ## fugit 1.10.1 released 2024-02-29
6
16
 
7
17
  * Fix on Ruby 2.2.6 thanks to @aunghtain, gh-93
data/CREDITS.md CHANGED
@@ -1,6 +1,10 @@
1
1
 
2
2
  # fugit credits
3
3
 
4
+ * https://github.com/personnumber3377, gh-104 Fugit.parse choke on long input
5
+ * Michael Scrivo, https://github.com/mscrivo, gh-103
6
+ * Benjamin Darcet, https://github.com/bdarcet gh-95 gh-96 et-orbi #rweek
7
+ * https://github.com/franckduche gh-95 gh-96 et-orbi #rweek
4
8
  * https://hithub.com/aunghtain, gh-93, include oneliner vs Ruby 2.6.6
5
9
  * Marcos Belluci, https://github.com/delbetu, gh-88, 1st and last nat
6
10
  * Michael Reinsch, https://github.com/mreinsch, gh-84 and gh-85
data/README.md CHANGED
@@ -34,13 +34,14 @@ The intersection of those two projects is where fugit is born:
34
34
  ### Projects using fugit
35
35
 
36
36
  * [arask](https://github.com/Ebbe/arask) - "Automatic RAils taSKs" uses fugit to parse cron strings
37
- * [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron) - recent versions of Sidekiq-Cron use fugit to parse cron strings
37
+ * [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron) - uses fugit to parse cron strings since version 1.0.0, it was using rufus-scheduler previously
38
38
  * [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) - as seen above
39
39
  * [flor](https://github.com/floraison/flor) - used in the [cron](https://github.com/floraison/flor/blob/master/doc/procedures/cron.md) procedure
40
40
  * [que-scheduler](https://github.com/hlascelles/que-scheduler) - a reliable job scheduler for [que](https://github.com/chanks/que)
41
41
  * [serial_scheduler](https://github.com/grosser/serial_scheduler) - ruby task scheduler without threading
42
42
  * [delayed_cron_job](https://github.com/codez/delayed_cron_job) - an extension to Delayed::Job that allows you to set cron expressions for your jobs
43
43
  * [GoodJob](https://github.com/bensheldon/good_job) - a multithreaded, Postgres-based, Active Job backend for Ruby on Rails
44
+ * [Solid Queue](https://github.com/rails/solid_queue) - a DB-based queuing backend for Active Job, designed with simplicity and performance in mind
44
45
  * ...
45
46
 
46
47
  ## `Fugit.parse(s)`
@@ -140,6 +141,8 @@ c = Fugit.parse_cron('0 12 * * mon#2')
140
141
 
141
142
  # `#next` and `#prev` return Enumerable instances
142
143
  #
144
+ # These two methods are available since fugit 1.10.0.
145
+ #
143
146
  c.next(Time.parse('2024-02-16 12:00:00'))
144
147
  .take(3)
145
148
  .map(&:to_s)
@@ -157,6 +160,8 @@ c.prev(Time.parse('2024-02-16 12:00:00'))
157
160
  # instances that correspond to the occurrences of the cron within
158
161
  # the time range
159
162
  #
163
+ # This method is available since fugit 1.10.0.
164
+ #
160
165
  c.within(Time.parse('2024-02-16 12:00')..Time.parse('2024-08-01 12:00'))
161
166
  .map(&:to_s)
162
167
  # => [ '2024-03-11 12:00:00',
@@ -251,6 +256,8 @@ p Fugit.parse_cron('59 6 1-7& * 2&').next_time('2020-03-15').to_s
251
256
 
252
257
  Fugit understands `0 5 * * 1#1` or `0 5 * * mon#1` as "each first Monday of the month, at 05:00".
253
258
 
259
+ The hash extension can only be used in the day-of-week field.
260
+
254
261
  ```ruby
255
262
  '0 5 * * 1#1' #
256
263
  '0 5 * * mon#1' # the first Monday of the month at 05:00
@@ -273,6 +280,8 @@ Fugit understands `0 5 * * 1#1` or `0 5 * * mon#1` as "each first Monday of the
273
280
 
274
281
  Fugit, since 1.1.10, also understands cron strings like "`9 0 * * sun%2`" which can be read as "every other Sunday at 9am".
275
282
 
283
+ The modulo extension can only be used in the day-of-week field.
284
+
276
285
  For odd Sundays, one can write `9 0 * * sun%2+1`.
277
286
 
278
287
  It can be combined, as in `9 0 * * sun%2,tue%3+2`
@@ -465,6 +474,8 @@ Fugit::Nat.parse('every day at 16:15 nada 18:30', multi: true)
465
474
 
466
475
  `multi: false` is the default behaviour, return a single `Fugit::Cron` instance or nil when it cannot parse.
467
476
 
477
+ Please note that "nat" input is limited to 256 characters (fugit 1.11.1).
478
+
468
479
  ### Nat Midnight
469
480
 
470
481
  `"Every day at midnight"` is supported, but `"Every monday at midnight"` will be interpreted (as of Fugit <= 1.4.x) as `"Every monday at 00:00"`. Sorry about that.
data/fugit.gemspec CHANGED
@@ -41,7 +41,7 @@ Time tools for flor and the floraison project. Cron parsing and occurrence compu
41
41
  # this dependency appears in 'et-orbi'
42
42
 
43
43
  s.add_runtime_dependency 'raabro', '~> 1.4'
44
- s.add_runtime_dependency 'et-orbi', '~> 1', '>= 1.2.7'
44
+ s.add_runtime_dependency 'et-orbi', '~> 1', '>= 1.2.11'
45
45
 
46
46
  s.add_development_dependency 'rspec', '~> 3.8'
47
47
  s.add_development_dependency 'chronic', '~> 0.10'
data/lib/fugit/cron.rb CHANGED
@@ -46,7 +46,20 @@ module Fugit
46
46
  def do_parse(s)
47
47
 
48
48
  parse(s) ||
49
- fail(ArgumentError.new("invalid cron string #{s.inspect}"))
49
+ fail(ArgumentError.new("invalid cron string #{trunc(s)}"))
50
+ end
51
+
52
+ protected
53
+
54
+ def trunc(s)
55
+
56
+ if s.is_a?(String)
57
+ r = s.length > 28 ? s[0, 28] + "... len #{s.length}" : s
58
+ r.inspect
59
+ else
60
+ r = s.inspect
61
+ r.length > 35 ? s[0, 35] + '...' : r
62
+ end
50
63
  end
51
64
  end
52
65
 
@@ -264,6 +277,8 @@ module Fugit
264
277
  "please fill an issue at https://git.io/fjJC9"
265
278
  ) if (i += 1) > MAX_ITERATION_COUNT
266
279
 
280
+ #tt = t.time;
281
+ #puts " #{tt.strftime('%F %T %:z %A')} #{tt.rweek} #{tt.rweek % 2}"
267
282
  (ifrom == t.to_i) && (t.inc(1); next)
268
283
  month_match?(t) || (t.inc_month; next)
269
284
  day_match?(t) || (t.inc_day; next)
@@ -307,6 +322,8 @@ module Fugit
307
322
  "please fill an issue at https://git.io/fjJCQ"
308
323
  ) if (i += 1) > MAX_ITERATION_COUNT
309
324
 
325
+ #tt = t.time;
326
+ #puts " #{tt.strftime('%F %T %:z %A')} #{tt.rweek} #{tt.rweek % 4}"
310
327
  month_match?(t) || (t.dec_month; next)
311
328
  day_match?(t) || (t.dec_day; next)
312
329
  hour_match?(t) || (t.dec_hour; next)
@@ -565,7 +582,10 @@ module Fugit
565
582
 
566
583
  sta, edn, sla = r
567
584
 
568
- return false if sla && sla > max
585
+ #return false if sla && sla > max
586
+ #
587
+ # let it go, "* */24 * * *" and "* */27 * * *" are okay
588
+ # gh-86 and gh-103
569
589
 
570
590
  edn = max if sla && edn.nil?
571
591
 
@@ -258,7 +258,7 @@ module Fugit
258
258
  when Numeric then add_numeric(a)
259
259
  when Fugit::Duration then add_duration(a)
260
260
  when String then add_duration(self.class.parse(a))
261
- when ::Time, EtOrbi::EoTime then add_to_time(a)
261
+ when ::Time, ::EtOrbi::EoTime then add_to_time(a)
262
262
  else fail ArgumentError.new(
263
263
  "cannot add #{a.class} instance to a Fugit::Duration")
264
264
  end
data/lib/fugit/nat.rb CHANGED
@@ -7,6 +7,8 @@ module Fugit
7
7
  #
8
8
  module Nat
9
9
 
10
+ MAX_INPUT_LENGTH = 256
11
+
10
12
  class << self
11
13
 
12
14
  def parse(s, opts={})
@@ -17,6 +19,16 @@ module Fugit
17
19
 
18
20
  s = s.strip
19
21
 
22
+ if s.length > MAX_INPUT_LENGTH
23
+
24
+ fail ArgumentError.new(
25
+ "input too long for a nat string, " +
26
+ "#{s.length} > #{MAX_INPUT_LENGTH}"
27
+ ) if opts[:do_parse]
28
+
29
+ return nil
30
+ end
31
+
20
32
  #p s; Raabro.pp(Parser.parse(s, debug: 3), colours: true)
21
33
  #(p s; Raabro.pp(Parser.parse(s, debug: 1), colours: true)) rescue nil
22
34
 
@@ -29,7 +41,7 @@ module Fugit
29
41
 
30
42
  def do_parse(s, opts={})
31
43
 
32
- parse(s, opts) ||
44
+ parse(s, opts.merge(do_parse: true)) ||
33
45
  fail(ArgumentError.new("could not parse a nat #{s.inspect}"))
34
46
  end
35
47
  end
data/lib/fugit/parse.rb CHANGED
@@ -20,17 +20,34 @@ module Fugit
20
20
 
21
21
  opts[:at] = opts[:in] if opts.has_key?(:in)
22
22
 
23
- (opts[:cron] != false && parse_cron(s)) ||
24
- (opts[:duration] != false && parse_duration(s)) ||
25
- (opts[:nat] != false && parse_nat(s, opts)) ||
26
- (opts[:at] != false && parse_at(s)) ||
23
+ (opts[:cron] != false && parse_cron(s)) || # 542ms 616ms
24
+ (opts[:duration] != false && parse_duration(s)) || # 645ms # 534ms
25
+ (opts[:nat] != false && parse_nat(s, opts)) || # 2s # 35s
26
+ (opts[:at] != false && parse_at(s)) || # 568ms 622ms
27
27
  nil
28
28
  end
29
29
 
30
30
  def do_parse(s, opts={})
31
31
 
32
- parse(s, opts) ||
33
- fail(ArgumentError.new("found no time information in #{s.inspect}"))
32
+ opts[:at] = opts[:in] if opts.has_key?(:in)
33
+
34
+ result = nil
35
+ errors = []
36
+
37
+ %i[ cron duration nat at ]
38
+ .each { |k|
39
+ begin
40
+ result ||= (opts[k] != false && self.send("do_parse_#{k}", s))
41
+ rescue => err
42
+ errors << err
43
+ end }
44
+
45
+ return result if result
46
+
47
+ raise(
48
+ errors.find { |r| r.class != ArgumentError } ||
49
+ errors.first ||
50
+ ArgumentError.new("found no time information in #{s.inspect}"))
34
51
  end
35
52
 
36
53
  def parse_cronish(s, opts={})
data/lib/fugit.rb CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Fugit
5
5
 
6
- VERSION = '1.10.1'
6
+ VERSION = '1.11.1'
7
7
  end
8
8
 
9
9
  require 'time'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fugit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.1
4
+ version: 1.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-28 00:00:00.000000000 Z
11
+ date: 2024-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: raabro
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '1'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 1.2.7
36
+ version: 1.2.11
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '1'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 1.2.7
46
+ version: 1.2.11
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
49
  requirement: !ruby/object:Gem::Requirement