ice_nine 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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