Merge pull request #28613 from cachedout/py26_method_deepcopy

Add facility to deepcopy bound methods in Py2.6 and apply to grains
This commit is contained in:
Pedro Algarvio 2015-11-05 23:28:50 +00:00
commit 9196c57e3f
2 changed files with 36 additions and 2 deletions

View file

@ -15,6 +15,7 @@ import collections
from functools import reduce
# Import 3rd-party libs
import salt.utils.compat
from salt.utils.odict import OrderedDict
import yaml
import salt.ext.six as six
@ -238,8 +239,15 @@ def setvals(grains, destructive=False):
grains[key] = val
__grains__[key] = val
# Cast defaultdict to dict; is there a more central place to put this?
yaml_reps = copy.deepcopy(yaml.representer.SafeRepresenter.yaml_representers)
yaml_multi_reps = copy.deepcopy(yaml.representer.SafeRepresenter.yaml_multi_representers)
try:
yaml_reps = copy.deepcopy(yaml.representer.SafeRepresenter.yaml_representers)
yaml_multi_reps = copy.deepcopy(yaml.representer.SafeRepresenter.yaml_multi_representers)
except (TypeError, NameError):
# This likely means we are running under Python 2.6 which cannot deepcopy
# bound methods. Fallback to a modification of deepcopy which can support
# this behavior.
yaml_reps = salt.utils.compat.deepcopy_bound(yaml.representer.SafeRepresenter.yaml_representers)
yaml_multi_reps = salt.utils.compat.deepcopy_bound(yaml.representer.SafeRepresenter.yaml_multi_representers)
yaml.representer.SafeRepresenter.add_representer(collections.defaultdict,
yaml.representer.SafeRepresenter.represent_dict)
yaml.representer.SafeRepresenter.add_representer(OrderedDict,

View file

@ -6,6 +6,8 @@ Compatibility functions for utils
# Import python libs
from __future__ import absolute_import
import sys
import copy
import types
# Import salt libs
import salt.loader
@ -20,3 +22,27 @@ def pack_dunder(name):
mod = sys.modules[name]
if not hasattr(mod, '__utils__'):
setattr(mod, '__utils__', salt.loader.utils(mod.__opts__))
def deepcopy_bound(name):
'''
Compatibility helper function to allow copy.deepcopy copy bound methods
which is broken on Python 2.6, due to the following bug:
https://bugs.python.org/issue1515
Warnings:
- This method will mutate the global deepcopy dispatcher, which means that
this function is NOT threadsafe!
- Not Py3 compatible. The intended use case is deepcopy compat for Py2.6
'''
def _deepcopy_method(x, memo):
return type(x)(x.im_func, copy.deepcopy(x.im_self, memo), x.im_class) # pylint: disable=W1699
try:
pre_dispatch = copy._deepcopy_dispatch
copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
ret = copy.deepcopy(name)
finally:
copy._deepcopy_dispatch = pre_dispatch
return ret