# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from copy import deepcopy def deepcopy_with_locators(value): """ Like :func:`deepcopy`, but also copies over locators. """ res = deepcopy(value) copy_locators(res, value) return res def copy_locators(target, source): """ Copies over ``_locator`` for all elements, recursively. Assumes that target and source have exactly the same list/dict structure. """ locator = getattr(source, '_locator', None) if locator is not None: try: setattr(target, '_locator', locator) except AttributeError: pass if isinstance(target, list) and isinstance(source, list): for i, _ in enumerate(target): copy_locators(target[i], source[i]) elif isinstance(target, dict) and isinstance(source, dict): for k, v in target.items(): copy_locators(v, source[k])