From f785f6223c305af417c213a0b5a46b9f48521a89 Mon Sep 17 00:00:00 2001 From: Parthiv Patel Date: Mon, 23 Oct 2023 10:44:57 +0000 Subject: [PATCH] [PATCH] upstream --- flectra/tools/_monkeypatches.py | 8 +++++++ flectra/tools/misc.py | 34 +++++++++++++++++++++++++++ flectra/tools/template_inheritance.py | 5 ++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/flectra/tools/_monkeypatches.py b/flectra/tools/_monkeypatches.py index b55ffd073a..ea3a20d99a 100644 --- a/flectra/tools/_monkeypatches.py +++ b/flectra/tools/_monkeypatches.py @@ -30,6 +30,14 @@ FileStorage.save = lambda self, dst, buffer_size=1<<20: copyfileobj(self.stream, Request.json_module = Response.json_module = scriptsafe +get_func_code = getattr(Rule, '_get_func_code', None) +if get_func_code: + @staticmethod + def _get_func_code(code, name): + assert isinstance(code, CodeType) + return get_func_code(code, name) + Rule._get_func_code = _get_func_code + orig_literal_eval = ast.literal_eval def literal_eval(expr): diff --git a/flectra/tools/misc.py b/flectra/tools/misc.py index ecbf5c46c6..f613eb390b 100644 --- a/flectra/tools/misc.py +++ b/flectra/tools/misc.py @@ -1576,6 +1576,40 @@ pickle.dump = pickle_.dump pickle.dumps = pickle_.dumps +class ReadonlyDict(Mapping): + """Helper for an unmodifiable dictionary, not even updatable using `dict.update`. + + This is similar to a `frozendict`, with one drawback and one advantage: + + - `dict.update` works for a `frozendict` but not for a `ReadonlyDict`. + - `json.dumps` works for a `frozendict` by default but not for a `ReadonlyDict`. + + This comes from the fact `frozendict` inherits from `dict` + while `ReadonlyDict` inherits from `collections.abc.Mapping`. + + So, depending on your needs, + whether you absolutely must prevent the dictionary from being updated (e.g., for security reasons) + or you require it to be supported by `json.dumps`, you can choose either option. + + E.g. + data = ReadonlyDict({'foo': 'bar'}) + data['baz'] = 'xyz' # raises exception + data.update({'baz', 'xyz'}) # raises exception + dict.update(data, {'baz': 'xyz'}) # raises exception + """ + def __init__(self, data): + self.__data = dict(data) + + def __getitem__(self, key): + return self.__data[key] + + def __len__(self): + return len(self.__data) + + def __iter__(self): + return iter(self.__data) + + class DotDict(dict): """Helper for dot.notation access to dictionary attributes diff --git a/flectra/tools/template_inheritance.py b/flectra/tools/template_inheritance.py index 1cce49701c..085312ed00 100644 --- a/flectra/tools/template_inheritance.py +++ b/flectra/tools/template_inheritance.py @@ -56,9 +56,8 @@ def locate_node(arch, spec): expr = spec.get('expr') try: xPath = etree.ETXPath(expr) - except etree.XPathSyntaxError: - _logger.error("XPathSyntaxError while parsing xpath %r", expr) - raise + except etree.XPathSyntaxError as e: + raise ValidationError(_("Invalid Expression while parsing xpath %r", expr)) from e nodes = xPath(arch) return nodes[0] if nodes else None elif spec.tag == 'field':