classiq 0.43.3__py3-none-any.whl → 0.44.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. classiq/__init__.py +7 -1
  2. classiq/_internals/client.py +4 -7
  3. classiq/_internals/host_checker.py +34 -12
  4. classiq/_internals/jobs.py +2 -2
  5. classiq/applications/chemistry/chemistry_model_constructor.py +12 -6
  6. classiq/applications/combinatorial_helpers/allowed_constraints.py +4 -1
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +1 -1
  8. classiq/applications/finance/finance_model_constructor.py +3 -2
  9. classiq/applications/grover/grover_model_constructor.py +7 -5
  10. classiq/applications/hamiltonian/__init__.py +0 -0
  11. classiq/applications/hamiltonian/pauli_decomposition.py +113 -0
  12. classiq/applications/qnn/qlayer.py +1 -1
  13. classiq/exceptions.py +4 -0
  14. classiq/interface/_version.py +1 -1
  15. classiq/interface/ast_node.py +1 -18
  16. classiq/interface/backend/backend_preferences.py +10 -16
  17. classiq/interface/backend/ionq/ionq_quantum_program.py +1 -1
  18. classiq/interface/backend/pydantic_backend.py +0 -5
  19. classiq/interface/backend/quantum_backend_providers.py +3 -2
  20. classiq/interface/chemistry/operator.py +5 -1
  21. classiq/interface/debug_info/__init__.py +0 -0
  22. classiq/interface/debug_info/debug_info.py +32 -0
  23. classiq/interface/executor/execution_preferences.py +1 -45
  24. classiq/interface/executor/result.py +25 -12
  25. classiq/interface/generator/application_apis/arithmetic_declarations.py +8 -5
  26. classiq/interface/generator/application_apis/chemistry_declarations.py +78 -60
  27. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +19 -10
  28. classiq/interface/generator/application_apis/entangler_declarations.py +11 -6
  29. classiq/interface/generator/application_apis/finance_declarations.py +36 -22
  30. classiq/interface/generator/application_apis/qsvm_declarations.py +21 -15
  31. classiq/interface/generator/arith/arithmetic_expression_abc.py +21 -1
  32. classiq/interface/generator/arith/binary_ops.py +5 -4
  33. classiq/interface/generator/arith/extremum_operations.py +43 -19
  34. classiq/interface/generator/constant.py +1 -1
  35. classiq/interface/generator/expressions/atomic_expression_functions.py +1 -0
  36. classiq/interface/generator/expressions/expression_constants.py +3 -1
  37. classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -66
  38. classiq/interface/generator/expressions/qmod_qstruct_proxy.py +35 -0
  39. classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
  40. classiq/interface/generator/functions/builtins/core_library/__init__.py +4 -2
  41. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +41 -41
  42. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +52 -42
  43. classiq/interface/generator/functions/builtins/open_lib_functions.py +1095 -3347
  44. classiq/interface/generator/functions/builtins/quantum_operators.py +9 -22
  45. classiq/interface/generator/functions/classical_function_declaration.py +14 -6
  46. classiq/interface/generator/functions/classical_type.py +7 -76
  47. classiq/interface/generator/functions/concrete_types.py +55 -0
  48. classiq/interface/generator/functions/function_declaration.py +10 -10
  49. classiq/interface/generator/functions/type_name.py +104 -0
  50. classiq/interface/generator/generated_circuit_data.py +3 -3
  51. classiq/interface/generator/model/model.py +11 -0
  52. classiq/interface/generator/model/preferences/preferences.py +5 -0
  53. classiq/interface/generator/quantum_function_call.py +3 -0
  54. classiq/interface/generator/quantum_program.py +2 -2
  55. classiq/interface/generator/register_role.py +7 -1
  56. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +1 -3
  57. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +1 -2
  58. classiq/interface/generator/types/qstruct_declaration.py +17 -0
  59. classiq/interface/generator/types/struct_declaration.py +1 -1
  60. classiq/interface/helpers/validation_helpers.py +1 -17
  61. classiq/interface/ide/visual_model.py +9 -2
  62. classiq/interface/interface_version.py +1 -0
  63. classiq/interface/model/bind_operation.py +25 -5
  64. classiq/interface/model/classical_parameter_declaration.py +8 -5
  65. classiq/interface/model/control.py +5 -5
  66. classiq/interface/model/handle_binding.py +185 -12
  67. classiq/interface/model/inplace_binary_operation.py +16 -4
  68. classiq/interface/model/model.py +28 -5
  69. classiq/interface/model/native_function_definition.py +8 -4
  70. classiq/interface/model/parameter.py +14 -0
  71. classiq/interface/model/port_declaration.py +20 -2
  72. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +21 -6
  73. classiq/interface/model/quantum_expressions/arithmetic_operation.py +30 -6
  74. classiq/interface/model/quantum_expressions/quantum_expression.py +4 -9
  75. classiq/interface/model/quantum_function_call.py +135 -192
  76. classiq/interface/model/quantum_function_declaration.py +147 -165
  77. classiq/interface/model/quantum_lambda_function.py +24 -6
  78. classiq/interface/model/quantum_statement.py +34 -8
  79. classiq/interface/model/quantum_type.py +61 -10
  80. classiq/interface/model/quantum_variable_declaration.py +1 -1
  81. classiq/interface/model/statement_block.py +2 -0
  82. classiq/interface/model/validation_handle.py +7 -0
  83. classiq/interface/server/global_versions.py +4 -4
  84. classiq/interface/server/routes.py +2 -0
  85. classiq/interface/source_reference.py +59 -0
  86. classiq/qmod/__init__.py +2 -3
  87. classiq/qmod/builtins/functions.py +39 -11
  88. classiq/qmod/builtins/operations.py +171 -40
  89. classiq/qmod/declaration_inferrer.py +99 -56
  90. classiq/qmod/expression_query.py +1 -1
  91. classiq/qmod/model_state_container.py +2 -0
  92. classiq/qmod/native/pretty_printer.py +71 -53
  93. classiq/qmod/pretty_print/pretty_printer.py +98 -52
  94. classiq/qmod/qfunc.py +11 -5
  95. classiq/qmod/qmod_parameter.py +1 -2
  96. classiq/qmod/qmod_variable.py +364 -172
  97. classiq/qmod/quantum_callable.py +3 -3
  98. classiq/qmod/quantum_expandable.py +119 -65
  99. classiq/qmod/quantum_function.py +15 -3
  100. classiq/qmod/semantics/annotation.py +12 -13
  101. classiq/qmod/semantics/error_manager.py +36 -10
  102. classiq/qmod/semantics/static_semantics_visitor.py +163 -75
  103. classiq/qmod/semantics/validation/func_call_validation.py +42 -96
  104. classiq/qmod/semantics/validation/handle_validation.py +85 -0
  105. classiq/qmod/semantics/validation/types_validation.py +108 -1
  106. classiq/qmod/type_attribute_remover.py +32 -0
  107. classiq/qmod/utilities.py +26 -5
  108. {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/METADATA +3 -3
  109. {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/RECORD +111 -99
  110. classiq/qmod/qmod_struct.py +0 -13
  111. /classiq/{interface/ide/show.py → show.py} +0 -0
  112. {classiq-0.43.3.dist-info → classiq-0.44.0.dist-info}/WHEEL +0 -0
@@ -1,14 +1,13 @@
1
1
  import abc
2
- from typing import Dict, List, Mapping, Optional, Union
2
+ from typing import Dict, List, Mapping, Optional
3
3
 
4
4
  import pydantic
5
5
 
6
6
  from classiq.interface.generator.expressions.expression import Expression
7
7
  from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
8
8
  from classiq.interface.model.handle_binding import (
9
+ ConcreteHandleBinding,
9
10
  HandleBinding,
10
- SlicedHandleBinding,
11
- SubscriptHandleBinding,
12
11
  )
13
12
  from classiq.interface.model.quantum_statement import QuantumOperation
14
13
  from classiq.interface.model.quantum_type import QuantumType
@@ -43,16 +42,12 @@ class QuantumExpressionOperation(QuantumOperation):
43
42
  self._var_types = var_types
44
43
 
45
44
  @property
46
- def wiring_inouts(
47
- self,
48
- ) -> Mapping[
49
- str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]
50
- ]:
45
+ def wiring_inouts(self) -> Mapping[str, ConcreteHandleBinding]:
51
46
  return nameables_to_dict(self.var_handles)
52
47
 
53
48
 
54
49
  class QuantumAssignmentOperation(QuantumExpressionOperation):
55
- result_var: HandleBinding = pydantic.Field(
50
+ result_var: ConcreteHandleBinding = pydantic.Field(
56
51
  description="The variable storing the expression result"
57
52
  )
58
53
  _result_type: Optional[QuantumType] = pydantic.PrivateAttr(
@@ -1,104 +1,40 @@
1
- import itertools
2
- from typing import Any, Dict, List, Literal, Mapping, Optional, Type, Union
1
+ from typing import (
2
+ Dict,
3
+ Iterable,
4
+ List,
5
+ Literal,
6
+ Mapping,
7
+ Optional,
8
+ Sequence,
9
+ Tuple,
10
+ Union,
11
+ )
12
+ from uuid import UUID, uuid4
3
13
 
4
14
  import pydantic
5
15
 
6
16
  from classiq.interface.ast_node import ASTNode
7
17
  from classiq.interface.generator.expressions.expression import Expression
8
- from classiq.interface.generator.functions.function_declaration import (
9
- FunctionDeclaration,
10
- )
11
18
  from classiq.interface.generator.functions.port_declaration import (
12
19
  PortDeclarationDirection,
13
20
  )
14
21
  from classiq.interface.model.handle_binding import (
22
+ ConcreteHandleBinding,
15
23
  HandleBinding,
16
- SlicedHandleBinding,
17
- SubscriptHandleBinding,
18
24
  )
25
+ from classiq.interface.model.port_declaration import AnonPortDeclaration
19
26
  from classiq.interface.model.quantum_function_declaration import (
20
27
  QuantumFunctionDeclaration,
21
28
  )
22
- from classiq.interface.model.quantum_lambda_function import (
23
- QuantumOperand,
24
- )
25
- from classiq.interface.model.quantum_statement import QuantumOperation
26
- from classiq.interface.model.validation_handle import get_unique_handle_names
29
+ from classiq.interface.model.quantum_lambda_function import QuantumOperand
30
+ from classiq.interface.model.quantum_statement import HandleMetadata, QuantumOperation
27
31
 
28
32
  from classiq.exceptions import ClassiqError, ClassiqValueError
29
33
 
30
-
31
- def _validate_no_duplicated_ports(
32
- inputs: Mapping[str, HandleBinding],
33
- outputs: Mapping[str, HandleBinding],
34
- inouts: Mapping[str, HandleBinding],
35
- ) -> None:
36
- inputs_and_inouts = inputs.keys() & inouts.keys()
37
- if inputs_and_inouts:
38
- raise ClassiqValueError(
39
- f"{inputs_and_inouts} are used as ports in both inputs and inouts"
40
- )
41
-
42
- outputs_and_inouts = outputs.keys() & inouts.keys()
43
- if outputs_and_inouts:
44
- raise ClassiqValueError(
45
- f"{outputs_and_inouts} are used as ports in both outputs and inouts"
46
- )
47
-
48
-
49
- def _validate_no_duplicated_handles(
50
- inputs: Mapping[str, HandleBinding],
51
- outputs: Mapping[str, HandleBinding],
52
- inouts: Mapping[str, HandleBinding],
53
- ) -> None:
54
- inputs_and_inouts = get_unique_handle_names(inputs) & get_unique_handle_names(
55
- inouts
56
- )
57
- if inputs_and_inouts:
58
- raise ClassiqValueError(
59
- f"{inputs_and_inouts} are used as handles in both inputs and inouts"
60
- )
61
-
62
- outputs_and_inouts = get_unique_handle_names(outputs) & get_unique_handle_names(
63
- inouts
64
- )
65
- if outputs_and_inouts:
66
- raise ClassiqValueError(
67
- f"{outputs_and_inouts} are used as handles in both outputs and inouts"
68
- )
69
-
70
-
71
- def _validate_no_mixing_sliced_and_whole_handles(
72
- inouts: Mapping[str, HandleBinding],
73
- ) -> None:
74
- def _treat_subscript_as_slice(type_: Type[HandleBinding]) -> Type[HandleBinding]:
75
- if type_ == SubscriptHandleBinding:
76
- return SlicedHandleBinding
77
- return type_
78
-
79
- inout_handle_names_to_types = {
80
- handle_name: {_treat_subscript_as_slice(type(handle)) for handle in handles}
81
- for handle_name, handles in itertools.groupby(
82
- inouts.values(), lambda handle: handle.name
83
- )
84
- }
85
- invalid_handles = [
86
- handle
87
- for handle, types in inout_handle_names_to_types.items()
88
- if len(types) > 1
89
- ]
90
- if invalid_handles:
91
- raise ClassiqValueError(
92
- f"Inout handles {', '.join(invalid_handles)} mix sliced and whole handles"
93
- )
94
-
95
-
96
34
  ArgValue = Union[
97
35
  Expression,
98
36
  QuantumOperand,
99
- SlicedHandleBinding,
100
- SubscriptHandleBinding,
101
- HandleBinding,
37
+ ConcreteHandleBinding,
102
38
  ]
103
39
 
104
40
 
@@ -113,26 +49,10 @@ class QuantumFunctionCall(QuantumOperation):
113
49
  function: Union[str, OperandIdentifier] = pydantic.Field(
114
50
  description="The function that is called"
115
51
  )
116
- designated_params: Dict[str, Expression] = pydantic.Field(default_factory=dict)
117
- designated_inputs: Dict[str, HandleBinding] = pydantic.Field(
118
- default_factory=dict,
119
- description="A mapping from the input name to the wire it connects to",
120
- )
121
- designated_inouts: Dict[
122
- str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]
123
- ] = pydantic.Field(
124
- default_factory=dict,
125
- description="A mapping from in/out name to the wires that connect to it",
126
- )
127
- designated_outputs: Dict[str, HandleBinding] = pydantic.Field(
128
- default_factory=dict,
129
- description="A mapping from the output name to the wire it connects to",
130
- )
131
- designated_operands: Dict[str, QuantumOperand] = pydantic.Field(
132
- description="Function calls passed to the operator",
133
- default_factory=dict,
134
- )
135
52
  positional_args: List[ArgValue] = pydantic.Field(default_factory=list)
53
+ uuid: UUID = pydantic.Field(
54
+ description="A unique identifier for this call", default_factory=uuid4
55
+ )
136
56
 
137
57
  _func_decl: Optional[QuantumFunctionDeclaration] = pydantic.PrivateAttr(
138
58
  default=None
@@ -145,7 +65,7 @@ class QuantumFunctionCall(QuantumOperation):
145
65
 
146
66
  return self._func_decl
147
67
 
148
- def set_func_decl(self, fd: Optional[FunctionDeclaration]) -> None:
68
+ def set_func_decl(self, fd: Optional[QuantumFunctionDeclaration]) -> None:
149
69
  if fd is not None and not isinstance(fd, QuantumFunctionDeclaration):
150
70
  raise ClassiqValueError(
151
71
  "the declaration of a quantum function call cannot be set to a non-quantum function declaration."
@@ -160,76 +80,113 @@ class QuantumFunctionCall(QuantumOperation):
160
80
 
161
81
  @property
162
82
  def wiring_inputs(self) -> Mapping[str, HandleBinding]:
163
- return self.inputs
83
+ return self._get_pos_port_args_by_direction(PortDeclarationDirection.Input)
84
+
85
+ @property
86
+ def inputs(self) -> Sequence[HandleBinding]:
87
+ return [
88
+ handle
89
+ for _, _, handle in self._get_handles_by_direction(
90
+ PortDeclarationDirection.Input
91
+ )
92
+ ]
93
+
94
+ @property
95
+ def readable_inputs(self) -> Sequence[HandleMetadata]:
96
+ return [
97
+ HandleMetadata(
98
+ handle=handle,
99
+ readable_location=self._get_readable_location(param_idx, param),
100
+ )
101
+ for param_idx, param, handle in self._get_handles_by_direction(
102
+ PortDeclarationDirection.Input
103
+ )
104
+ ]
164
105
 
165
106
  @property
166
107
  def wiring_inouts(
167
108
  self,
168
- ) -> Mapping[
169
- str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]
170
- ]:
171
- return self.inouts
109
+ ) -> Mapping[str, ConcreteHandleBinding]:
110
+ return self._get_pos_port_args_by_direction(PortDeclarationDirection.Inout)
111
+
112
+ @property
113
+ def inouts(self) -> Sequence[HandleBinding]:
114
+ return [
115
+ handle
116
+ for _, _, handle in self._get_handles_by_direction(
117
+ PortDeclarationDirection.Inout
118
+ )
119
+ ]
120
+
121
+ @property
122
+ def readable_inouts(self) -> Sequence[HandleMetadata]:
123
+ return [
124
+ HandleMetadata(
125
+ handle=handle,
126
+ readable_location=self._get_readable_location(param_idx, param),
127
+ )
128
+ for param_idx, param, handle in self._get_handles_by_direction(
129
+ PortDeclarationDirection.Inout
130
+ )
131
+ ]
172
132
 
173
133
  @property
174
134
  def wiring_outputs(self) -> Mapping[str, HandleBinding]:
175
- return self.outputs
135
+ return self._get_pos_port_args_by_direction(PortDeclarationDirection.Output)
176
136
 
177
- def get_positional_args(self) -> List[ArgValue]:
178
- result: List[ArgValue] = self.positional_args
179
- if not result:
180
- result = list(self.designated_params.values())
181
- result.extend(self.designated_operands.values())
182
- result.extend(self.designated_inputs.values())
183
- result.extend(self.designated_inouts.values())
184
- result.extend(self.designated_outputs.values())
185
- return result
137
+ @property
138
+ def outputs(self) -> Sequence[HandleBinding]:
139
+ return [
140
+ handle
141
+ for _, _, handle in self._get_handles_by_direction(
142
+ PortDeclarationDirection.Output
143
+ )
144
+ ]
186
145
 
187
146
  @property
188
- def positional_params(self) -> Dict[str, Expression]:
189
- return dict(
190
- zip(
191
- self.func_decl.param_decls.keys(),
192
- (
193
- param
194
- for param in self.positional_args
195
- if isinstance(param, Expression)
196
- ),
147
+ def readable_outputs(self) -> Sequence[HandleMetadata]:
148
+ return [
149
+ HandleMetadata(
150
+ handle=handle,
151
+ readable_location=self._get_readable_location(param_idx, param),
197
152
  )
198
- )
153
+ for param_idx, param, handle in self._get_handles_by_direction(
154
+ PortDeclarationDirection.Output
155
+ )
156
+ ]
199
157
 
200
158
  @property
201
- def params(self) -> Dict[str, Expression]:
202
- return self.positional_params or self.designated_params
159
+ def params(self) -> List[Expression]:
160
+ return [
161
+ param for param in self.positional_args if isinstance(param, Expression)
162
+ ]
203
163
 
204
164
  @property
205
- def positional_operands(self) -> Dict[str, "QuantumOperand"]:
206
- return dict(
207
- zip(
208
- self.func_decl.operand_declarations.keys(),
209
- (
210
- param
211
- for param in self.positional_args
212
- if not isinstance(param, (Expression, HandleBinding))
213
- ),
214
- )
215
- )
165
+ def params_dict(self) -> Dict[str, Expression]:
166
+ return dict(zip(self.func_decl.param_names, self.params))
216
167
 
217
168
  @property
218
- def operands(self) -> Dict[str, "QuantumOperand"]:
219
- return self.positional_operands or self.designated_operands
169
+ def operands(self) -> List["QuantumOperand"]:
170
+ return [
171
+ param
172
+ for param in self.positional_args
173
+ if not isinstance(param, (Expression, HandleBinding))
174
+ ]
220
175
 
221
176
  @property
222
- def pos_port_args(self) -> Dict[str, HandleBinding]:
223
- return dict(
224
- zip(
225
- self.func_decl.port_declarations.keys(),
226
- (
227
- param
228
- for param in self.positional_args
229
- if isinstance(param, HandleBinding)
230
- ),
231
- )
232
- )
177
+ def ports(self) -> List[HandleBinding]:
178
+ return [
179
+ param for param in self.positional_args if isinstance(param, HandleBinding)
180
+ ]
181
+
182
+ def _get_handles_by_direction(
183
+ self, direction: PortDeclarationDirection
184
+ ) -> List[Tuple[int, AnonPortDeclaration, HandleBinding]]:
185
+ return [
186
+ (idx, port_decl, handle)
187
+ for idx, port_decl, handle in self._get_handles_with_declarations()
188
+ if direction == port_decl.direction
189
+ ]
233
190
 
234
191
  def _get_pos_port_args_by_direction(
235
192
  self, direction: PortDeclarationDirection
@@ -240,49 +197,35 @@ class QuantumFunctionCall(QuantumOperation):
240
197
  if self._func_decl is None:
241
198
  return dict()
242
199
  return {
243
- port_decl.name: port
244
- for port_decl, port in zip(
245
- self.func_decl.port_declarations.values(),
246
- (
247
- param
248
- for param in self.positional_args
249
- if isinstance(param, HandleBinding)
250
- ),
251
- )
200
+ port_decl.get_name(): handle
201
+ for _, port_decl, handle in self._get_handles_with_declarations()
252
202
  if direction == port_decl.direction
253
203
  }
254
204
 
255
- @property
256
- def inputs(self) -> Dict[str, HandleBinding]:
257
- return (
258
- self._get_pos_port_args_by_direction(PortDeclarationDirection.Input)
259
- or self.designated_inputs
260
- )
261
-
262
- @property
263
- def inouts(
205
+ def _get_handles_with_declarations(
264
206
  self,
265
- ) -> Dict[str, Union[SlicedHandleBinding, SubscriptHandleBinding, HandleBinding]]:
266
- return (
267
- self._get_pos_port_args_by_direction(PortDeclarationDirection.Inout)
268
- or self.designated_inouts
269
- )
207
+ ) -> Iterable[Tuple[int, AnonPortDeclaration, HandleBinding]]:
208
+ return [
209
+ (idx, port, handle)
210
+ for idx, (port, handle) in enumerate(
211
+ zip(
212
+ (port_decl for port_decl in self.func_decl.port_declarations),
213
+ (
214
+ param
215
+ for param in self.positional_args
216
+ if isinstance(param, HandleBinding)
217
+ ),
218
+ )
219
+ )
220
+ ]
270
221
 
271
- @property
272
- def outputs(self) -> Dict[str, HandleBinding]:
273
- return (
274
- self._get_pos_port_args_by_direction(PortDeclarationDirection.Output)
275
- or self.designated_outputs
222
+ def _get_readable_location(
223
+ self, param_index: int, param_decl: AnonPortDeclaration
224
+ ) -> str:
225
+ param_name = (
226
+ repr(param_decl.name) if param_decl.name is not None else f"#{param_index}"
276
227
  )
277
-
278
- @pydantic.root_validator()
279
- def validate_handles(cls, values: Dict[str, Any]) -> Dict[str, Any]:
280
- inputs = values.get("designated_inputs", dict())
281
- outputs = values.get("designated_outputs", dict())
282
- inouts = values.get("designated_inouts", dict())
283
-
284
- _validate_no_duplicated_ports(inputs, outputs, inouts)
285
- _validate_no_duplicated_handles(inputs, outputs, inouts)
286
- _validate_no_mixing_sliced_and_whole_handles(inouts)
287
-
288
- return values
228
+ param_text = (
229
+ f" for parameter {param_name}" if len(self.positional_args) > 1 else ""
230
+ )
231
+ return f"as an argument{param_text} of function {self.func_name!r}"