19
19
from builtins import str , bytes
20
20
from packaging .version import Version
21
21
22
- from ...utils .filemanip import md5 , hash_infile , hash_timestamp , to_str
22
+ from traits .trait_errors import TraitError
23
+ from traits .trait_handlers import TraitDictObject , TraitListObject
24
+ from ...utils .filemanip import (
25
+ md5 , hash_infile , hash_timestamp , to_str , USING_PATHLIB2 )
23
26
from .traits_extension import (
24
27
traits ,
25
28
Undefined ,
26
29
isdefined ,
27
- TraitError ,
28
- TraitDictObject ,
29
- TraitListObject ,
30
30
has_metadata ,
31
31
)
32
32
33
33
from ... import config , __version__
34
34
35
+
35
36
FLOAT_FORMAT = '{:.10f}' .format
36
37
nipype_version = Version (__version__ )
37
38
@@ -314,6 +315,39 @@ def __all__(self):
314
315
return self .copyable_trait_names ()
315
316
316
317
318
+ def _deepcopypatch (self , memo ):
319
+ """
320
+ Replace the ``__deepcopy__`` member with a traits-friendly implementation.
321
+
322
+ A bug in ``__deepcopy__`` for ``HasTraits`` results in weird cloning behaviors.
323
+ Occurs for all specs in Python<3 and only for DynamicTraitedSpec in Python>2.
324
+
325
+ """
326
+ id_self = id (self )
327
+ if id_self in memo :
328
+ return memo [id_self ]
329
+ dup_dict = deepcopy (self .trait_get (), memo )
330
+ # access all keys
331
+ for key in self .copyable_trait_names ():
332
+ if key in self .__dict__ .keys ():
333
+ _ = getattr (self , key )
334
+ # clone once
335
+ dup = self .clone_traits (memo = memo )
336
+ for key in self .copyable_trait_names ():
337
+ try :
338
+ _ = getattr (dup , key )
339
+ except :
340
+ pass
341
+ # clone twice
342
+ dup = self .clone_traits (memo = memo )
343
+ dup .trait_set (** dup_dict )
344
+ return dup
345
+
346
+
347
+ if USING_PATHLIB2 :
348
+ BaseTraitedSpec .__deepcopy__ = _deepcopypatch
349
+
350
+
317
351
class TraitedSpec (BaseTraitedSpec ):
318
352
""" Create a subclass with strict traits.
319
353
@@ -333,29 +367,9 @@ class DynamicTraitedSpec(BaseTraitedSpec):
333
367
functioning well together.
334
368
"""
335
369
336
- def __deepcopy__ (self , memo ):
337
- """ bug in deepcopy for HasTraits results in weird cloning behavior for
338
- added traits
339
- """
340
- id_self = id (self )
341
- if id_self in memo :
342
- return memo [id_self ]
343
- dup_dict = deepcopy (self .trait_get (), memo )
344
- # access all keys
345
- for key in self .copyable_trait_names ():
346
- if key in self .__dict__ .keys ():
347
- _ = getattr (self , key )
348
- # clone once
349
- dup = self .clone_traits (memo = memo )
350
- for key in self .copyable_trait_names ():
351
- try :
352
- _ = getattr (dup , key )
353
- except :
354
- pass
355
- # clone twice
356
- dup = self .clone_traits (memo = memo )
357
- dup .trait_set (** dup_dict )
358
- return dup
370
+
371
+ if not USING_PATHLIB2 :
372
+ DynamicTraitedSpec .__deepcopy__ = _deepcopypatch
359
373
360
374
361
375
class CommandLineInputSpec (BaseInterfaceInputSpec ):
0 commit comments