[blivet:master] Factor duplicate code in __deepcopy__ methods into one method (#1095244)
mulhern
amulhern at redhat.com
Fri May 9 16:39:43 UTC 2014
Related: fed#1095244
The method treats attributes in omit and attributes w/ value None the
same way. Previously, an attribute with a None value was not handled
specially, which could lead to "NoneType has no attribute <x>"
sorts of errors.
Signed-off-by: mulhern <amulhern at redhat.com>
---
blivet/devices.py | 16 +++-------------
blivet/formats/disklabel.py | 19 ++++---------------
blivet/util.py | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 45 insertions(+), 28 deletions(-)
diff --git a/blivet/devices.py b/blivet/devices.py
index 256d830..009d127 100644
--- a/blivet/devices.py
+++ b/blivet/devices.py
@@ -249,19 +249,9 @@ class Device(util.ObjectID):
We can't do copy.deepcopy on parted objects, which is okay.
For these parted objects, we just do a shallow copy.
"""
- new = self.__class__.__new__(self.__class__)
- memo[id(self)] = new
- dont_copy_attrs = ('_raidSet', 'node')
- shallow_copy_attrs = ('_partedDevice', '_partedPartition')
- for (attr, value) in self.__dict__.items():
- if attr in dont_copy_attrs:
- setattr(new, attr, value)
- elif attr in shallow_copy_attrs:
- setattr(new, attr, copy.copy(value))
- else:
- setattr(new, attr, copy.deepcopy(value, memo))
-
- return new
+ return util.variable_copy(self, memo,
+ omit=('_raidSet', 'node'),
+ shallow=('_partedDevice', '_partedPartition'))
def __repr__(self):
s = ("%(type)s instance (%(id)s) --\n"
diff --git a/blivet/formats/disklabel.py b/blivet/formats/disklabel.py
index e06c39f..a7609aa 100644
--- a/blivet/formats/disklabel.py
+++ b/blivet/formats/disklabel.py
@@ -21,13 +21,13 @@
#
import os
-import copy
from ..storage_log import log_exception_info, log_method_call
import parted
import _ped
from ..errors import DeviceFormatError, DiskLabelCommitError, InvalidDiskLabelError
from .. import arch
+from .. import util
from ..flags import flags
from ..udev import udev_settle
from ..i18n import _, N_
@@ -78,21 +78,10 @@ class DiskLabel(DeviceFormat):
""" Create a deep copy of a Disklabel instance.
We can't do copy.deepcopy on parted objects, which is okay.
- For these parted objects, we just do a shallow copy.
"""
- new = self.__class__.__new__(self.__class__)
- memo[id(self)] = new
- shallow_copy_attrs = ('_partedDevice', '_alignment', '_endAlignment')
- duplicate_attrs = ('_partedDisk', '_origPartedDisk')
- for (attr, value) in self.__dict__.items():
- if attr in shallow_copy_attrs:
- setattr(new, attr, copy.copy(value))
- elif attr in duplicate_attrs:
- setattr(new, attr, value.duplicate())
- else:
- setattr(new, attr, copy.deepcopy(value, memo))
-
- return new
+ return util.variable_copy(self, memo,
+ shallow=('_partedDevice', '_alignment', '_endAlignment'),
+ duplicate=('_partedDisk', '_origPartedDisk'))
def __repr__(self):
s = DeviceFormat.__repr__(self)
diff --git a/blivet/util.py b/blivet/util.py
index 1fd5035..6b9fed6 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -1,3 +1,4 @@
+import copy
import itertools
import os
import shutil
@@ -353,3 +354,40 @@ class ObjectID(object):
self = super(ObjectID, cls).__new__(cls, *args, **kwargs)
self.id = self._newid_gen() # pylint: disable=attribute-defined-outside-init
return self
+
+def variable_copy(obj, memo, omit=None, shallow=None, duplicate=None):
+ """ A configurable copy function. Any attributes not specified in omit,
+ shallow, or duplicate are copied using copy.deepcopy().
+
+ :param object obj: a python object to be copied.
+ :param dict memo: a dictionary of already copied items
+ :param omit: a list of names of attributes not to copy
+ :type omit: iterable of str
+ :param shallow: a list of names of attributes to shallow copy
+ :type shallow: iterable of str
+ :param duplicate: a list of names of attributes to duplicate
+ :type duplicate: iterable of str
+
+ Note that all atrributes in duplicate must implement a duplicate()
+ method that does what is expected of it. Attributes with type
+ pyparted.Disk are known to do so.
+
+ A shallow copy is implemented by calling copy.copy().
+ """
+ omit = omit or []
+ shallow = shallow or []
+ duplicate = duplicate or []
+
+ new = obj.__class__.__new__(obj.__class__)
+ memo[id(obj)] = new
+ for (attr, value) in obj.__dict__.items():
+ if attr in omit or value == None:
+ setattr(new, attr, value)
+ elif attr in shallow:
+ setattr(new, attr, copy.copy(value))
+ elif attr in duplicate:
+ setattr(new, attr, value.duplicate())
+ else:
+ setattr(new, attr, copy.deepcopy(value, memo))
+
+ return new
--
1.8.3.1
More information about the anaconda-patches
mailing list