This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: SimpleNamespace deep copy
Type: enhancement Stage: resolved
Components: Extension Modules Versions: Python 3.7, Python 3.6, Python 3.5
process
Status: closed Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Pritish Patil, eric.snow, steven.daprano, yselivanov
Priority: normal Keywords:

Created on 2017-09-01 14:51 by Pritish Patil, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg301112 - (view) Author: Pritish Patil (Pritish Patil) Date: 2017-09-01 14:51
I am new here and not sure how I can suggest this properly.


When using nested SimpleNamespaces, a making a copy by using 

new_NS=SimpleNamespace(**namespace.__dict__.copy())

only copies the highest level namespace. This is expected in python as shallow copies are preferred. But, a nested deep copy function would be nice, and will allow easier use.

I suggest a simple

def my_namespace_copy(namespace):
    '''Recursively deep copies nested namespaces'''
    new_NS=SimpleNamespace(**namespace.__dict__.copy())
    for i in new_NS.__dict__.keys():
        if(type(new_NS.__dict__[i]) == types.SimpleNamespace):
            new_NS.__setattr__(i, my_namespace_copy(new_NS.__getattribute__(i)))
    return new_NS

I am not sure of the exact implementation of the class and guess this would need some appropriate modifications.

I suggest this be added at SimpleNameSpace.__copy__ or at SimpleNameSpace.__deepcopy__
msg301120 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2017-09-01 15:06
> When using nested SimpleNamespaces, a making a copy by using 
> 
> new_NS=SimpleNamespace(**namespace.__dict__.copy())

In general, you shouldn't call or directly access dunder attributes. 
There are exceptions, but generally they're for Python's use only. For 
example, the public interface for getting __dict__ is to call 
vars(namespace).

But there's no need to do this by hand. Use the copy module instead.

copy.copy(namespace)  # copy one level only

copy.deepcopy(namespace)  # copy all the way down

seem to work for me.

Does this solve your problem? If so, we'll close this issue.
msg301121 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2017-09-01 15:08
Hmm.  What problems are you seeing with deep copies?  copy.deepcopy() should work since SimpleNamespace is picklable. [1][2]  I don't have any problems:

>>> import types, copy
>>> ns = types.SimpleNamespace(x=1, y=2)
>>> copied = copy.deepcopy(ns)
>>> copied
namespace(x=1, y=2)
>>> ns = types.SimpleNamespace(x=types.SimpleNamespace(a=1),
                               y=types.SimpleNamespace(b=2))
>>> copied = copy.deepcopy(ns)
>>> copied
namespace(x=namespace(a=1), y=namespace(b=2))
>>> ns.x is copied.x
False

[1] issue #15022
[2] https://docs.python.org/3/library/copy.html
msg301125 - (view) Author: Pritish Patil (Pritish Patil) Date: 2017-09-01 15:13
Yes. copy.deepcopy() works. 

Didn't think of it!
History
Date User Action Args
2022-04-11 14:58:51adminsetgithub: 75503
2017-09-01 15:13:27Pritish Patilsetstatus: open -> closed

messages: + msg301125
stage: resolved
2017-09-01 15:08:12eric.snowsetnosy: + eric.snow
messages: + msg301121
2017-09-01 15:06:19steven.dapranosetnosy: + steven.daprano
messages: + msg301120
2017-09-01 14:53:54Pritish Patilsetnosy: + yselivanov, - docs@python
2017-09-01 14:52:47Pritish Patilsetcomponents: + Extension Modules, - Documentation, Library (Lib)
2017-09-01 14:51:16Pritish Patilcreate