• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / RestrictedPython / 26870188116

03 Jun 2026 07:27AM UTC coverage: 98.978% (+0.006%) from 98.972%
26870188116

Pull #317

github

web-flow
Merge b1d1303c6 into a2891c0d1
Pull Request #317: Type Annotations for RestrictedPython

207 of 209 branches covered (99.04%)

153 of 154 new or added lines in 7 files covered. (99.35%)

3 existing lines in 2 files now uncovered.

2518 of 2544 relevant lines covered (98.98%)

0.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.46
/src/RestrictedPython/Utilities.py
1
##############################################################################
2
#
3
# Copyright (c) 2002 Zope Foundation and Contributors.
4
#
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
7
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
# FOR A PARTICULAR PURPOSE
11
#
12
##############################################################################
13

14
import collections.abc
1✔
15
import math
1✔
16
import random
1✔
17
import string
1✔
18

19

20
utility_builtins = {}
1✔
21

22

23
class _AttributeDelegator:
1✔
24
    def __init__(self, mod, *excludes):
1✔
25
        """delegate attribute lookups outside *excludes* to module *mod*."""
26
        self.__mod = mod
1✔
27
        self.__excludes = excludes
1✔
28

29
    def __getattr__(self, attr):
1✔
30
        if attr in self.__excludes:
1✔
31
            raise NotImplementedError(
32
                f"{self.__mod.__name__}.{attr} is not safe")
33
        try:
1✔
34
            return getattr(self.__mod, attr)
1✔
35
        except AttributeError as e:
1✔
36
            e.obj = self
1✔
37
            raise
1✔
38

39

40
utility_builtins['string'] = _AttributeDelegator(string, "Formatter")
1✔
41
utility_builtins['math'] = math
1✔
42
utility_builtins['random'] = random
1✔
43
utility_builtins['whrandom'] = random
1✔
44
utility_builtins['set'] = set
1✔
45
utility_builtins['frozenset'] = frozenset
1✔
46

47
try:
1✔
48
    import DateTime
1✔
UNCOV
49
    utility_builtins['DateTime'] = DateTime.DateTime
×
50
except ImportError:
51
    pass
52

53

54
def same_type(arg1, *args):
1✔
55
    """Compares the class or type of two or more objects."""
56
    t = getattr(arg1, '__class__', type(arg1))
1✔
57
    for arg in args:
1✔
58
        if getattr(arg, '__class__', type(arg)) is not t:
1✔
59
            return False
1✔
60
    return True
1✔
61

62

63
utility_builtins['same_type'] = same_type
1✔
64

65

66
def test(*args):
1✔
67
    length = len(args)
1✔
68
    for i in range(1, length, 2):
1✔
69
        if args[i - 1]:
1✔
70
            return args[i]
1✔
71

72
    if length % 2:
1✔
73
        return args[-1]
1✔
74

75

76
utility_builtins['test'] = test
1✔
77

78

79
def reorder(
1✔
80
        s: collections.abc.Iterable,
81
        with_: collections.abc.Iterable | None = None,
82
        without: collections.abc.Iterable = ()) -> collections.abc.Iterable:
83
    # s, with_, and without are sequences treated as sets.
84
    # The result is subtract(intersect(s, with_), without),
85
    # unless with_ is None, in which case it is subtract(s, without).
86
    if with_ is None:
1✔
87
        with_ = s
1✔
88
    orig = {}
1✔
89
    for item in s:
1✔
90
        if isinstance(item, tuple) and len(item) == 2:
1✔
91
            key, value = item
1✔
92
        else:
93
            key = value = item
1✔
94
        orig[key] = value
1✔
95

96
    result = []
1✔
97

98
    for item in without:
1✔
99
        if isinstance(item, tuple) and len(item) == 2:
1✔
100
            key, ignored = item
1✔
101
        else:
102
            key = item
1✔
103
        if key in orig:
1✔
104
            del orig[key]
1✔
105

106
    for item in with_:
1✔
107
        if isinstance(item, tuple) and len(item) == 2:
1✔
108
            key, ignored = item
1✔
109
        else:
110
            key = item
1✔
111
        if key in orig:
1✔
112
            result.append((key, orig[key]))
1✔
113
            del orig[key]
1✔
114

115
    return result
1✔
116

117

118
utility_builtins['reorder'] = reorder
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc