full_dup 0.0.5 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e29b1fda9c75d8b3d58009be5e0a05cdbb4900d0
4
- data.tar.gz: 12eaab0453df9c9929cba76476eef2afe49f5768
2
+ SHA256:
3
+ metadata.gz: 5780661f9225891467a4552a1b065627b67c21f5619566e7038cfcbf50b8c148
4
+ data.tar.gz: ff40d94205773a95baccc9feaa4c6c9a287ed89f5b12b3b9e1f8cb5000506c17
5
5
  SHA512:
6
- metadata.gz: d528171d9e4b7fd69372df61f51d50e90a67357275e3735692fceb3c8fbe26b3afe8a311fd26eecc5dead476693fbdee927dc0a6c6cf669b18ed7af3c164d5f0
7
- data.tar.gz: d2922af5bc54fb610c6ebcf752df513e1f86c4f92185bbbb30dd94f90f18ff2726b38d5b32e4ed83b59f0b47db75f3e871ec32c4d97998b5c80ebfdf9f8794b7
6
+ metadata.gz: 779b609572b851269a75014bedadd06c8443b4041562cf05046c75717f877a6a6d7e136ac967751a7af368d37ba588993e2066e92e3742949978b5328b9fa0c6
7
+ data.tar.gz: fd1f6a258c8d494b196e6e228689a23127f7b4618fec197621d5b0b7fe8c322f635824ed37cb90b169d541992e298fbe51b3f5d1968ffd3b8572ab5d9ce17852
data/README.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # FullDup
2
2
 
3
+ The full_dup gem adds the full_dup method to all objects descended from the
4
+ Object class. While this gem makes extensive use of monkey patching, it does
5
+ not modify the behaviour of any existing methods. This is done to minimize
6
+ the risk of breaking any existing code.
7
+
8
+ New for version 0.0.6, now 84% faster (at least in my tests).
9
+
3
10
  The standard dup method creates a fresh instance of most (non-scalar) objects
4
11
  but does not process internal state. This internal state remains aliased in the
5
12
  duplicated copy. The full_dup method digs deep and makes copies of these
@@ -13,13 +20,24 @@ it does mean that the dup operation must be applied with great care.
13
20
 
14
21
  Unlike the standard dup method, the full\_dup method does not throw an
15
22
  exception when it sees un-duppable value objects like 42 or true. These values
16
- simply return themselves. This is correct because those types of objects do
17
- not _need_ to be duped. Instead of having a fit, the code just works!
23
+ simply return themselves. This is deemed correct because those types of objects
24
+ are immutable and do not need to be duped. Instead of raising an exception,
25
+ the code returns the immutable object instead.
18
26
 
19
27
  Another issue that this gem deals with is that of data with looping reference
20
28
  chains. To handle this, the code tracks object ID values and does not re-dup
21
29
  data that has already been duped. Thus even nasty edge cases are handled
22
- without any special effort on the part of the application programmer.
30
+ without any special effort on the part of the application programmer. Note though
31
+ that this also means that it is important that the object id be correctly
32
+ implemented. Fortunately, this is done by default in Ruby.
33
+
34
+ If you wish to implement your own object id for your own special classes:
35
+ 1. Don't! If object_id is broken,
36
+ then full_dup (and a whole lot of other things too) will also be broken!
37
+ 2. It's all on you to do as good a job as Ruby. Like the Ruby object id method,
38
+ your method must create id values that are unique to each object and are perfectly
39
+ repeatable for that object.
40
+ 3. Really DON'T! I have never found a valid reason for doing so. I doubt that one exists.
23
41
 
24
42
  ## Family Overview
25
43
 
@@ -93,20 +111,46 @@ array:
93
111
  ```ruby
94
112
  my_array.define_singleton_method(:full_dup_exclude) { [0, 1] }
95
113
  ```
96
- <br>**Possible Red Flag** There is a catch here. The dup method does _not_
97
- duplicate singleton methods (unlike the clone method). Thus any duplicates
98
- made in this manner will lose the attached full_dup_exclude method. If it is
99
- important to retain singleton methods, consider using the full_clone gem
100
- instead.
114
+ <br>**Possible Red Flag** There is a catch here. The dup and full_dup methods
115
+ do not duplicate singleton methods (unlike the clone and full_clone methods).
116
+ Thus any duplicates made in this manner will lose the attached full_dup_exclude
117
+ method. If it is important to retain singleton methods, consider using the
118
+ full_clone gem instead.
101
119
 
102
- ## Notes
120
+ ### irbt
103
121
 
104
- The full_dup gem tracks its progress and handles data objects that
105
- contain loops, cycles, and other forms of recursion. In order to do this,
106
- it relies heavily on the object_id property of the data being copied.
107
- If object_id is broken, then full_dup and hashes and ... will also be
108
- broken!
122
+ The root folder of the full_dup gem contains the file irbt.rb. This program
123
+ opens up the irb repl with the full_dup gem preloaded and is useful for trying
124
+ out the gem interactively.
109
125
 
126
+ By default, irbt will load the system gem version of full dup. The following
127
+ interactive session demonstrates the difference between dup and full_dup
128
+
129
+ ```
130
+ C:\Sites\full_dup>ruby irbt.rb
131
+ Starting an IRB console with full_dup loaded.
132
+ full_dup loaded from gem: 0.0.5
133
+ irb(main):001:0> a = ["a", "b", "c"]
134
+ => ["a", "b", "c"]
135
+ irb(main):002:0> b = a.dup
136
+ => ["a", "b", "c"]
137
+ irb(main):003:0> c = a.full_dup
138
+ => ["a", "b", "c"]
139
+ irb(main):004:0> a[0] << "foo"
140
+ => "afoo"
141
+ irb(main):005:0> a
142
+ => ["afoo", "b", "c"]
143
+ irb(main):006:0> b
144
+ => ["afoo", "b", "c"]
145
+ irb(main):007:0> c
146
+ => ["a", "b", "c"]
147
+ irb(main):008:0>
148
+ ```
149
+ To load the local copy of full_dup use:
150
+ ```
151
+ >ruby irbt.rb local #optional irb args go here.
152
+ #etc etc etc...
153
+ ```
110
154
 
111
155
  ## Contributing
112
156
 
@@ -122,3 +166,14 @@ broken!
122
166
 
123
167
  Go to the GitHub repository and raise an issue calling attention to some
124
168
  aspect that could use some TLC or a suggestion or an idea.
169
+
170
+ ## License
171
+
172
+ The gem is available as open source under the terms of the
173
+ [MIT License](./LICENSE.txt).
174
+
175
+ ## Code of Conduct
176
+
177
+ Everyone interacting in the fully_freeze project’s codebases, issue trackers,
178
+ chat rooms and mailing lists is expected to follow the
179
+ [code of conduct](./CODE_OF_CONDUCT.md).
data/full_dup.gemspec CHANGED
@@ -17,8 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test)/}) }
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_development_dependency "rake", "~> 12.0"
21
- spec.add_development_dependency "bundler", "~> 1.3"
20
+ spec.add_development_dependency "rake", ">= 12.3.3"
21
+ spec.add_development_dependency "bundler", ">= 2.1.0"
22
22
  spec.add_development_dependency 'minitest', "~> 5.7"
23
- spec.add_development_dependency 'minitest_visible', "~> 0.1"
23
+ spec.add_development_dependency 'reek', "~> 5.0.2"
24
24
  end
data/lib/full_dup.rb CHANGED
@@ -1,37 +1,12 @@
1
1
  # coding: utf-8
2
2
 
3
+ # A deep, safe, recursive variant of the dup method. The full_dup method.
4
+
5
+ require_relative 'full_dup/use_self'
6
+ require_relative 'full_dup/use_dup'
3
7
  require_relative 'full_dup/version'
4
8
  require_relative 'full_dup/object'
5
9
  require_relative 'full_dup/array'
6
10
  require_relative 'full_dup/hash'
7
11
  require_relative 'full_dup/struct'
8
12
 
9
- module FullDup
10
- def full_dup(_progress={})
11
- self
12
- end
13
- end
14
-
15
- class Numeric
16
- include FullDup
17
- end
18
-
19
- class NilClass
20
- include FullDup
21
- end
22
-
23
- class TrueClass
24
- include FullDup
25
- end
26
-
27
- class FalseClass
28
- include FullDup
29
- end
30
-
31
- class Symbol
32
- include FullDup
33
- end
34
-
35
- class Regexp
36
- include FullDup
37
- end
@@ -1,23 +1,26 @@
1
1
  # coding: utf-8
2
2
 
3
+ # Add full_dup support to the array class.
3
4
  class Array
4
5
 
5
- #The full_dup method for arrays.
6
- def full_dup(progress={})
7
- progress[object_id] = result = dup
8
- exclude = full_dup_exclude
9
-
6
+ # Do a full_dup with no exclusions
7
+ def full_dup_no_exclusions(progress)
10
8
  each_index do |name|
9
+ value = self[name]
10
+ value = progress[value.object_id] || value.full_dup(progress)
11
+ self[name] = value
12
+ end
13
+ end
11
14
 
15
+ # Do a full_dup with exclusions
16
+ def full_dup_with_exclusions(progress, exclude)
17
+ each_index do |name|
12
18
  unless exclude.include?(name)
13
- value = result[name]
19
+ value = self[name]
14
20
  value = progress[value.object_id] || value.full_dup(progress)
15
- result[name] = value
21
+ self[name] = value
16
22
  end
17
-
18
23
  end
19
-
20
- result
21
24
  end
22
25
 
23
26
  end
data/lib/full_dup/hash.rb CHANGED
@@ -1,23 +1,26 @@
1
- # coding: utf-8
2
-
3
- class Hash
4
-
5
- #The full_dup method for hashes.
6
- def full_dup(progress={})
7
- progress[object_id] = result = dup
8
- exclude = full_dup_exclude
9
-
10
- each_key do |name|
11
-
12
- unless exclude.include?(name)
13
- value = result[name]
14
- value = progress[value.object_id] || value.full_dup(progress)
15
- result[name] = value
16
- end
17
-
18
- end
19
-
20
- result
21
- end
22
-
23
- end
1
+ # coding: utf-8
2
+
3
+ # Add full_dup support to the hash class.
4
+ class Hash
5
+
6
+ # Do a full_dup with no exclusions
7
+ def full_dup_no_exclusions(progress)
8
+ each_key do |name|
9
+ value = self[name]
10
+ value = progress[value.object_id] || value.full_dup(progress)
11
+ self[name] = value
12
+ end
13
+ end
14
+
15
+ # Do a full_dup with exclusions
16
+ def full_dup_with_exclusions(progress, exclude)
17
+ each_key do |name|
18
+ unless exclude.include?(name)
19
+ value = self[name]
20
+ value = progress[value.object_id] || value.full_dup(progress)
21
+ self[name] = value
22
+ end
23
+ end
24
+ end
25
+
26
+ end
@@ -1,5 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
+ # Add full_dup support to the object class.
3
4
  class Object
4
5
 
5
6
  #By default, no instance variables are excluded.
@@ -7,22 +8,38 @@ class Object
7
8
  []
8
9
  end
9
10
 
10
- #The full_dup method for most objects.
11
+ #The common part of the full_dup.
11
12
  def full_dup(progress={})
12
13
  progress[object_id] = result = dup
13
14
  exclude = full_dup_exclude
14
15
 
16
+ if exclude.empty?
17
+ result.full_dup_no_exclusions(progress)
18
+ else
19
+ result.full_dup_with_exclusions(progress, exclude)
20
+ end
21
+
22
+ result
23
+ end
24
+
25
+ # Do a full_dup with no exclusions
26
+ def full_dup_no_exclusions(progress)
15
27
  instance_variables.each do |name|
28
+ value = instance_variable_get(name)
29
+ value = progress[value.object_id] || value.full_dup(progress)
30
+ instance_variable_set(name, value)
31
+ end
32
+ end
16
33
 
34
+ # Do a full_dup with exclusions
35
+ def full_dup_with_exclusions(progress, exclude)
36
+ instance_variables.each do |name|
17
37
  unless exclude.include?(name)
18
- value = result.instance_variable_get(name)
38
+ value = instance_variable_get(name)
19
39
  value = progress[value.object_id] || value.full_dup(progress)
20
- result.instance_variable_set(name, value)
40
+ instance_variable_set(name, value)
21
41
  end
22
-
23
42
  end
24
-
25
- result
26
43
  end
27
44
 
28
45
  end
@@ -1,23 +1,26 @@
1
1
  # coding: utf-8
2
2
 
3
+ # Add full_dup support to the struct class.
3
4
  class Struct
4
5
 
5
- #The full_dup method for structs.
6
- def full_dup(progress={})
7
- progress[object_id] = result = dup
8
- exclude = full_dup_exclude
9
-
6
+ # Do a full_dup with no exclusions
7
+ def full_dup_no_exclusions(progress)
10
8
  members.each do |name|
9
+ value = self[name]
10
+ value = progress[value.object_id] || value.full_dup(progress)
11
+ self[name] = value
12
+ end
13
+ end
11
14
 
15
+ # Do a full_dup with exclusions
16
+ def full_dup_with_exclusions(progress, exclude)
17
+ members.each do |name|
12
18
  unless exclude.include?(name)
13
- value = result[name]
19
+ value = self[name]
14
20
  value = progress[value.object_id] || value.full_dup(progress)
15
- result[name] = value
21
+ self[name] = value
16
22
  end
17
-
18
23
  end
19
-
20
- result
21
24
  end
22
25
 
23
26
  end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+
3
+ # The mixin for classes where dup is just simple dup.
4
+ module FullDupDup
5
+ def full_dup(_progress=nil)
6
+ dup
7
+ end
8
+ end
9
+
10
+ # Strings answer dup.
11
+ class String
12
+ include FullDupDup
13
+ end
14
+
15
+ # Enumerators answer dup.
16
+ class Enumerator
17
+ include FullDupDup
18
+ end
19
+
20
+ # MatchData answer dup.
21
+ class MatchData
22
+ include FullDupDup
23
+ end
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+
3
+ # A mixin for classes where the dup is the object itself.
4
+ module FullDupSelf
5
+ def full_dup(_progress=nil)
6
+ self
7
+ end
8
+ end
9
+
10
+ # Numerics answer self.
11
+ class Numeric
12
+ include FullDupSelf
13
+ end
14
+
15
+ # NilClass objects (nil) answer self.
16
+ class NilClass
17
+ include FullDupSelf
18
+ end
19
+
20
+ # TrueClass objects (true) answer self.
21
+ class TrueClass
22
+ include FullDupSelf
23
+ end
24
+
25
+ # FalseClass objects (false) answer self.
26
+ class FalseClass
27
+ include FullDupSelf
28
+ end
29
+
30
+ # Symbols answer self.
31
+ class Symbol
32
+ include FullDupSelf
33
+ end
34
+
35
+ # Regular expressions answer self.
36
+ class Regexp
37
+ include FullDupSelf
38
+ end
39
+
40
+ # Threads answer self.
41
+ class Thread
42
+ include FullDupSelf
43
+ end
44
+
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module FullDup
4
- VERSION = "0.0.5"
4
+ VERSION = "1.0.3".freeze
5
5
  end
data/rakefile.rb CHANGED
@@ -14,6 +14,11 @@ Rake::TestTask.new do |t|
14
14
  t.warning = true
15
15
  end
16
16
 
17
+ desc "Run a scan for smelly code!"
18
+ task :reek do |t|
19
+ `reek --no-color lib > reek.txt`
20
+ end
21
+
17
22
  desc "Fire up an IRB session with full_dup preloaded."
18
23
  task :console do
19
24
  system "ruby irbt.rb local"
data/reek.txt ADDED
@@ -0,0 +1 @@
1
+ 0 total warnings
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: full_dup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Camilleri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-13 00:00:00.000000000 Z
11
+ date: 2021-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '12.0'
19
+ version: 12.3.3
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '12.0'
26
+ version: 12.3.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
33
+ version: 2.1.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.3'
40
+ version: 2.1.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.7'
55
55
  - !ruby/object:Gem::Dependency
56
- name: minitest_visible
56
+ name: reek
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.1'
61
+ version: 5.0.2
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.1'
68
+ version: 5.0.2
69
69
  description: A (safe/no exceptions) dup variant that performs a deep, recursive copy.
70
70
  email:
71
71
  - peter.c.camilleri@gmail.com
@@ -85,8 +85,11 @@ files:
85
85
  - lib/full_dup/hash.rb
86
86
  - lib/full_dup/object.rb
87
87
  - lib/full_dup/struct.rb
88
+ - lib/full_dup/use_dup.rb
89
+ - lib/full_dup/use_self.rb
88
90
  - lib/full_dup/version.rb
89
91
  - rakefile.rb
92
+ - reek.txt
90
93
  homepage: https://github.com/PeterCamilleri/full_dup
91
94
  licenses:
92
95
  - MIT
@@ -106,10 +109,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
109
  - !ruby/object:Gem::Version
107
110
  version: '0'
108
111
  requirements: []
109
- rubyforge_project:
110
- rubygems_version: 2.2.3
112
+ rubygems_version: 3.2.17
111
113
  signing_key:
112
114
  specification_version: 4
113
115
  summary: A dup variant that performs a deep copy.
114
116
  test_files: []
115
- has_rdoc: