# Path: sacred/config/custom_containers.py
# def make_read_only(o):
#     """Makes objects read-only.
# 
#     Converts every `list` and `dict` into `ReadOnlyList` and `ReadOnlyDict` in
#     a nested structure of `list`s, `dict`s and `tuple`s. Does not modify `o`
#     but returns the converted structure.
#     """
#     if type(o) == dict:
#         return ReadOnlyDict({k: make_read_only(v) for k, v in o.items()})
#     elif type(o) == list:
#         return ReadOnlyList([make_read_only(v) for v in o])
#     elif type(o) == tuple:
#         return tuple(map(make_read_only, o))
#     else:
#         return o
# 
# class ReadOnlyList(ReadOnlyContainer, list):
#     """A read-only variant of a `list`."""
# 
#     append = ReadOnlyContainer._readonly
#     clear = ReadOnlyContainer._readonly
#     extend = ReadOnlyContainer._readonly
#     insert = ReadOnlyContainer._readonly
#     pop = ReadOnlyContainer._readonly
#     remove = ReadOnlyContainer._readonly
#     reverse = ReadOnlyContainer._readonly
#     sort = ReadOnlyContainer._readonly
#     __setitem__ = ReadOnlyContainer._readonly
#     __delitem__ = ReadOnlyContainer._readonly
# 
#     def __copy__(self):
#         return [*self]
# 
#     def __deepcopy__(self, memo):
#         lst = list(self)
#         return copy.deepcopy(lst, memo=memo)
# 
# class ReadOnlyDict(ReadOnlyContainer, dict):
#     """A read-only variant of a `dict`."""
# 
#     # Overwrite all methods that can modify a dict
#     clear = ReadOnlyContainer._readonly
#     pop = ReadOnlyContainer._readonly
#     popitem = ReadOnlyContainer._readonly
#     setdefault = ReadOnlyContainer._readonly
#     update = ReadOnlyContainer._readonly
#     __setitem__ = ReadOnlyContainer._readonly
#     __delitem__ = ReadOnlyContainer._readonly
# 
#     def __copy__(self):
#         return {**self}
# 
#     def __deepcopy__(self, memo):
#         d = dict(self)
#         return copy.deepcopy(d, memo=memo)
# 
# Path: sacred/utils.py
# class SacredError(Exception):
#     def __init__(
#         self,
#         message,
#         print_traceback=True,
#         filter_traceback="default",
#         print_usage=False,
#     ):
#         super().__init__(message)
#         self.print_traceback = print_traceback
#         if filter_traceback not in ["always", "default", "never"]:
#             raise ValueError(
#                 "filter_traceback must be one of 'always', "
#                 "'default' or 'never', not " + filter_traceback
#             )
#         self.filter_traceback = filter_traceback
#         self.print_usage = print_usage


import json
import pickle
import pytest
from copy import copy, deepcopy
from sacred.config.custom_containers import make_read_only, ReadOnlyList, ReadOnlyDict
from sacred.utils import SacredError
    d = make_read_only(d)
    copied_d = copy(d)
    for (k, v), (k_copied, v_copied) in zip(
        sorted(d.items()), sorted(copied_d.items())
    ):
        assert k == k_copied
        assert v == v_copied


def test_copy_on_nested_readonly_dict_still_raises():
    d = dict(a=1, b=dict(c=3))
    d = make_read_only(d)
    copied_d = copy(d)
    with pytest.raises(SacredError):
        copied_d["b"]["c"] = 4


def test_deepcopy_on_readonly_dict():
    d = dict(a=1, b=2, c=3)
    d = make_read_only(d)
    copied_d = deepcopy(d)
    for (k, v), (k_copied, v_copied) in zip(
        sorted(d.items()), sorted(copied_d.items())
    ):
        assert k == k_copied
        assert v == v_copied


def test_deepcopy_on_nested_readonly_dict():
    d = dict(a=1, b=dict(c=3))

# Path: sacred/config/custom_containers.py
# def make_read_only(o):
#     """Makes objects read-only.
# 
#     Converts every `list` and `dict` into `ReadOnlyList` and `ReadOnlyDict` in
#     a nested structure of `list`s, `dict`s and `tuple`s. Does not modify `o`
#     but returns the converted structure.
#     """
#     if type(o) == dict:
#         return ReadOnlyDict({k: make_read_only(v) for k, v in o.items()})
#     elif type(o) == list:
#         return ReadOnlyList([make_read_only(v) for v in o])
#     elif type(o) == tuple:
#         return tuple(map(make_read_only, o))
#     else:
#         return o
# 
# class ReadOnlyList(ReadOnlyContainer, list):
#     """A read-only variant of a `list`."""
# 
#     append = ReadOnlyContainer._readonly
#     clear = ReadOnlyContainer._readonly
#     extend = ReadOnlyContainer._readonly
#     insert = ReadOnlyContainer._readonly
#     pop = ReadOnlyContainer._readonly
#     remove = ReadOnlyContainer._readonly
#     reverse = ReadOnlyContainer._readonly
#     sort = ReadOnlyContainer._readonly
#     __setitem__ = ReadOnlyContainer._readonly
#     __delitem__ = ReadOnlyContainer._readonly
# 
#     def __copy__(self):
#         return [*self]
# 
#     def __deepcopy__(self, memo):
#         lst = list(self)
#         return copy.deepcopy(lst, memo=memo)
# 
# class ReadOnlyDict(ReadOnlyContainer, dict):
#     """A read-only variant of a `dict`."""
# 
#     # Overwrite all methods that can modify a dict
#     clear = ReadOnlyContainer._readonly
#     pop = ReadOnlyContainer._readonly
#     popitem = ReadOnlyContainer._readonly
#     setdefault = ReadOnlyContainer._readonly
#     update = ReadOnlyContainer._readonly
#     __setitem__ = ReadOnlyContainer._readonly
#     __delitem__ = ReadOnlyContainer._readonly
# 
#     def __copy__(self):
#         return {**self}
# 
#     def __deepcopy__(self, memo):
#         d = dict(self)
#         return copy.deepcopy(d, memo=memo)
# 
# Path: sacred/utils.py
# class SacredError(Exception):
#     def __init__(
#         self,
#         message,
#         print_traceback=True,
#         filter_traceback="default",
#         print_usage=False,
#     ):
#         super().__init__(message)
#         self.print_traceback = print_traceback
#         if filter_traceback not in ["always", "default", "never"]:
#             raise ValueError(
#                 "filter_traceback must be one of 'always', "
#                 "'default' or 'never', not " + filter_traceback
#             )
#         self.filter_traceback = filter_traceback
#         self.print_usage = print_usage


# Path: tests/test_config/test_readonly_containers.py
import json
import pickle
import pytest
from copy import copy, deepcopy
from sacred.config.custom_containers import make_read_only, ReadOnlyList, ReadOnlyDict
from sacred.utils import SacredError

    d = make_read_only(d)
    copied_d = copy(d)
    for (k, v), (k_copied, v_copied) in zip(
        sorted(d.items()), sorted(copied_d.items())
    ):
        assert k == k_copied
        assert v == v_copied


def test_copy_on_nested_readonly_dict_still_raises():
    d = dict(a=1, b=dict(c=3))
    d = make_read_only(d)
    copied_d = copy(d)
    with pytest.raises(SacredError):
        copied_d["b"]["c"] = 4


def test_deepcopy_on_readonly_dict():
    d = dict(a=1, b=2, c=3)
    d = make_read_only(d)
    copied_d = deepcopy(d)
    for (k, v), (k_copied, v_copied) in zip(
        sorted(d.items()), sorted(copied_d.items())
    ):
        assert k == k_copied
        assert v == v_copied


def test_deepcopy_on_nested_readonly_dict():
    d = dict(a=1, b=dict(c=3))

    d = make_read_only(d)