weak 0.3.1 → 0.4.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: bd14986fea0acdca768d90fa686370e5e2f92207e4bd82a55cbc17b53fa6f81d
4
- data.tar.gz: b3f39735d13792b488a837841fa2c3b10f164955bbb8e791127504f2236e5a8f
3
+ metadata.gz: de4d3b085987c7e4374f7921d0312730ddb5941170ca06328eb239a8928bb649
4
+ data.tar.gz: 199ae4143167bf3351cfd9c21d3525434692bf0ba04085bfc60df0dc0dde7cfd
5
5
  SHA512:
6
- metadata.gz: b005c22ef5a2a7d4d43a75ef6633e3b1c29347943e71515894885c134f014e4ecd4152522f758052a2a33c847417c3eaa2358ade5f3b5a22993c657a59aa63e1
7
- data.tar.gz: a76fa37a0b49c4dc305c899e1de3111452bb4f668779b688b13508cf16bc47759c74dfa5345d11a5e3a42b8d556ea6d27d0c742e8d11accf354e3f0f6d791389
6
+ metadata.gz: c386274b05c8a4bb347673cd51aff04977c88ecee16ba5678b10ffd95e78b56397752df958b3e79b8ae5d76034f32eb94c642cfc3de0aaca8117e7e3f9792969
7
+ data.tar.gz: fc50a65f6d0ccc286430d0917f102b742c90c1becbd9cfa22730e57f298da6ceba5c7011ddded19b767af89a2a5253f111c8e44428547e9ab2f65f656e9f9dcd
data/CHANGELOG.md CHANGED
@@ -2,40 +2,72 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [0.3.1] - 2026-01-16
5
+ ## [0.4.0] - 2026-06-23
6
6
 
7
- - Update changelog of 0.3.0 release
7
+ ### Changed
8
8
 
9
- ## [0.3.0] - 2026-01-16
9
+ - Improve documentation for `Weak::Set#delete?`
10
+ - Clarify humanistic usage policy
11
+ - Update Github actions
12
+ - Use [Common Changelog](https://common-changelog.org) style for the entire changelog
13
+ - Return the resolved proc from `Weak::Map#default_proc=` instead if the given value
10
14
 
11
- ### Features
15
+ ### Added
12
16
 
13
- - Add `Weak::Cache` as a thread-safe wrapper around `Weak::Map` to provide an object cache.
17
+ - Add documentation for remaining `Weak::Cache` methods.
18
+ - Run specs for JRuby 10.1
19
+
20
+ ### Fixed
21
+
22
+ - Fix error reporting on Github CI
23
+ - Do not clear `Weak::Map#default` if the object given to `Weak::Map#default_proc=` is invalid
24
+
25
+ ## [0.3.1] - 2026-01-16
26
+
27
+ ### Fixed
14
28
 
15
- ### Bug Fixes
29
+ - Update changelog of 0.3.0 release
16
30
 
17
- - Fix `Weak::Map#store` method alias to `Weak::Map#[]=`. Previously, it was errouneously aliased to `Weak::Map#[]`.
31
+ ## [0.3.0] - 2026-01-16
18
32
 
19
- ### Improvements
33
+ ### Changed
20
34
 
21
35
  - Adapt `Weak::Set#inspect` output to more resemble the output of `Set#inspect` in Ruby 4.0
22
36
  - Fix typos in code documentation
23
37
  - Use `require_relative` instead of require for all gem files
24
- - Add addititional specs for `Weak::Map`
25
38
  - Clarify humanistic usage policy
26
39
 
40
+ ### Added
41
+
42
+ - Add `Weak::Cache` as a thread-safe wrapper around `Weak::Map` to provide an object cache.
43
+ - Add addititional specs for `Weak::Map`
44
+
45
+ ### Fixed
46
+
47
+ - Fix `Weak::Map#store` method alias to `Weak::Map#[]=`. Previously, it was erroneously aliased to `Weak::Map#[]`.
48
+
27
49
  ## [0.2.1] - 2025-12-27
28
50
 
29
- - Fix typos in code documentation
51
+ ### Changed
52
+
30
53
  - Ignore some unnecessary methods defined on some `Weak::Set` implementations in `set_spec`
31
- - Run specs on JRuby 10 in Github Actions
32
- - Retry TruffleRuby rspec runs on Github Actions to avoid random failures due to flakey GC.
33
54
  - Extract `UNDEFINED` to its own file and require it where used.
55
+
56
+ ### Added
57
+
34
58
  - Add more details about the gem version in `Weak::Version`
59
+ - Run specs on JRuby 10 in Github Actions
60
+
61
+ ### Fixed
62
+
35
63
  - Handle object cycles in `pretty_print`.
64
+ - Retry TruffleRuby rspec runs on Github Actions to avoid random failures due to flakey GC.
65
+ - Fix typos in code documentation
36
66
 
37
67
  ## [0.2.0] - 2025-04-09
38
68
 
69
+ ### Added
70
+
39
71
  - Add `Weak::Map#delete_if`
40
72
  - Add `Weak::Map#keep_if`
41
73
  - Add `Weak::Map#reject!`
@@ -45,6 +77,8 @@
45
77
 
46
78
  ## [0.1.0] - 2025-03-14
47
79
 
80
+ ### Added
81
+
48
82
  - Initial version of `Weak::Set` to store an unordered collection of objects.
49
83
  - Initial version of `Weak::Map` to store key-value pairs of objects.
50
84
  - Support for Ruby 3.0 using the following impementations
@@ -54,4 +88,4 @@
54
88
 
55
89
  ## [0.0.1.pre] - 2025-02-05
56
90
 
57
- - First blank slate
91
+ First blank slate
data/README.md CHANGED
@@ -1,21 +1,21 @@
1
1
  # Weak
2
2
 
3
3
  [![gem version badge](https://badge.fury.io/rb/weak.svg)](https://rubygems.org/gems/weak)
4
- [![license badge](https://img.shields.io/badge/license-MIT-brightgreen.svg)](#license)
4
+ [![license badge](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/meineerde/weak/blob/main/LICENSE.txt)
5
5
  [![github repo badge](https://img.shields.io/badge/github-meineerde/weak-blue.svg)](https://github.com/meineerde/weak)
6
6
  [![documentation badge](https://img.shields.io/badge/docs-rubydoc.info-blue.svg)](https://www.rubydoc.info/gems/weak)
7
7
 
8
8
  [![code style: standard badge](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/standardrb/standard)
9
- [![CI status badge](https://github.com/meineerde/weak/actions/workflows/ci.yml/badge.svg)](https://github.com/meineerde/weak/actions/workflows/ci.yml)
9
+ [![CI status badge](https://github.com/meineerde/weak/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/meineerde/weak/actions/workflows/ci.yml?query=branch%3Amain)
10
10
  [![Coverage Status](https://coveralls.io/repos/github/meineerde/weak/badge.svg?branch=main)](https://coveralls.io/github/meineerde/weak?branch=main)
11
11
 
12
- Weak is a Ruby library which implements collections of unordered values without strong object references.
12
+ Weak is a Ruby library which implements collections of unordered values with weak object references.
13
13
 
14
14
  We provide multiple classes which behave similar to their standard-library counterparts. However, all elements are only weakly referenced. That way, all elements can be garbage collected and silently removed from the collection unless they are still referenced from some other live object.
15
15
 
16
16
  ## Weak::Set
17
17
 
18
- `Weak::Set` behaves similar to the [Set](https://docs.ruby-lang.org/en/3.4/Set.html) class of the Ruby standard library, but all values are only weakly referenced. That way, all values can be garbage collected and silently removed from the set unless they are still referenced from some other live object.
18
+ [`Weak::Set`](https://www.rubydoc.info/gems/weak/Weak/Set) behaves similar to the [Set](https://docs.ruby-lang.org/en/3.4/Set.html) class of the Ruby standard library, but all values are only weakly referenced. That way, all values can be garbage collected and silently removed from the set unless they are still referenced from some other live object.
19
19
 
20
20
  > [!CAUTION]
21
21
  > `Weak::Set` objects are not inherently thread-safe. When accessing a weak set from multiple threads or fibers, you MUST use a mutex or another locking mechanism.
@@ -43,11 +43,11 @@ set
43
43
 
44
44
  ## Weak::Map
45
45
 
46
- `Weak::Map` behaves similar to a `Hash` or an `ObjectSpace::WeakMap` in Ruby (aka. MRI, aka. YARV).
46
+ [`Weak::Map`](https://www.rubydoc.info/gems/weak/Weak/Map) behaves similar to a `Hash` or an `ObjectSpace::WeakMap` in Ruby (aka. MRI, aka. YARV).
47
47
  Both keys and values are weak references, allowing either of them to be garbage collected. If either the key or the value of a pair is garbage collected, the entire pair will be removed from the `Weak::Map`.
48
48
 
49
49
  > [!CAUTION]
50
- > `Weak::Map` objects are not inherently thread-safe. When accessing a weak map from multiple threads or fibers, you MUST use a mutex or another locking mechanism.
50
+ > `Weak::Map` objects are not inherently thread-safe. When accessing a weak map from multiple threads or fibers, you MUST use a mutex or another locking mechanism. You can also use `Weak::Cache` as a thread-safe option.
51
51
 
52
52
  Compared to the `Hash` class, there are a few differences:
53
53
 
@@ -72,7 +72,7 @@ map
72
72
 
73
73
  ## Weak::Cache
74
74
 
75
- `Weak::Cache` is a thread-safe wrapper around `Weak::Map`. The class behaves similar to an `ActiveSupport::Cache::Store`.
75
+ [`Weak::Cache`](https://www.rubydoc.info/gems/weak/Weak/Cache) is a thread-safe wrapper around `Weak::Map`. The class behaves similar to an `ActiveSupport::Cache::Store`.
76
76
 
77
77
  > [!TIP]
78
78
  > `Weak::Cache` objects can safely be used from multiple threads and fibers concurrently without any additional locks.
@@ -100,7 +100,7 @@ Please refer to the documentation at:
100
100
  - [📘 Documentation](https://www.rubydoc.info/gems/weak)
101
101
  - [💥 Development Documentation](https://www.rubydoc.info/github/meineerde/weak) of the [main branch](https://github.com/meineerde/weak/tree/main)
102
102
 
103
- The Weak collections use Ruby's [ObjectSpace::WeakMap](https://docs.ruby-lang.org/en/3.4/ObjectSpace/WeakMap.html) under the hood. Unfortunately, different Ruby implementations and versions such as Ruby (aka. MRI, aka. YARV), JRuby, or TruffleRuby show quite diverse behavior in their respective `ObjectSpace::WeakMap` implementations. To provide a unified behavior on all supported Rubies, we use multiple different storage strategies.
103
+ The Weak collections use Ruby's [ObjectSpace::WeakMap](https://docs.ruby-lang.org/en/3.4/ObjectSpace/WeakMap.html) under the hood. Unfortunately, different Ruby implementations and versions such as Ruby (aka. MRI, aka. YARV), JRuby, or TruffleRuby implement diverse behavior in their respective `ObjectSpace::WeakMap` implementations. To provide a unified behavior on all supported Rubies, we use multiple different storage strategies.
104
104
 
105
105
  The appropriate strategy is selected automatically. Their exposed behavior should be identical across all implementations. If you experience diverging behavior, we consider this a bug. Please [open an issue](https://github.com/meineerde/weak/issues/new) and describe the diverging or unexpected behavior.
106
106
 
@@ -246,7 +246,7 @@ end
246
246
 
247
247
  ### Weak::Cache Example
248
248
 
249
- We can simplify the above example by using `Weak::Cache`.
249
+ Insted of manually locking a `Weak::Map` to get or create the lock for provided `object` as in the above example, we can leverage a `Weak::Cache` object which is inherently threadsafe. This allows us to update the above example as follows:
250
250
 
251
251
  ```ruby
252
252
  require "weak/cache"
@@ -293,9 +293,9 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/meinee
293
293
 
294
294
  Weak is available as free and open source under the terms of the [MIT License](https://github.com/meineerde/weak/blob/main/LICENSE.txt).
295
295
 
296
- This license does not preclude you from using Weak with AI-encumbered or AI-associated projects, but you do not have the author's consent to do so. This may seem like a contradiction, but copyright is a blunt tool that does not in general have the humanistic nuance to describe something like "you can legally do this thing, but if you do, you're an asshole."
296
+ You do not have the author's consent to use Weak in projects associated with so-called "AI" (generative AI, LLMs, ...), even though the MIT license does not specifically preclude you from doing so. This may seem like a contradiction, but copyright is a blunt tool that does not in general have the humanistic nuance to describe something like "you can legally do this thing, but if you do, you're an asshole."
297
297
 
298
- We also explicitly affirm: Trans Rights Are Human Rights. If you do not agree, please refrain from using Weak.
298
+ We also explicitly affirm: Trans Rights Are Human Rights. We explicitly discourage the usage of Weak in any environment where this basic decency is not universally afforded.
299
299
 
300
300
  (Thanks to [Cassandra Granade](https://codeberg.org/cgranade/do#license-and-ai-policy) for the inspiration.)
301
301
 
data/lib/weak/cache.rb CHANGED
@@ -65,6 +65,7 @@ module Weak
65
65
  @mutex.synchronize { super }
66
66
  end
67
67
 
68
+ # (see Weak::Map#each_key)
68
69
  def each_key(&block)
69
70
  return enum_for(__method__) { size } unless block_given?
70
71
  keys.each(&block)
@@ -83,8 +84,8 @@ module Weak
83
84
  alias_method :include?, :exist?
84
85
  alias_method :key?, :exist?
85
86
 
86
- # Fetches data from the cache, using the given `key`. If there is a value in
87
- # the cache for the given key, that value is returned.
87
+ # Fetches or sets data from the cache, using the given `key`. If there is a
88
+ # value in the cache for the given key, that value is returned.
88
89
  #
89
90
  # If there is no value in the cache (a cache miss), then the given block
90
91
  # will be passed the key and executed in the event of a cache miss. The
@@ -122,6 +123,9 @@ module Weak
122
123
  self
123
124
  end
124
125
 
126
+ # @return [String] a string containing a human-readable representation of
127
+ # the weak cache, e.g.,
128
+ # `"#<Weak::Cache {key1 => value1, key2 => value2, ...}>"`
125
129
  def inspect
126
130
  @mutex.synchronize { "#<#{self.class} #{@map._inspect}>" }
127
131
  end
@@ -155,6 +159,7 @@ module Weak
155
159
  end
156
160
  alias_method :[], :read
157
161
 
162
+ # (see Weak::Map#size)
158
163
  def size
159
164
  @mutex.synchronize { @map.size }
160
165
  end
@@ -39,7 +39,7 @@ module Weak
39
39
  #
40
40
  # The `ObjectSpace::WeakMap` does not allow to explicitly delete entries. We
41
41
  # emulate this by setting the garbage-collectible value of a deleted entry
42
- # to a simple new object. This value will be garbage collected on the next
42
+ # to a new "empty" object. This object will be garbage collected on the next
43
43
  # GC run which will then remove the entry. When accessing elements, we
44
44
  # delete and filter out these recently deleted entries.
45
45
  module StrongKeys
@@ -17,10 +17,10 @@ module Weak
17
17
  # the key or the value can be independently garbage collected. If either of
18
18
  # them vanishes, the entry is removed.
19
19
  #
20
- # The `ObjectSpace::WeakMap` does not allow to explicitly delete entries.
21
- # We emulate this by setting the garbage-collectible value of a deleted
22
- # entry to a simple new object. This value will be garbage collected on the
23
- # next GC run which will then remove the entry. When accessing elements, we
20
+ # The `ObjectSpace::WeakMap` does not allow to explicitly delete entries. We
21
+ # emulate this by setting the garbage-collectible value of a deleted entry
22
+ # to a new "empty" object. This value will be garbage collected on the next
23
+ # GC run which will then remove the entry. When accessing elements, we
24
24
  # delete and filter out these recently deleted entries.
25
25
  module WeakKeys
26
26
  include Deletable
data/lib/weak/map.rb CHANGED
@@ -39,8 +39,8 @@ module Weak
39
39
  #
40
40
  # ## Implementation Details
41
41
  #
42
- # The various Ruby implementations and versions show quite diverse behavior in
43
- # their respective `ObjectSpace::WeakMap` implementations. To provide a
42
+ # The supported Ruby implementations and versions implement diverse behavior
43
+ # in their respective `ObjectSpace::WeakMap` implementations. To provide a
44
44
  # unified behavior on all implementations, we use different storage
45
45
  # strategies:
46
46
  #
@@ -406,10 +406,9 @@ module Weak
406
406
  # @return [Proc, nil] the new default proc
407
407
  # @raise [TypeError] if the given `proc` can not be converted to a `Proc`.
408
408
  def default_proc=(proc)
409
- @default_value = nil
410
- return @default_proc = nil if proc.nil?
411
-
412
- if Proc === proc
409
+ if proc.nil?
410
+ default_proc = nil
411
+ elsif Proc === proc
413
412
  default_proc = proc
414
413
  elsif proc.respond_to?(:to_proc)
415
414
  default_proc = proc.to_proc
@@ -421,16 +420,16 @@ module Weak
421
420
  raise TypeError, "no implicit conversion of #{proc.class} into Proc"
422
421
  end
423
422
 
424
- if default_proc.lambda?
423
+ if default_proc&.lambda?
425
424
  arity = default_proc.arity
426
425
  if arity != 2 && (arity >= 0 || arity < -3)
427
426
  arity = -arity - 1 if arity < 0
428
427
  raise TypeError, "default_proc takes two arguments (2 for #{arity})"
429
428
  end
430
429
  end
431
- @default_proc = default_proc
432
430
 
433
- proc
431
+ @default_value = nil
432
+ @default_proc = default_proc
434
433
  end
435
434
 
436
435
  # Deletes every key-value pair from `self` for which the given block
@@ -24,11 +24,11 @@ module Weak
24
24
  # `Integer`, the object_id is generally is not garbage collected anyway but
25
25
  # allows to uniquely identity the object.
26
26
  #
27
- # The `ObjectSpace::WeakMap` class does not allow to explicitly delete
28
- # entries. We emulate this by setting the garbage-collectible value of a
29
- # deleted entry to a simple new object. This value will be garbage collected
30
- # on the next GC run which will then remove the entry. When accessing
31
- # elements, we delete and filter out these recently deleted entries.
27
+ # The `ObjectSpace::WeakMap` does not allow to explicitly delete entries. We
28
+ # emulate this by setting the garbage-collectible value of a deleted entry
29
+ # to a new "empty" object. This value will be garbage collected on the next
30
+ # GC run which will then remove the entry. When accessing elements, we
31
+ # delete and filter out these recently deleted entries.
32
32
  module StrongKeys
33
33
  class DeletedEntry; end
34
34
  private_constant :DeletedEntry
@@ -16,7 +16,7 @@ module Weak
16
16
  #
17
17
  # The `ObjectSpace::WeakMap` does not allow to explicitly delete entries. We
18
18
  # emulate this by setting the garbage-collectible value of a deleted entry
19
- # to a simple new object. This value will be garbage collected on the next
19
+ # to a new "empty" object. This value will be garbage collected on the next
20
20
  # GC run which will then remove the entry. When accessing elements, we
21
21
  # delete and filter out these recently deleted entries.
22
22
  module WeakKeys
data/lib/weak/set.rb CHANGED
@@ -37,8 +37,8 @@ module Weak
37
37
  #
38
38
  # ## Implementation Details
39
39
  #
40
- # The various Ruby implementations and versions show quite diverse behavior in
41
- # their respective `ObjectSpace::WeakMap` implementations. To provide a
40
+ # The supported Ruby implementations and versions implement diverse behavior
41
+ # in their respective `ObjectSpace::WeakMap` implementations. To provide a
42
42
  # unified behavior on all implementations, we use different storage
43
43
  # strategies:
44
44
  #
@@ -125,12 +125,15 @@ module Weak
125
125
  # @return [self]
126
126
 
127
127
  # @!macro weak_set_method_delete_question
128
- # Deletes the given object from `self` and returns `self` if it was
129
- # present in the set. If the object was not in the set, returns `nil`.
128
+ # Deletes the given object from `self` and returns `self` if the given
129
+ # object was present in the set. If the object was not in the set,
130
+ # returns `nil`.
130
131
  #
131
132
  # @param obj [Object]
132
- # @return [self, nil] `self` if the given object was deleted from the set
133
- # or `nil` if the object was not part of the set
133
+ # @return [self, nil] `self` if the given object was present in the set
134
+ # and was deleted accordingly or `nil` if the object was not part of
135
+ # the set
136
+ # @see Weak::Set#delete
134
137
  # @!macro weak_set_note_object_equality
135
138
 
136
139
  # @!macro weak_set_method_each
@@ -424,6 +427,7 @@ module Weak
424
427
  #
425
428
  # @param obj [Object] an object to delete from the weak set
426
429
  # @return [self] always returns self
430
+ # @see #delete?
427
431
  # @!macro weak_set_note_object_equality
428
432
  def delete(obj)
429
433
  delete?(obj)
data/lib/weak/version.rb CHANGED
@@ -13,10 +13,10 @@ module Weak
13
13
  MAJOR = 0
14
14
  # MINOR version. It is incremented after adding functionality in a
15
15
  # backwards-compatible manner
16
- MINOR = 3
16
+ MINOR = 4
17
17
  # PATCH version. It is incremented when making backwards-compatible
18
18
  # bug-fixes.
19
- PATCH = 1
19
+ PATCH = 0
20
20
  # PRERELEASE suffix. Set to a alphanumeric string on any pre-release
21
21
  # versions like beta or RC releases; `nil` on regular releases
22
22
  PRERELEASE = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weak
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Holger Just
@@ -10,10 +10,9 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: |
13
- The Weak library provides a Weak::Set class to store an unordered list of
14
- objects and a Weak::Map class to store a key-value map. The collection
15
- classes only hold weak references to all elements so they can be
16
- garbage-collected when there are no more references left.
13
+ The Weak library provides collections of unordered values. Each of the
14
+ provided collection classes only holds weak references to all elements so
15
+ they can be garbage-collected when there are no more references left.
17
16
  executables: []
18
17
  extensions: []
19
18
  extra_rdoc_files: []
@@ -47,7 +46,7 @@ metadata:
47
46
  homepage_uri: https://github.com/meineerde/weak
48
47
  source_code_uri: https://github.com/meineerde/weak
49
48
  changelog_uri: https://github.com/meineerde/weak/blob/main/CHANGELOG.md
50
- documentation_uri: https://www.rubydoc.info/gems/weak/0.3.1
49
+ documentation_uri: https://www.rubydoc.info/gems/weak/0.4.0
51
50
  rdoc_options: []
52
51
  require_paths:
53
52
  - lib