Copy dictionary and modify it without affecting the original

As @bkarabinchak.psi pointed out even though the structure “looks” like a dict it isn’t actually a dict.
Actually the type of a perspective property when accessed from a script is:com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper.ObjectWrapper.

Thus deepcopy chokes when it runs into an object that it doesn’t know how to handle.

If you need a true deepcopy, then you have couple of options.

  1. Write a function which recursively loops through the structure and correctly maps objects to dictionaries, and arrays to lists.
  2. Encode to JSON and de-encode to guarantee you’re dealing with native Python objects

I have done both of those things in the past.

Note: Option 1 will work for “perspective properties”, it doesn’t account for other possible types that aren’t handled by deepcopy. The assumption I have made here is that if it isn’t an object, or array, then it is a basic type (string,integer,float,etc…). The function can/should be modified to handle other types if you need that particular thing.

Code for option 1:

def recursiveCopy(original):
    from copy import deepcopy
    from com.inductiveautomation.ignition.common.script.abc import AbstractMutableJythonMap,AbstractMutableJythonSequence

    if isinstance(original,AbstractMutableJythonMap):
        return {key:recursiveCopy(value) for key,value in original.iteritems()}

    if isinstance(original,AbstractMutableJythonSequence):
        return [recursiveCopy(item) for item in original]

    return deepcopy(original)

Code for Option 2:

from copy import deepcopy
pen = deepcopy(system.util.jsonDecode(system.util.jsonEncode(self.view.custom.penEjemplo)))

There are reasons to go with option 1 over option 2, but for what it looks like you’re trying to do either will work.

I will say though, that if I were trying to modify a pen in a power chart, I would just modify the pen, not sure why you need a copy for that.

4 Likes