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

CityOfZion / neo3-boa / cfb7933f-2cb9-40ed-8eeb-fdcaff5adc56

02 Jan 2024 02:52PM UTC coverage: 92.1% (+0.02%) from 92.076%
cfb7933f-2cb9-40ed-8eeb-fdcaff5adc56

push

circleci

web-flow
Merge pull request #1156 from CityOfZion/CU-86a1huhbg

Implement the structure used on all boa unit tests working with BoaTestConstructor

1 of 1 new or added line in 1 file covered. (100.0%)

10 existing lines in 2 files now uncovered.

20763 of 22544 relevant lines covered (92.1%)

1.84 hits per line

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

91.45
/boa3/internal/model/callable.py
1
from __future__ import annotations
2✔
2

3
import ast
2✔
4
from abc import ABC
2✔
5
from typing import Dict, List, Optional, Set, Tuple
2✔
6

7
from boa3.internal.model import set_internal_call
2✔
8
from boa3.internal.model.expression import IExpression
2✔
9
from boa3.internal.model.type.type import IType, Type
2✔
10
from boa3.internal.model.variable import Variable
2✔
11
from boa3.internal.neo.vm.VMCode import VMCode
2✔
12

13

14
class Callable(IExpression, ABC):
2✔
15
    """
16
    A class used to represent a function or a class method
17

18
    :ivar args: a dictionary that maps each arg with its name. Empty by default.
19
    :ivar is_public: a boolean value that specifies if the method is public. False by default.
20
    :ivar return_type: the return type of the method. None by default.
21
    """
22

23
    def __init__(self, args: Dict[str, Variable] = None,
2✔
24
                 vararg: Optional[Tuple[str, Variable]] = None,
25
                 kwargs: Optional[Dict[str, Variable]] = None,
26
                 defaults: List[ast.AST] = None,
27
                 return_type: IType = Type.none, is_public: bool = False,
28
                 decorators: List[Callable] = None,
29
                 external_name: str = None,
30
                 is_safe: bool = False,
31
                 origin_node: Optional[ast.AST] = None):
32

33
        if args is None:
2✔
34
            args = {}
2✔
35
        self.args: Dict[str, Variable] = args.copy()
2✔
36

37
        if not isinstance(defaults, list):
2✔
38
            defaults = []
2✔
39
        self.defaults: List[ast.AST] = defaults
2✔
40

41
        self._vararg: Optional[Tuple[str, Variable]] = None
2✔
42
        if (isinstance(vararg, tuple) and len(vararg) == 2
2✔
43
                and isinstance(vararg[0], str) and isinstance(vararg[1], Variable)):
44

45
            from boa3.internal.model.type.typeutils import TypeUtils
2✔
46

47
            vararg_id, vararg_var = vararg
2✔
48
            if vararg_var.type is not Type.any:
2✔
49
                default_code = "{0}({1}, {2})".format(TypeUtils.cast.raw_identifier,
2✔
50
                                                      Type.tuple.build_collection(vararg_var.type),
51
                                                      Type.tuple.default_value)
52
            else:
53
                default_code = "{0}".format(Type.tuple.default_value)
×
54

55
            default_value = set_internal_call(ast.parse(default_code).body[0].value)
2✔
56

57
            self.args[vararg_id] = Variable(Type.tuple.build_collection([vararg_var.type]))
2✔
58
            self.defaults.append(default_value)
2✔
59
            self._vararg = vararg
2✔
60

61
        if kwargs is None:
2✔
62
            kwargs = {}
2✔
63
        self._kwargs: Dict[str, Variable] = kwargs.copy()
2✔
64

65
        self.return_type: IType = return_type
2✔
66

67
        if decorators is None:
2✔
68
            decorators = []
2✔
69
        from boa3.internal.model.decorator import IDecorator
2✔
70
        self.decorators: List[IDecorator] = [decorator for decorator in decorators
2✔
71
                                             if isinstance(decorator, IDecorator)]
72

73
        from boa3.internal.model.builtin.decorator import PublicDecorator
2✔
74
        public_decorator = next((decorator for decorator in self.decorators
2✔
75
                                 if isinstance(decorator, PublicDecorator)),
76
                                None)
77

78
        self.is_public: bool = is_public or public_decorator is not None
2✔
79
        if self.is_public:
2✔
80
            if isinstance(public_decorator, PublicDecorator):
2✔
81
                external_name = public_decorator.name
2✔
82
            elif self.defined_by_entry:
2✔
83
                external_name = None
×
84

85
        self.external_name: Optional[str] = external_name
2✔
86
        self.is_safe: bool = is_safe or (isinstance(public_decorator, PublicDecorator) and public_decorator.safe)
2✔
87

88
        self._self_calls: Set[ast.AST] = set()
2✔
89

90
        super().__init__(origin_node)
2✔
91

92
        self.init_address: Optional[int] = None
2✔
93
        self.init_bytecode: Optional[VMCode] = None
2✔
94
        self.init_defaults_bytecode: Optional[VMCode] = None
2✔
95
        self.end_bytecode: Optional[VMCode] = None
2✔
96

97
    @property
2✔
98
    def type(self) -> IType:
2✔
99
        return self.return_type
2✔
100

101
    @property
2✔
102
    def symbols(self) -> Dict[str, Variable]:
2✔
103
        """
104
        Gets all the symbols in the method
105

106
        :return: a dictionary that maps each symbol in the module with its name
107
        """
108
        return self.args.copy()
×
109

110
    @property
2✔
111
    def args_without_default(self) -> Dict[str, Variable]:
2✔
112
        num_defaults = len(self.defaults)
2✔
113
        if num_defaults > 0:
2✔
114
            return {key: self.args[key] for key in list(self.args.keys())[:-num_defaults]}
2✔
115
        return self.args
2✔
116

117
    @property
2✔
118
    def positional_args(self) -> Dict[str, Variable]:
2✔
119
        return {key: value for key, value in self.args.items() if key not in self._kwargs}
2✔
120

121
    @property
2✔
122
    def has_cls_or_self(self) -> bool:
2✔
123
        return any(decorator.has_cls_or_self for decorator in self.decorators)
2✔
124

125
    @property
2✔
126
    def cls_or_self_type(self) -> Optional[IType]:
2✔
UNCOV
127
        if not self.has_cls_or_self or len(self.args) == 0:
×
UNCOV
128
            return None
×
129

UNCOV
130
        return list(self.args.values())[0].type
×
131

132
    @property
2✔
133
    def has_starred_argument(self) -> bool:
2✔
134
        return self._vararg is not None
2✔
135

136
    @property
2✔
137
    def start_address(self) -> Optional[int]:
2✔
138
        """
139
        Gets the address where this method starts in the bytecode
140

141
        :return: the first address of the method
142
        """
143
        if self.init_bytecode is None and self.init_defaults_bytecode is None:
2✔
144
            return self.init_address
2✔
145
        else:
146
            from boa3.internal.compiler.codegenerator.vmcodemapping import VMCodeMapping
2✔
147
            return VMCodeMapping.instance().get_start_address(self.init_bytecode)
2✔
148

149
    @property
2✔
150
    def start_bytecode(self) -> Optional[VMCode]:
2✔
151
        return (self.init_defaults_bytecode if len(self.defaults) > 0
2✔
152
                else self.init_bytecode)
153

154
    @property
2✔
155
    def end_address(self) -> Optional[int]:
2✔
156
        """
157
        Gets the address of this method's last operation in the bytecode
158

159
        :return: the last address of the method
160
        """
161
        if self.end_bytecode is None:
2✔
162
            return self.start_address
2✔
163
        else:
164
            from boa3.internal.compiler.codegenerator.vmcodemapping import VMCodeMapping
2✔
165
            return VMCodeMapping.instance().get_end_address(self.end_bytecode)
2✔
166

167
    @property
2✔
168
    def is_called(self) -> bool:
2✔
169
        return len(self._self_calls) > 0
2✔
170

171
    def reset_calls(self):
2✔
172
        self._self_calls.clear()
2✔
173

174
    @property
2✔
175
    def is_compiled(self) -> bool:
2✔
176
        return self.start_address is not None and self.end_address is not None
2✔
177

178
    def add_call_origin(self, origin: ast.AST) -> bool:
2✔
179
        try:
2✔
180
            self._self_calls.add(origin)
2✔
181
            return True
2✔
UNCOV
182
        except BaseException:
×
UNCOV
183
            return False
×
184

185
    def __str__(self) -> str:
2✔
186
        args_types: List[str] = [str(arg.type) for arg in self.args.values()]
2✔
187
        if self.return_type is not Type.none:
2✔
188
            signature = '({0}) -> {1}'.format(', '.join(args_types), self.return_type)
2✔
189
        else:
190
            signature = '({0})'.format(', '.join(args_types))
2✔
191
        public = 'public ' if self.is_public else ''
2✔
192
        return '{0}{1}'.format(public, signature)
2✔
193

194
    def __repr__(self) -> str:
2✔
UNCOV
195
        name = self.identifier if hasattr(self, 'identifier') else self.__class__.__name__
×
UNCOV
196
        return f'{name}{str(self)}'
×
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

© 2025 Coveralls, Inc