net-imap 0.5.9 → 0.5.10

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: 9a31378c34762136e5fc341801a0b4073157dc6c35df6aae3254d3f7b90a07b7
4
- data.tar.gz: cbf787e39ecfde5a7af0061baba54eae3d7b12077679854ea62b335fc9b48798
3
+ metadata.gz: 261794e07175481d35e146b718183fc057a3a54e2fd9958b25918c6bd4178ec4
4
+ data.tar.gz: 2568eb1d284b3f1662d1cf0c1bc79eb65722fa3ba8dc03072b52fbd3716c9294
5
5
  SHA512:
6
- metadata.gz: fd0c8a34fa212bb42a55e943bf8184c614256b52da4ac13bdddb48f74c8517f5c7b72addb2153af42d76f2a8bcf42627ceb34e874b7842d8a6dfd542ba577578
7
- data.tar.gz: 91dd4d1d35582abb9e4fd0df64c63ee5c9320f3404d548bff0a4023e32dc9a6ddd6b90cd1cc221e637a4719f3cc5699d57cc337ea17a6454b3aa7d7be9ffb423
6
+ metadata.gz: 357279f77c69c27b78924847216afad6c806abb7bfee5f0c95aab6c397cb10298440a59cb32b9f75a4174e6965d6bfe48a5e847e20d9098845033e8453f73302
7
+ data.tar.gz: e3c29888d787de23a843bfb9ff9194d1fa136763e9d9bcf36800953362f7611c489da1f9150ee2a23baa571125f4f2af2cebe4ee4666447783e355bd9995eb3a
data/Gemfile CHANGED
@@ -16,6 +16,7 @@ gem "test-unit-ruby-core", git: "https://github.com/ruby/test-unit-ruby-core"
16
16
 
17
17
  gem "benchmark", require: false
18
18
  gem "benchmark-driver", require: false
19
+ gem "vernier", require: false, platform: :mri
19
20
 
20
21
  group :test do
21
22
  gem "simplecov", require: false
@@ -173,7 +173,7 @@ module Net
173
173
  SUBSCRIBED = :Subscribed
174
174
 
175
175
  # The mailbox is a remote mailbox.
176
- REMOTE = :Remove
176
+ REMOTE = :Remote
177
177
 
178
178
  # Alias for NO_INFERIORS, to match the \IMAP spelling.
179
179
  NOINFERIORS = NO_INFERIORS
@@ -84,7 +84,7 @@ module Net
84
84
  #
85
85
  # # Other inputs are normalized
86
86
  # set = Net::IMAP::SequenceSet([1, 2, [3..7, 5], 6..10, 2048, 1024])
87
- # set.valid_string #=> "1:10,55,1024:2048"
87
+ # set.valid_string #=> "1:10,1024,2048"
88
88
  # set.frozen? #=> false
89
89
  #
90
90
  # unfrozen = set
@@ -107,7 +107,7 @@ module Net
107
107
  #
108
108
  # # Other inputs are normalized
109
109
  # set = Net::IMAP::SequenceSet[1, 2, [3..7, 5], 6..10, 2048, 1024]
110
- # set.valid_string #=> "1:10,55,1024:2048"
110
+ # set.valid_string #=> "1:10,1024,2048"
111
111
  # set.frozen? #=> true
112
112
  #
113
113
  # frozen = set
@@ -396,6 +396,23 @@ module Net
396
396
  STARS = [:*, ?*, -1].freeze
397
397
  private_constant :STARS
398
398
 
399
+ INSPECT_MAX_LEN = 512
400
+ INSPECT_TRUNCATE_LEN = 16
401
+ private_constant :INSPECT_MAX_LEN, :INSPECT_TRUNCATE_LEN
402
+
403
+ # /(,\d+){100}\z/ is shockingly slow on huge strings.
404
+ # /(,\d{0,10}){100}\z/ is ok, but ironically, Regexp.linear_time? is false.
405
+ #
406
+ # This unrolls all nested quantifiers. It's much harder to read, but it's
407
+ # also the fastest out of all the versions I tested.
408
+ nz_uint32 = /[1-9](?:\d(?:\d(?:\d(?:\d(?:\d(?:\d(?:\d(?:\d(?:\d)?)?)?)?)?)?)?)?)?/
409
+ num_or_star = /#{nz_uint32}|\*/
410
+ entry = /#{num_or_star}(?::#{num_or_star})?/
411
+ entries = ([entry] * INSPECT_TRUNCATE_LEN).join(",")
412
+ INSPECT_ABRIDGED_HEAD_RE = /\A#{entries},/
413
+ INSPECT_ABRIDGED_TAIL_RE = /,#{entries}\z/
414
+ private_constant :INSPECT_ABRIDGED_HEAD_RE, :INSPECT_ABRIDGED_TAIL_RE
415
+
399
416
  class << self
400
417
 
401
418
  # :call-seq:
@@ -465,7 +482,7 @@ module Net
465
482
  # set = Net::IMAP::SequenceSet.new("1,2,3:7,5,6:10,2048,1024")
466
483
  # set.valid_string #=> "1,2,3:7,5,6:10,2048,1024"
467
484
  # set = Net::IMAP::SequenceSet.new(1, 2, 3..7, 5, 6..10, 2048, 1024)
468
- # set.valid_string #=> "1:10,55,1024:2048"
485
+ # set.valid_string #=> "1:10,1024,2048"
469
486
  #
470
487
  # With no arguments (or +nil+) creates an empty sequence set. Note that
471
488
  # an empty sequence set is invalid in the \IMAP grammar.
@@ -530,7 +547,10 @@ module Net
530
547
  # accepted by ::new.
531
548
  def replace(other)
532
549
  case other
533
- when SequenceSet then initialize_dup(other)
550
+ when SequenceSet then
551
+ modifying! # short circuit before doing any work
552
+ @tuples = other.deep_copy_tuples
553
+ @string = other.instance_variable_get(:@string)
534
554
  when String then self.string = other
535
555
  else clear; merge other
536
556
  end
@@ -559,29 +579,31 @@ module Net
559
579
  # If the set was created from a single string, it is not normalized. If
560
580
  # the set is updated the string will be normalized.
561
581
  #
562
- # Related: #valid_string, #normalized_string, #to_s
582
+ # Related: #valid_string, #normalized_string, #to_s, #inspect
563
583
  def string; @string ||= normalized_string if valid? end
564
584
 
565
585
  # Returns an array with #normalized_string when valid and an empty array
566
586
  # otherwise.
567
587
  def deconstruct; valid? ? [normalized_string] : [] end
568
588
 
569
- # Assigns a new string to #string and resets #elements to match. It
570
- # cannot be set to an empty string—assign +nil+ or use #clear instead.
571
- # The string is validated but not normalized.
589
+ # Assigns a new string to #string and resets #elements to match.
590
+ # Assigning +nil+ or an empty string are equivalent to calling #clear.
591
+ #
592
+ # Non-empty strings are validated but not normalized.
572
593
  #
573
- # Use #add or #merge to add a string to an existing set.
594
+ # Use #add, #merge, or #append to add a string to an existing set.
574
595
  #
575
596
  # Related: #replace, #clear
576
- def string=(str)
577
- if str.nil?
597
+ def string=(input)
598
+ if input.nil?
578
599
  clear
579
- else
580
- modifying! # redundant check, to normalize the error message for JRuby
581
- str = String.try_convert(str) or raise ArgumentError, "not a string"
600
+ elsif (str = String.try_convert(input))
601
+ modifying! # short-circuit before parsing the string
582
602
  tuples = str_to_tuples str
583
603
  @tuples, @string = [], -str
584
604
  tuples_add tuples
605
+ else
606
+ raise ArgumentError, "expected a string or nil, got #{input.class}"
585
607
  end
586
608
  str
587
609
  end
@@ -590,7 +612,7 @@ module Net
590
612
  # string when the set is empty. Note that an empty set is invalid in the
591
613
  # \IMAP syntax.
592
614
  #
593
- # Related: #valid_string, #normalized_string, #to_s
615
+ # Related: #string, #valid_string, #normalized_string, #inspect
594
616
  def to_s; string || "" end
595
617
 
596
618
  # Freezes and returns the set. A frozen SequenceSet is Ractor-safe.
@@ -1623,21 +1645,60 @@ module Net
1623
1645
  #
1624
1646
  # Returns +nil+ when the set is empty.
1625
1647
  #
1626
- # Related: #normalize!, #normalize
1648
+ # Related: #normalize!, #normalize, #string, #to_s
1627
1649
  def normalized_string
1628
1650
  @tuples.empty? ? nil : -@tuples.map { tuple_to_str _1 }.join(",")
1629
1651
  end
1630
1652
 
1653
+ # Returns an inspection string for the SequenceSet.
1654
+ #
1655
+ # Net::IMAP::SequenceSet.new.inspect
1656
+ # #=> "Net::IMAP::SequenceSet()"
1657
+ #
1658
+ # Net::IMAP::SequenceSet(1..5, 1024, 15, 2000).inspect
1659
+ # #=> 'Net::IMAP::SequenceSet("1:5,15,1024,2000")'
1660
+ #
1661
+ # Frozen sets have slightly different output:
1662
+ #
1663
+ # Net::IMAP::SequenceSet.empty.inspect
1664
+ # #=> "Net::IMAP::SequenceSet.empty"
1665
+ #
1666
+ # Net::IMAP::SequenceSet[1..5, 1024, 15, 2000].inspect
1667
+ # #=> 'Net::IMAP::SequenceSet["1:5,15,1024,2000"]'
1668
+ #
1669
+ # Large sets (by number of #entries) have abridged output, with only the
1670
+ # first and last entries:
1671
+ #
1672
+ # Net::IMAP::SequenceSet(((1..5000) % 2).to_a).inspect
1673
+ # #=> #<Net::IMAP::SequenceSet 2500 entries "1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,...(2468 entries omitted)...,4969,4971,4973,4975,4977,4979,4981,4983,4985,4987,4989,4991,4993,4995,4997,4999">
1674
+ #
1675
+ # Related: #to_s, #string
1631
1676
  def inspect
1632
- if empty?
1633
- (frozen? ? "%s.empty" : "#<%s empty>") % [self.class]
1634
- elsif frozen?
1635
- "%s[%p]" % [self.class, to_s]
1677
+ case (count = count_entries)
1678
+ when 0
1679
+ (frozen? ? "%s.empty" : "%s()") % [self.class]
1680
+ when ..INSPECT_MAX_LEN
1681
+ (frozen? ? "%s[%p]" : "%s(%p)") % [self.class, to_s]
1636
1682
  else
1637
- "#<%s %p>" % [self.class, to_s]
1683
+ if @string
1684
+ head = @string[INSPECT_ABRIDGED_HEAD_RE]
1685
+ tail = @string[INSPECT_ABRIDGED_TAIL_RE]
1686
+ else
1687
+ head = export_string_entries(@tuples.first(INSPECT_TRUNCATE_LEN)) + ","
1688
+ tail = "," + export_string_entries(@tuples.last(INSPECT_TRUNCATE_LEN))
1689
+ end
1690
+ '#<%s %d entries "%s...(%d entries omitted)...%s"%s>' % [
1691
+ self.class, count,
1692
+ head, count - INSPECT_TRUNCATE_LEN * 2, tail,
1693
+ frozen? ? " (frozen)" : "",
1694
+ ]
1638
1695
  end
1639
1696
  end
1640
1697
 
1698
+ private def count_entries
1699
+ @string ? @string.count(",") + 1 : @tuples.count
1700
+ end
1701
+
1641
1702
  ##
1642
1703
  # :method: to_sequence_set
1643
1704
  # :call-seq: to_sequence_set -> self
@@ -1676,6 +1737,8 @@ module Net
1676
1737
 
1677
1738
  attr_reader :tuples # :nodoc:
1678
1739
 
1740
+ def deep_copy_tuples; @tuples.map { _1.dup } end # :nodoc:
1741
+
1679
1742
  private
1680
1743
 
1681
1744
  def remain_frozen(set) frozen? ? set.freeze : set end
@@ -1683,13 +1746,12 @@ module Net
1683
1746
 
1684
1747
  # frozen clones are shallow copied
1685
1748
  def initialize_clone(other)
1686
- other.frozen? ? super : initialize_dup(other)
1749
+ @tuples = other.deep_copy_tuples unless other.frozen?
1750
+ super
1687
1751
  end
1688
1752
 
1689
1753
  def initialize_dup(other)
1690
- modifying! # redundant check, to normalize the error message for JRuby
1691
- @tuples = other.tuples.map(&:dup)
1692
- @string = other.string&.-@
1754
+ @tuples = other.deep_copy_tuples
1693
1755
  super
1694
1756
  end
1695
1757
 
@@ -1741,6 +1803,10 @@ module Net
1741
1803
  def to_tuple_int(obj) STARS.include?(obj) ? STAR_INT : nz_number(obj) end
1742
1804
  def from_tuple_int(num) num == STAR_INT ? :* : num end
1743
1805
 
1806
+ def export_string_entries(entries)
1807
+ -entries.map { tuple_to_str _1 }.join(",")
1808
+ end
1809
+
1744
1810
  def tuple_to_str(tuple) tuple.uniq.map{ from_tuple_int _1 }.join(":") end
1745
1811
  def str_to_tuples(str) str.split(",", -1).map! { str_to_tuple _1 } end
1746
1812
  def str_to_tuple(str)
data/lib/net/imap.rb CHANGED
@@ -788,7 +788,7 @@ module Net
788
788
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
789
789
  #
790
790
  class IMAP < Protocol
791
- VERSION = "0.5.9"
791
+ VERSION = "0.5.10"
792
792
 
793
793
  # Aliases for supported capabilities, to be used with the #enable command.
794
794
  ENABLE_ALIASES = {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.5.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
@@ -129,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  requirements: []
132
- rubygems_version: 3.6.7
132
+ rubygems_version: 3.6.9
133
133
  specification_version: 4
134
134
  summary: Ruby client api for Internet Message Access Protocol
135
135
  test_files: []