зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1632870 - [mozbuild] Allow making copies of 'mozbuild.util.ReadOnlyDict', r=firefox-build-system-reviewers,mhentges
The copy and deepcopy operations currently use 'setitem' which obviously fails for 'ReadOnlyDict'. But copying the dict yields a new instance so there should be no reason this is prevented. Specifically, I'd like to make certain subsets of task configuration read-only. But copying is needed when we split the task into multiple tasks (e.g for chunking). Differential Revision: https://phabricator.services.mozilla.com/D131284
This commit is contained in:
Родитель
6340a6db91
Коммит
7856dcfe71
|
@ -5,6 +5,7 @@
|
|||
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import copy
|
||||
import hashlib
|
||||
import io
|
||||
import itertools
|
||||
|
@ -15,6 +16,7 @@ import string
|
|||
import sys
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
from mozfile.mozfile import NamedTemporaryFile
|
||||
from mozunit import main
|
||||
|
||||
|
@ -32,6 +34,7 @@ from mozbuild.util import (
|
|||
HierarchicalStringList,
|
||||
EnumString,
|
||||
EnumStringComparisonError,
|
||||
ReadOnlyDict,
|
||||
StrictOrderingOnAppendList,
|
||||
StrictOrderingOnAppendListWithAction,
|
||||
StrictOrderingOnAppendListWithFlagsFactory,
|
||||
|
@ -927,5 +930,32 @@ class TestHexDump(unittest.TestCase):
|
|||
)
|
||||
|
||||
|
||||
def test_read_only_dict():
|
||||
d = ReadOnlyDict(foo="bar")
|
||||
with pytest.raises(Exception):
|
||||
d["foo"] = "baz"
|
||||
|
||||
with pytest.raises(Exception):
|
||||
d.update({"foo": "baz"})
|
||||
|
||||
with pytest.raises(Exception):
|
||||
del d["foo"]
|
||||
|
||||
# ensure copy still works
|
||||
d_copy = d.copy()
|
||||
assert d == d_copy
|
||||
# TODO Returning a dict here feels like a bug, but there are places in-tree
|
||||
# relying on this behaviour.
|
||||
assert isinstance(d_copy, dict)
|
||||
|
||||
d_copy = copy.copy(d)
|
||||
assert d == d_copy
|
||||
assert isinstance(d_copy, ReadOnlyDict)
|
||||
|
||||
d_copy = copy.deepcopy(d)
|
||||
assert d == d_copy
|
||||
assert isinstance(d_copy, ReadOnlyDict)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -10,6 +10,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
import argparse
|
||||
import collections
|
||||
import collections.abc
|
||||
import copy
|
||||
import ctypes
|
||||
import difflib
|
||||
import errno
|
||||
|
@ -133,6 +134,16 @@ class ReadOnlyDict(dict):
|
|||
def update(self, *args, **kwargs):
|
||||
raise Exception("Object does not support update.")
|
||||
|
||||
def __copy__(self, *args, **kwargs):
|
||||
return ReadOnlyDict(**dict.copy(self, *args, **kwargs))
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
result = {}
|
||||
for k, v in self.items():
|
||||
result[k] = copy.deepcopy(v, memo)
|
||||
|
||||
return ReadOnlyDict(**result)
|
||||
|
||||
|
||||
class undefined_default(object):
|
||||
"""Represents an undefined argument value that isn't None."""
|
||||
|
|
Загрузка…
Ссылка в новой задаче