ice_nine 0.10.0 → 0.11.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.
Files changed (59) hide show
  1. checksums.yaml +7 -15
  2. data/.travis.yml +8 -7
  3. data/Gemfile +10 -0
  4. data/Gemfile.devtools +5 -4
  5. data/README.md +4 -24
  6. data/benchmarks/speed.rb +4 -2
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/reek.yml +9 -2
  10. data/config/rubocop.yml +0 -1
  11. data/ice_nine.gemspec +1 -0
  12. data/lib/ice_nine.rb +24 -9
  13. data/lib/ice_nine/core_ext/object.rb +17 -3
  14. data/lib/ice_nine/freezer.rb +43 -3
  15. data/lib/ice_nine/freezer/array.rb +6 -8
  16. data/lib/ice_nine/freezer/false_class.rb +2 -2
  17. data/lib/ice_nine/freezer/hash.rb +22 -9
  18. data/lib/ice_nine/freezer/hash/state.rb +3 -3
  19. data/lib/ice_nine/freezer/module.rb +2 -2
  20. data/lib/ice_nine/freezer/nil_class.rb +2 -2
  21. data/lib/ice_nine/freezer/no_freeze.rb +5 -6
  22. data/lib/ice_nine/freezer/numeric.rb +2 -2
  23. data/lib/ice_nine/freezer/object.rb +7 -8
  24. data/lib/ice_nine/freezer/range.rb +7 -8
  25. data/lib/ice_nine/freezer/rubinius.rb +2 -2
  26. data/lib/ice_nine/freezer/struct.rb +2 -2
  27. data/lib/ice_nine/freezer/symbol.rb +2 -2
  28. data/lib/ice_nine/freezer/true_class.rb +2 -2
  29. data/lib/ice_nine/support/recursion_guard.rb +48 -28
  30. data/lib/ice_nine/version.rb +3 -3
  31. data/spec/integration/ice_nine/class_methods/deep_freeze_bang_spec.rb +21 -0
  32. data/spec/integration/ice_nine/class_methods/deep_freeze_spec.rb +5 -254
  33. data/spec/shared/array_deep_freeze_shared_spec.rb +9 -0
  34. data/spec/shared/hash_deep_freeze_shared_spec.rb +23 -0
  35. data/spec/shared/ice_nine_deep_freeze_shared_spec.rb +263 -0
  36. data/spec/shared/no_freeze_deep_freeze_shared_spec.rb +19 -0
  37. data/spec/shared/object_deep_freeze_shared_spec.rb +19 -0
  38. data/spec/shared/range_deep_freeze_shared_spec.rb +13 -0
  39. data/spec/unit/ice_nine/class_methods/deep_freeze_bang_spec.rb +24 -0
  40. data/spec/unit/ice_nine/class_methods/deep_freeze_spec.rb +6 -19
  41. data/spec/unit/ice_nine/core_ext/object/deep_freeze_bang_spec.rb +24 -0
  42. data/spec/unit/ice_nine/core_ext/object/deep_freeze_spec.rb +3 -9
  43. data/spec/unit/ice_nine/freezer/array/class_methods/deep_freeze_spec.rb +0 -14
  44. data/spec/unit/ice_nine/freezer/false_class/class_methods/deep_freeze_spec.rb +1 -7
  45. data/spec/unit/ice_nine/freezer/hash/class_methods/deep_freeze_spec.rb +1 -29
  46. data/spec/unit/ice_nine/freezer/module/class_methods/deep_freeze_spec.rb +1 -7
  47. data/spec/unit/ice_nine/freezer/nil_class/class_methods/deep_freeze_spec.rb +1 -7
  48. data/spec/unit/ice_nine/freezer/no_freeze/class_methods/deep_freeze_spec.rb +3 -23
  49. data/spec/unit/ice_nine/freezer/numeric/class_methods/deep_freeze_spec.rb +3 -12
  50. data/spec/unit/ice_nine/freezer/object/class_methods/deep_freeze_spec.rb +0 -18
  51. data/spec/unit/ice_nine/freezer/range/class_methods/deep_freeze_spec.rb +0 -18
  52. data/spec/unit/ice_nine/freezer/struct/class_methods/deep_freeze_spec.rb +1 -11
  53. data/spec/unit/ice_nine/freezer/symbol/class_methods/deep_freeze_spec.rb +1 -7
  54. data/spec/unit/ice_nine/freezer/true_class/class_methods/deep_freeze_spec.rb +1 -7
  55. data/spec/unit/ice_nine/recursion_guard/frozen/guard_spec.rb +28 -0
  56. data/spec/unit/ice_nine/recursion_guard/object_set/guard_spec.rb +31 -0
  57. data/spec/unit/object/deep_freeze_spec.rb +3 -9
  58. metadata +54 -41
  59. data/spec/unit/ice_nine/recursion_guard/class_methods/guard_spec.rb +0 -33
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YWEyOTlkYzI1MTM2YTg3YjdmMTg0MzU1MzA5NjQwOTBkNzViOTg3NQ==
5
- data.tar.gz: !binary |-
6
- ZDM3ZmJkYzE4MjFjZTdiOGMyODJhNTg3NzJiNmNmNjJlYjE1MTM4OQ==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- NGFlY2QxNDNmOWE2MDBjYmUyMzE5ZTU2NzE4ZmQxNDQ1OTMzNTFkZmFlNDJj
10
- YjlkODVhNWI3MmFiYzBmZTA0ZTViZjg0YmJjZDNhMmZjZDk4NTA1MzQzYzdm
11
- YWI3N2QzOTZkMGQwMDU5ODIxMmFlOWNjMzJmMzlkOGY3YzRlMzA=
12
- data.tar.gz: !binary |-
13
- YzQ5ZWY3NjQ4ZTJjNjYzZjMxZGI4Nzk3MGI1OGEzZmQ2NjQ5ZDExOTU0NDM1
14
- OTRlNWY2ZDFiMTEzNDhkNTcwZmE4NTc4NTE2NWU1NGJjM2M2YTg4MDdjM2Q4
15
- N2JiMjlmYzM2Mzk3YjQ3YTJkNzBkODdjM2JlNzMwNzNmNDc5ODU=
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1f7071ad57746e7737cabbd2b77cb04f716d0338
4
+ data.tar.gz: f042013897a106e927f81857121b7ef2c2d118fd
5
+ SHA512:
6
+ metadata.gz: 4a8b26471b093168d8b769ee344b8b9e47c579d321f2f604438b79246899868089ededcec51238fa59727ae3bbc5c46d13fb7a3c5769ab2cc48815ade54a7d9c
7
+ data.tar.gz: 45623b5d9fa123b9901167b648121643dea9b055652a476c1af1be9ed4f8a47ab669c7f37e818f8da1717d5a6aa4bd436db7616a2427f5fbab92ee398f06b2d1
@@ -1,20 +1,21 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
  bundler_args: --without yard guard benchmarks
3
- script: "bundle exec rake ci"
4
+ script: "bundle exec rake ci:metrics"
4
5
  rvm:
5
6
  - 1.9.3
6
7
  - 2.0.0
7
8
  - ruby-head
8
- - rbx-19mode
9
+ - rbx
9
10
  matrix:
10
11
  include:
11
12
  - rvm: jruby-19mode
12
- env: JRUBY_OPTS="$JRUBY_OPTS --debug"
13
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
14
+ - rvm: jruby-20mode
15
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
13
16
  - rvm: jruby-head
14
- env: JRUBY_OPTS="$JRUBY_OPTS --debug"
15
- allow_failures:
16
- - rvm: ruby-head # travis broken
17
- - rvm: rbx-19mode # mutant fails
17
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
18
+ fast_finish: true
18
19
  notifications:
19
20
  irc:
20
21
  channels:
data/Gemfile CHANGED
@@ -4,6 +4,16 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
+ platform :rbx do
8
+ gem 'racc', '~> 1.4.10'
9
+ gem 'rubinius-coverage', '~> 2.0.3'
10
+ gem 'rubysl-bigdecimal', '~> 2.0.2'
11
+ gem 'rubysl-coverage', '~> 2.0.3'
12
+ gem 'rubysl-json', '~> 2.0.2'
13
+ gem 'rubysl-logger', '~> 2.0.0'
14
+ gem 'rubysl-singleton', '~> 2.0.0'
15
+ end
16
+
7
17
  group :development, :test do
8
18
  gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
9
19
  end
@@ -30,16 +30,17 @@ group :guard do
30
30
  end
31
31
 
32
32
  group :metrics do
33
- gem 'coveralls', '~> 0.6.7'
33
+ gem 'coveralls', '~> 0.7.0'
34
34
  gem 'flay', '~> 2.4.0'
35
- gem 'flog', '~> 4.1.1'
35
+ gem 'flog', '~> 4.2.0'
36
36
  gem 'reek', '~> 1.3.2'
37
- gem 'rubocop', '~> 0.13.0'
37
+ gem 'rubocop', '~> 0.14.1'
38
38
  gem 'simplecov', '~> 0.7.1'
39
39
  gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
40
40
 
41
41
  platforms :ruby_19, :ruby_20 do
42
- gem 'mutant', git: 'https://github.com/mbj/mutant.git'
42
+ gem 'mutant', '~> 0.3.0.rc3', git: 'https://github.com/mbj/mutant.git'
43
+ gem 'unparser', '~> 0.1.3', git: 'https://github.com/mbj/unparser.git'
43
44
  gem 'yard-spellcheck', '~> 0.1.5'
44
45
  end
45
46
  end
data/README.md CHANGED
@@ -19,42 +19,22 @@ Examples
19
19
  --------
20
20
 
21
21
  ```ruby
22
- # Freezes most objects
22
+ # Deep freezes most kinds of objects
23
23
  hash = IceNine.deep_freeze('a' => '1')
24
24
  array = IceNine.deep_freeze([ 'a', 'b', 'c' ])
25
25
  range = IceNine.deep_freeze('a'..'z')
26
26
  struct = IceNine.deep_freeze(Struct.new(:a, :b).new('a', 'b'))
27
27
  object = IceNine.deep_freeze(Object.new)
28
- user = IceNine.deep_freeze(Application::User.new('dkubb'))
28
+ user = IceNine.deep_freeze(User.new(name: 'dkubb'))
29
29
 
30
30
  # Add core extension for Object#deep_freeze (not required by default)
31
31
  require 'ice_nine/core_ext/object'
32
32
 
33
33
  object = Object.new
34
34
  object.deep_freeze
35
- ```
36
-
37
- Installation
38
- ------------
39
-
40
- With Rubygems:
41
-
42
- ```bash
43
- $ gem install ice_nine
44
- $ irb -rubygems
45
- >> require 'ice_nine'
46
- => true
47
- ```
48
-
49
- With git and local working copy:
50
35
 
51
- ```bash
52
- $ git clone git://github.com/dkubb/ice_nine.git
53
- $ cd ice_nine
54
- $ rake install
55
- $ irb -rubygems
56
- >> require 'ice_nine'
57
- => true
36
+ # Faster deep freeze that skips walking frozen objects
37
+ object = IceNine.deep_freeze!(Object.new)
58
38
  ```
59
39
 
60
40
  Contributing
@@ -25,8 +25,10 @@ def self.nested(depth, width, array_length)
25
25
  hash
26
26
  end
27
27
 
28
- hash = nested(3, 5, 100)
28
+ hash = nested(3, 5, 500)
29
+ hash2 = nested(3, 5, 500)
29
30
 
30
31
  RBench.run do
31
- report("deep_freeze") { IceNine.deep_freeze(hash) }
32
+ report('deep_freeze') { IceNine.deep_freeze(hash) }
33
+ report('deep_freeze!') { IceNine.deep_freeze!(hash2) }
32
34
  end
@@ -1,3 +1,3 @@
1
1
  ---
2
- threshold: 5
3
- total_score: 29.0
2
+ threshold: 8
3
+ total_score: 50.0
@@ -1,2 +1,2 @@
1
1
  ---
2
- threshold: 9.1
2
+ threshold: 5.5
@@ -23,7 +23,8 @@ DuplicateMethodCall:
23
23
  allow_calls: []
24
24
  FeatureEnvy:
25
25
  enabled: true
26
- exclude: []
26
+ exclude:
27
+ - IceNine::RecursionGuard::Frozen#guard
27
28
  IrresponsibleModule:
28
29
  enabled: true
29
30
  exclude: []
@@ -61,9 +62,14 @@ TooManyMethods:
61
62
  TooManyStatements:
62
63
  enabled: true
63
64
  exclude:
65
+ - IceNine::Freezer::Hash#self.freeze_key_value_pairs
66
+ - IceNine::Freezer::Hash#self.guarded_deep_freeze
64
67
  - IceNine::Freezer::Hash#self.deep_freeze
68
+ - IceNine::Freezer::Object#self.guarded_deep_freeze
65
69
  - IceNine::Freezer::Range#self.deep_freeze
70
+ - IceNine::Freezer::Range#self.guarded_deep_freeze
66
71
  - IceNine::RecursionGuard#guard
72
+ - IceNine::RecursionGuard::ObjectSet#guard
67
73
  - each
68
74
  max_statements: 2
69
75
  UncommunicativeMethodName:
@@ -102,5 +108,6 @@ UnusedParameters:
102
108
  exclude: []
103
109
  UtilityFunction:
104
110
  enabled: true
105
- exclude: []
111
+ exclude:
112
+ - IceNine::RecursionGuard::Frozen#guard
106
113
  max_helper_calls: 0
@@ -2,7 +2,6 @@ AllCops:
2
2
  Includes:
3
3
  - '**/*.rake'
4
4
  - 'Gemfile'
5
- - 'Gemfile.devtools'
6
5
  Excludes:
7
6
  - '**/vendor/**'
8
7
  - '**/benchmarks/**'
@@ -10,6 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.description = 'Deep Freeze Ruby Objects'
11
11
  gem.summary = gem.description
12
12
  gem.homepage = 'https://github.com/dkubb/ice_nine'
13
+ gem.license = 'MIT'
13
14
 
14
15
  gem.require_paths = %w[lib]
15
16
  gem.files = `git ls-files`.split($/)
@@ -1,7 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'set'
4
-
5
3
  require 'ice_nine/support/recursion_guard'
6
4
 
7
5
  require 'ice_nine/freezer'
@@ -32,16 +30,33 @@ module IceNine
32
30
  # object = IceNine.deep_freeze(object)
33
31
  #
34
32
  # @param [Object] object
35
- # @param [RecursionGuard] recursion_guard
36
33
  #
37
34
  # @return [Object]
38
35
  #
39
36
  # @api public
40
- def self.deep_freeze(object, recursion_guard = RecursionGuard.new)
41
- return object if object.frozen?
42
- recursion_guard.guard(object.__id__) do
43
- Freezer[object.class].deep_freeze(object, recursion_guard)
44
- end
37
+ def self.deep_freeze(object)
38
+ Freezer.deep_freeze(object)
39
+ end
40
+
41
+ # Deep Freeze an object
42
+ #
43
+ # This method uses a faster algorithm that will assume objects that are
44
+ # `frozen?` do not need to be frozen deeply. Use this method when `object`
45
+ # contains no shallowly frozen objects that need deep freezing.
46
+ #
47
+ # @example
48
+ # IceNine.deep_freeze!(['a', 'b']).map(&:frozen?) # [true, true]
49
+ #
50
+ # @example
51
+ # IceNine.deep_freeze!(['a', 'b'].freeze).map(&:frozen?) # [false, false]
52
+ #
53
+ # @param [Object] object
54
+ #
55
+ # @return [Object]
56
+ #
57
+ # @api public
58
+ def self.deep_freeze!(object)
59
+ Freezer.deep_freeze!(object)
45
60
  end
46
61
 
47
- end # module IceNine
62
+ end # IceNine
@@ -20,9 +20,23 @@ module IceNine
20
20
  IceNine.deep_freeze(self)
21
21
  end
22
22
 
23
- end # module Object
24
- end # module CoreExt
25
- end # module IceNine
23
+ # Deep freeze an object
24
+ #
25
+ # @see IceNine.deep_freeze!
26
+ #
27
+ # @example
28
+ # object = object.deep_freeze!
29
+ #
30
+ # @return [self]
31
+ #
32
+ # @api public
33
+ def deep_freeze!
34
+ IceNine.deep_freeze!(self)
35
+ end
36
+
37
+ end # Object
38
+ end # CoreExt
39
+ end # IceNine
26
40
 
27
41
  # Add Object#deep_freeze
28
42
  Object.instance_eval { include IceNine::CoreExt::Object }
@@ -29,6 +29,32 @@ module IceNine
29
29
  @freezer_cache[mod]
30
30
  end
31
31
 
32
+ # Deep freeze an object with a particular Freezer
33
+ #
34
+ # @see IceNine.deep_freeze
35
+ #
36
+ # @param [Object] object
37
+ #
38
+ # @return [Object]
39
+ #
40
+ # @api public
41
+ def self.deep_freeze(object)
42
+ guarded_deep_freeze(object, RecursionGuard::ObjectSet.new)
43
+ end
44
+
45
+ # Deep freeze an object with a particular Freezer
46
+ #
47
+ # @see IceNine.deep_freeze!
48
+ #
49
+ # @param [Object] object
50
+ #
51
+ # @return [Object]
52
+ #
53
+ # @api public
54
+ def self.deep_freeze!(object)
55
+ guarded_deep_freeze(object, RecursionGuard::Frozen.new)
56
+ end
57
+
32
58
  # Find a Freezer descendant by name
33
59
  #
34
60
  # @param [String] name
@@ -62,9 +88,23 @@ module IceNine
62
88
  const_get(namespace) if const_defined?(namespace, nil)
63
89
  end
64
90
 
91
+ # Deep freeze an object with a particular Freezer and RecursionGuard
92
+ #
93
+ # @param [Object] object
94
+ # @param [RecursionGuard] recursion_guard
95
+ #
96
+ # @return [Object]
97
+ #
98
+ # @api private
99
+ def self.guarded_deep_freeze(object, recursion_guard)
100
+ recursion_guard.guard(object) do
101
+ Freezer[object.class].guarded_deep_freeze(object, recursion_guard)
102
+ end
103
+ end
104
+
65
105
  class << self
66
- protected :const_lookup
106
+ protected :const_lookup, :guarded_deep_freeze
67
107
  end
68
108
 
69
- end # class Freezer
70
- end # module IceNine
109
+ end # Freezer
110
+ end # IceNine
@@ -16,15 +16,13 @@ module IceNine
16
16
  # @param [RecursionGuard] recursion_guard
17
17
  #
18
18
  # @return [Array]
19
- #
20
- # @api public
21
- def self.deep_freeze(array, recursion_guard = RecursionGuard.new)
19
+ def self.guarded_deep_freeze(array, recursion_guard)
20
+ super
22
21
  array.each do |entry|
23
- IceNine.deep_freeze(entry, recursion_guard)
22
+ Freezer.guarded_deep_freeze(entry, recursion_guard)
24
23
  end
25
- super
26
24
  end
27
25
 
28
- end # class Array
29
- end # class Freezer
30
- end # module IceNine
26
+ end # Array
27
+ end # Freezer
28
+ end # IceNine
@@ -6,5 +6,5 @@ module IceNine
6
6
  # Skip freezing false objects
7
7
  class FalseClass < NoFreeze; end
8
8
 
9
- end # class Freezer
10
- end # module IceNine
9
+ end # Freezer
10
+ end # IceNine
@@ -17,17 +17,30 @@ module IceNine
17
17
  # @param [RecursionGuard] recursion_guard
18
18
  #
19
19
  # @return [Hash]
20
+ def self.guarded_deep_freeze(hash, recursion_guard)
21
+ super
22
+ default = hash.default_proc || hash.default
23
+ Freezer.guarded_deep_freeze(default, recursion_guard)
24
+ freeze_key_value_pairs(hash, recursion_guard)
25
+ end
26
+
27
+ # Handle freezing the key/value pairs
20
28
  #
21
- # @api public
22
- def self.deep_freeze(hash, recursion_guard = RecursionGuard.new)
23
- IceNine.deep_freeze(hash.default_proc || hash.default, recursion_guard)
29
+ # @param [Hash] hash
30
+ # @param [RecursionGuard] recursion_guard
31
+ #
32
+ # @return [undefined]
33
+ #
34
+ # @api private
35
+ def self.freeze_key_value_pairs(hash, recursion_guard)
24
36
  hash.each do |key, value|
25
- IceNine.deep_freeze(key, recursion_guard)
26
- IceNine.deep_freeze(value, recursion_guard)
37
+ Freezer.guarded_deep_freeze(key, recursion_guard)
38
+ Freezer.guarded_deep_freeze(value, recursion_guard)
27
39
  end
28
- super
29
40
  end
30
41
 
31
- end # class Hash
32
- end # class Freezer
33
- end # module IceNine
42
+ private_class_method :freeze_key_value_pairs
43
+
44
+ end # Hash
45
+ end # Freezer
46
+ end # IceNine
@@ -7,6 +7,6 @@ module IceNine
7
7
  # Skip freezing Hash::State objects on Rubinius
8
8
  class State < NoFreeze; end
9
9
 
10
- end # class Hash
11
- end # class Freezer
12
- end # module IceNine
10
+ end # Hash
11
+ end # Freezer
12
+ end # IceNine
@@ -6,5 +6,5 @@ module IceNine
6
6
  # Skip freezing Module objects
7
7
  class Module < NoFreeze; end
8
8
 
9
- end # class Freezer
10
- end # module IceNine
9
+ end # Freezer
10
+ end # IceNine
@@ -6,5 +6,5 @@ module IceNine
6
6
  # Skip freezing nil objects
7
7
  class NilClass < NoFreeze; end
8
8
 
9
- end # class Freezer
10
- end # module IceNine
9
+ end # Freezer
10
+ end # IceNine