Best Python code snippet using fMBT_python
types.py
Source:types.py
1from concat.orderedset import OrderedSet2from concat.typecheck import (3 AttributeError,4 StackMismatchError,5 TypeError,6)7import concat.typecheck8from typing import (9 Optional,10 Dict,11 Iterable,12 Iterator,13 Sequence,14 Tuple,15 Union,16 List,17 Iterator,18 Set,19 Mapping,20 NoReturn,21 cast,22 overload,23 TYPE_CHECKING,24)25from typing_extensions import Literal26import abc27import collections.abc28import builtins29if TYPE_CHECKING:30 from concat.typecheck import Substitutions31class Type(abc.ABC):32 # TODO: Fully replace with <=.33 def is_subtype_of(self, supertype: 'Type') -> bool:34 return (35 supertype is self36 or isinstance(self, IndividualType)37 and supertype is object_type38 )39 def __le__(self, other: object) -> bool:40 if not isinstance(other, Type):41 return NotImplemented42 return self.is_subtype_of(other)43 def __eq__(self, other: object) -> bool:44 if self is other:45 return True46 if not isinstance(other, Type):47 return NotImplemented48 return self <= other and other <= self49 def get_type_of_attribute(self, name: str) -> 'IndividualType':50 raise AttributeError(self, name)51 def has_attribute(self, name: str) -> bool:52 try:53 self.get_type_of_attribute(name)54 return True55 except AttributeError:56 return False57 @abc.abstractproperty58 def attributes(self) -> Mapping[str, 'Type']:59 pass60 @abc.abstractmethod61 def free_type_variables(self) -> OrderedSet['_Variable']:62 pass63 @abc.abstractmethod64 def apply_substitution(65 self, _: 'concat.typecheck.Substitutions'66 ) -> Union['Type', Sequence['StackItemType']]:67 pass68 @abc.abstractmethod69 def constrain_and_bind_supertype_variables(70 self, supertype: 'Type', rigid_variables: Set['_Variable']71 ) -> 'Substitutions':72 pass73 @abc.abstractmethod74 def constrain_and_bind_subtype_variables(75 self, supertype: 'Type', rigid_variables: Set['_Variable']76 ) -> 'Substitutions':77 pass78 def constrain(self, supertype: 'Type') -> None:79 if not self.is_subtype_of(supertype):80 raise TypeError(81 '{} is not a subtype of {}'.format(self, supertype)82 )83 def instantiate(self) -> 'Type':84 return self85class IndividualType(Type, abc.ABC):86 def to_for_all(self) -> Type:87 return ForAll([], self)88 def __and__(self, other: object) -> 'IndividualType':89 raise NotImplementedError('take advantage of constraints instead')90 def is_subtype_of(self, supertype: Type) -> bool:91 if isinstance(supertype, _OptionalType):92 if (93 self == none_type94 or not supertype.type_arguments95 or isinstance(supertype.type_arguments[0], IndividualType)96 and self.is_subtype_of(supertype.type_arguments[0])97 ):98 return True99 return False100 return super().is_subtype_of(supertype)101class _Variable(Type, abc.ABC):102 """Objects that represent type variables.103 Every type variable object is assumed to be unique. Thus, fresh type104 variables can be made simply by creating new objects. They can also be105 compared by identity."""106 def apply_substitution(107 self, sub: 'concat.typecheck.Substitutions'108 ) -> Union[IndividualType, '_Variable', 'TypeSequence']:109 if self in sub:110 return sub[self] # type: ignore111 return self112 def free_type_variables(self) -> OrderedSet['_Variable']:113 return OrderedSet({self})114class IndividualVariable(_Variable, IndividualType):115 def __init__(self) -> None:116 super().__init__()117 def constrain_and_bind_supertype_variables(118 self, supertype: Type, rigid_variables: Set['_Variable']119 ) -> 'Substitutions':120 from concat.typecheck import Substitutions121 if self is supertype or supertype == object_type:122 return Substitutions()123 if not isinstance(supertype, IndividualType):124 raise TypeError(125 '{} must be an individual type: expected {}'.format(126 supertype, self127 )128 )129 if self in rigid_variables:130 raise TypeError(131 '{} is considered fixed here and cannot become a subtype of {}'.format(132 self, supertype133 )134 )135 if (136 isinstance(supertype, IndividualVariable)137 and supertype not in rigid_variables138 ):139 return Substitutions({supertype: self})140 # Let's not support bounded quantification or inferring the types of141 # named functions. Thus, the subtype constraint should fail here.142 raise TypeError(143 '{} is an individual type variable and cannot be a subtype of {}'.format(144 self, supertype145 )146 )147 def constrain_and_bind_subtype_variables(148 self, supertype: Type, rigid_variables: Set['_Variable']149 ) -> 'Substitutions':150 from concat.typecheck import Substitutions151 if self is supertype:152 return Substitutions()153 if supertype == object_type:154 return Substitutions({self: object_type})155 if not isinstance(supertype, IndividualType):156 raise TypeError(157 '{} must be an individual type: expected {}'.format(158 supertype, self159 )160 )161 if self in rigid_variables:162 raise TypeError(163 '{} is considered fixed here and cannot become a subtype of {}'.format(164 self, supertype165 )166 )167 return Substitutions({self: supertype})168 # __hash__ by object identity is used since that's the only way for two169 # type variables to be ==.170 def __hash__(self) -> int:171 return hash(id(self))172 def __str__(self) -> str:173 return '`t_{}'.format(id(self))174 def __repr__(self) -> str:175 return '<individual variable {}>'.format(id(self))176 def apply_substitution(177 self, sub: 'concat.typecheck.Substitutions'178 ) -> IndividualType:179 return cast(IndividualType, super().apply_substitution(sub))180 @property181 def attributes(self) -> NoReturn:182 raise TypeError(183 '{} is an individual type variable, so its attributes are unknown'.format(184 self185 )186 )187class SequenceVariable(_Variable):188 def __init__(self) -> None:189 super().__init__()190 def __str__(self) -> str:191 return '*t_{}'.format(id(self))192 def __hash__(self) -> int:193 return hash(id(self))194 def constrain_and_bind_supertype_variables(195 self, supertype: Type, rigid_variables: Set['_Variable']196 ) -> 'Substitutions':197 from concat.typecheck import Substitutions198 if not isinstance(supertype, (SequenceVariable, TypeSequence)):199 raise TypeError(200 '{} must be a sequence type, not {}'.format(self, supertype)201 )202 if self in rigid_variables:203 raise Exception('todo')204 # occurs check205 if self is not supertype and self in supertype.free_type_variables():206 raise TypeError(207 '{} cannot be a subtype of {} because it appears in {}'.format(208 self, supertype, supertype209 )210 )211 if isinstance(supertype, SequenceVariable):212 return Substitutions({supertype: self})213 return Substitutions()214 def constrain_and_bind_subtype_variables(215 self, supertype: Type, rigid_variables: Set['_Variable']216 ) -> 'Substitutions':217 from concat.typecheck import Substitutions218 if not isinstance(supertype, (SequenceVariable, TypeSequence)):219 raise TypeError(220 '{} must be a sequence type, not {}'.format(self, supertype)221 )222 if self in rigid_variables:223 raise TypeError(224 '{} is fixed here and cannot become a subtype of another type'.format(225 self226 )227 )228 # occurs check229 if self is not supertype and self in supertype.free_type_variables():230 raise TypeError(231 '{} cannot be a subtype of {} because it appears in {}'.format(232 self, supertype, supertype233 )234 )235 return Substitutions({self: supertype})236 def get_type_of_attribute(self, name: str) -> NoReturn:237 raise TypeError(238 'the sequence type {} does not hold attributes'.format(self)239 )240 @property241 def attributes(self) -> NoReturn:242 raise TypeError(243 'the sequence type {} does not hold attributes'.format(self)244 )245class TypeSequence(Type, Iterable['StackItemType']):246 def __init__(self, sequence: Sequence['StackItemType']) -> None:247 self._rest: Optional[SequenceVariable]248 if sequence and isinstance(sequence[0], SequenceVariable):249 self._rest = sequence[0]250 self._individual_types = sequence[1:]251 else:252 self._rest = None253 self._individual_types = sequence254 def as_sequence(self) -> Sequence['StackItemType']:255 if self._rest is not None:256 return [self._rest, *self._individual_types]257 return self._individual_types258 def apply_substitution(self, sub) -> 'TypeSequence':259 subbed_types: List[StackItemType] = []260 for type in self:261 subbed_type: Union[StackItemType, Sequence[StackItemType]] = sub(262 type263 )264 if isinstance(subbed_type, TypeSequence):265 subbed_types += [*subbed_type]266 else:267 subbed_types.append(subbed_type)268 return TypeSequence(subbed_types)269 def is_subtype_of(self, supertype: Type) -> bool:270 if (271 isinstance(supertype, SequenceVariable)272 and not self._individual_types273 and self._rest is supertype274 ):275 return True276 elif isinstance(supertype, TypeSequence):277 if self._is_empty() and supertype._is_empty():278 return True279 elif not self._individual_types:280 if (281 self._rest282 and supertype._rest283 and not supertype._individual_types284 ):285 return self._rest is supertype._rest286 else:287 return False288 elif self._individual_types and supertype._individual_types:289 if (290 not self._individual_types[-1]291 <= supertype._individual_types[-1]292 ):293 return False294 return self[:-1] <= supertype[:-1]295 else:296 return False297 else:298 raise TypeError(299 '{} must be a sequence type, not {}'.format(self, supertype)300 )301 def constrain_and_bind_supertype_variables(302 self, supertype: Type, rigid_variables: Set['_Variable']303 ) -> 'Substitutions':304 """Check that self is a subtype of supertype.305 Free type variables that appear in the supertype type sequence are set306 to be equal to their counterparts in the subtype sequence so that type307 information can be propagated into calls of named functions.308 """309 from concat.typecheck import Substitutions310 if (311 isinstance(supertype, SequenceVariable)312 and supertype not in rigid_variables313 ):314 return Substitutions({supertype: self})315 elif isinstance(supertype, TypeSequence):316 if self._is_empty() and supertype._is_empty():317 return Substitutions()318 elif (319 self._is_empty()320 and supertype._rest321 and not supertype._individual_types322 and supertype._rest not in rigid_variables323 ):324 return Substitutions({supertype._rest: self})325 elif (326 supertype._is_empty()327 and self._rest328 and not self._individual_types329 ):330 raise StackMismatchError(self, supertype)331 elif not self._individual_types:332 if (333 self._rest334 and supertype._rest335 and not supertype._individual_types336 and supertype._rest not in rigid_variables337 ):338 return Substitutions({supertype._rest: self._rest})339 elif self._is_empty() and supertype._is_empty():340 return Substitutions()341 elif (342 self._is_empty()343 and supertype._rest344 and not supertype._individual_types345 and supertype._rest not in rigid_variables346 ):347 return Substitutions({supertype._rest: self})348 else:349 raise StackMismatchError(self, supertype)350 elif (351 not supertype._individual_types352 and supertype._rest353 and supertype._rest not in self.free_type_variables()354 and supertype._rest not in rigid_variables355 ):356 return Substitutions({supertype._rest: self})357 elif self._individual_types and supertype._individual_types:358 sub = self._individual_types[359 -1360 ].constrain_and_bind_supertype_variables(361 supertype._individual_types[-1], rigid_variables362 )363 # constrain individual variables in the second sequence type to364 # be *equal* to the corresponding type in the first sequence365 # type.366 is_variable = isinstance(367 supertype._individual_types[-1], IndividualVariable368 )369 if (370 is_variable371 and supertype._individual_types[-1] not in rigid_variables372 ):373 sub = Substitutions(374 {375 supertype._individual_types[376 -1377 ]: self._individual_types[-1]378 }379 )(sub)380 try:381 sub = sub(382 self[:-1]383 ).constrain_and_bind_supertype_variables(384 sub(supertype[:-1]), rigid_variables385 )(386 sub387 )388 return sub389 except StackMismatchError:390 raise StackMismatchError(self, supertype)391 else:392 raise StackMismatchError(self, supertype)393 else:394 raise TypeError(395 '{} must be a sequence type, not {}'.format(self, supertype)396 )397 def constrain_and_bind_subtype_variables(398 self, supertype: Type, rigid_variables: Set['_Variable']399 ) -> 'Substitutions':400 from concat.typecheck import Substitutions401 if isinstance(supertype, SequenceVariable) and (402 not self._rest or self._individual_types403 ):404 raise StackMismatchError(self, TypeSequence([supertype]))405 elif isinstance(supertype, TypeSequence):406 if self._is_empty() and supertype._is_empty():407 return Substitutions()408 elif (409 self._is_empty()410 and supertype._rest411 and not supertype._individual_types412 and supertype._rest not in rigid_variables413 ):414 raise StackMismatchError(self, supertype)415 elif (416 supertype._is_empty()417 and self._rest418 and not self._individual_types419 and self._rest not in rigid_variables420 ):421 return Substitutions({self._rest: supertype})422 elif not self._individual_types:423 if (424 self._rest425 and self._rest not in rigid_variables426 and self._rest not in supertype.free_type_variables()427 ):428 return Substitutions({self._rest: supertype})429 elif self._is_empty() and supertype._is_empty():430 return Substitutions()431 elif (432 self._is_empty()433 and supertype._rest434 and not supertype._individual_types435 ):436 # QUESTION: Should this be allowed? I'm being defensive here.437 raise StackMismatchError(self, supertype)438 else:439 raise StackMismatchError(self, supertype)440 elif (441 not supertype._individual_types442 and supertype._rest443 and supertype._rest not in self.free_type_variables()444 and supertype._rest not in rigid_variables445 ):446 raise StackMismatchError(self, supertype)447 elif self._individual_types and supertype._individual_types:448 sub = self._individual_types[449 -1450 ].constrain_and_bind_subtype_variables(451 supertype._individual_types[-1], rigid_variables452 )453 is_variable = isinstance(454 self._individual_types[-1], IndividualVariable455 )456 if (457 is_variable458 and self._individual_types[-1] not in rigid_variables459 ):460 sub = Substitutions(461 {462 self._individual_types[463 -1464 ]: supertype._individual_types[-1]465 }466 )(sub)467 try:468 sub = sub(self[:-1]).constrain_and_bind_subtype_variables(469 sub(supertype[:-1]), rigid_variables470 )(sub)471 return sub472 except StackMismatchError:473 raise StackMismatchError(self, supertype)474 else:475 raise StackMismatchError(self, supertype)476 else:477 raise TypeError(478 '{} must be a sequence type, not {}'.format(self, supertype)479 )480 def free_type_variables(self) -> OrderedSet['_Variable']:481 ftv: OrderedSet[_Variable] = OrderedSet([])482 for t in self:483 ftv |= t.free_type_variables()484 return ftv485 @property486 def attributes(self) -> NoReturn:487 raise TypeError(488 'the sequence type {} does not hold attributes'.format(self)489 )490 def __bool__(self) -> bool:491 return not self._is_empty()492 def _is_empty(self) -> bool:493 return self._rest is None and not self._individual_types494 @overload495 def __getitem__(self, key: int) -> 'StackItemType':496 ...497 @overload498 def __getitem__(self, key: slice) -> 'TypeSequence':499 ...500 def __getitem__(501 self, key: Union[int, slice]502 ) -> Union['StackItemType', 'TypeSequence']:503 if isinstance(key, int):504 return self.as_sequence()[key]505 return TypeSequence(self.as_sequence()[key])506 def __str__(self) -> str:507 return '[' + ', '.join(str(t) for t in self) + ']'508 def __repr__(self) -> str:509 return 'TypeSequence([' + ', '.join(repr(t) for t in self) + '])'510 def __iter__(self) -> Iterator['StackItemType']:511 return iter(self.as_sequence())512 def __hash__(self) -> int:513 return hash(tuple(self.as_sequence()))514# TODO: Actually get rid of ForAll uses. This is a temporary measure since I515# don't want to do that work right now.516def ForAll(type_parameters: Sequence['_Variable'], type: Type) -> Type:517 return ObjectType(IndividualVariable(), type.attributes, type_parameters,)518# TODO: Rename to StackEffect at all use sites.519class _Function(IndividualType):520 def __init__(521 self,522 input: Iterable['StackItemType'],523 output: Iterable['StackItemType'],524 ) -> None:525 super().__init__()526 self.input = TypeSequence(tuple(input))527 self.output = TypeSequence(tuple(output))528 def __iter__(self) -> Iterator['TypeSequence']:529 return iter((self.input, self.output))530 def generalized_wrt(self, gamma: Dict[str, Type]) -> Type:531 return ObjectType(532 IndividualVariable(),533 {'__call__': self,},534 list(535 self.free_type_variables()536 - _free_type_variables_of_mapping(gamma)537 ),538 )539 def can_be_complete_program(self) -> bool:540 """Returns true iff the function type is a subtype of ( -- *out)."""541 out_var = SequenceVariable()542 return self.is_subtype_of(_Function([], [out_var]))543 def __hash__(self) -> int:544 # FIXME: Alpha equivalence545 return hash((self.input, self.output))546 def is_subtype_of(547 self,548 supertype: Type,549 _sub: Optional['concat.typecheck.Substitutions'] = None,550 ) -> bool:551 if super().is_subtype_of(supertype):552 return True553 if isinstance(supertype, _Function):554 if len(tuple(self.input)) != len(tuple(supertype.input)) or len(555 tuple(self.output)556 ) != len(tuple(supertype.output)):557 return False558 # Sequence variables are handled through renaming.559 if _sub is None:560 _sub = concat.typecheck.Substitutions()561 input_rename_result = self._rename_sequence_variable(562 tuple(self.input), tuple(supertype.input), _sub563 )564 output_rename_result = self._rename_sequence_variable(565 tuple(supertype.output), tuple(self.output), _sub566 )567 if not (input_rename_result and output_rename_result):568 return False569 # TODO: What about individual type variables. We should be careful570 # with renaming those, too.571 # input types are contravariant572 for type_from_self, type_from_supertype in zip(573 self.input, supertype.input574 ):575 type_from_self, type_from_supertype = (576 cast(StackItemType, _sub(type_from_self)),577 cast(StackItemType, _sub(type_from_supertype)),578 )579 if isinstance(type_from_supertype, _Function):580 if not type_from_supertype.is_subtype_of(581 type_from_self, _sub582 ):583 return False584 elif not type_from_supertype.is_subtype_of(type_from_self):585 return False586 # output types are covariant587 for type_from_self, type_from_supertype in zip(588 self.output, supertype.output589 ):590 type_from_self, type_from_supertype = (591 cast(StackItemType, _sub(type_from_self)),592 cast(StackItemType, _sub(type_from_supertype)),593 )594 if isinstance(type_from_self, _Function):595 if not type_from_self.is_subtype_of(596 type_from_supertype, _sub597 ):598 return False599 elif not type_from_self.is_subtype_of(type_from_supertype):600 return False601 return True602 return False603 def constrain_and_bind_supertype_variables(604 self, supertype: Type, rigid_variables: Set['_Variable']605 ) -> 'Substitutions':606 if not isinstance(supertype, StackEffect):607 raise TypeError(608 '{} is not a subtype of {}'.format(self, supertype)609 )610 # Remember that the input should be contravariant!611 # QUESTION: Constrain the supertype variables here during contravariance check?612 sub = supertype.input.constrain_and_bind_subtype_variables(613 self.input, rigid_variables614 )615 sub = sub(self.output).constrain_and_bind_supertype_variables(616 sub(supertype.output), rigid_variables617 )(sub)618 return sub619 def constrain_and_bind_subtype_variables(620 self, supertype: Type, rigid_variables: Set['_Variable']621 ) -> 'Substitutions':622 if not isinstance(supertype, StackEffect):623 raise TypeError(624 '{} is not a subtype of {}'.format(self, supertype)625 )626 # Remember that the input should be contravariant!627 # QUESTION: Constrain the supertype variables here during contravariance check?628 sub = supertype.input.constrain_and_bind_supertype_variables(629 self.input, rigid_variables630 )631 sub = sub(self.output).constrain_and_bind_subtype_variables(632 sub(supertype.output), rigid_variables633 )(sub)634 return sub635 def free_type_variables(self) -> OrderedSet['_Variable']:636 return (637 self.input.free_type_variables()638 | self.output.free_type_variables()639 )640 @staticmethod641 def _rename_sequence_variable(642 supertype_list: Sequence['StackItemType'],643 subtype_list: Sequence['StackItemType'],644 sub: 'concat.typecheck.Substitutions',645 ) -> bool:646 both_lists_nonempty = supertype_list and subtype_list647 if (648 both_lists_nonempty649 and isinstance(supertype_list[0], SequenceVariable)650 and isinstance(subtype_list[0], SequenceVariable)651 ):652 if supertype_list[0] not in sub:653 sub[supertype_list[0]] = subtype_list[0]654 else:655 if sub(supertype_list[0]) is not subtype_list[0]:656 return False657 return True658 def __repr__(self) -> str:659 return '{}({!r}, {!r})'.format(660 type(self).__qualname__, self.input, self.output661 )662 def __str__(self) -> str:663 in_types = ' '.join(map(str, self.input))664 out_types = ' '.join(map(str, self.output))665 return '({} -- {})'.format(in_types, out_types)666 def __and__(self, other: object) -> IndividualType:667 if isinstance(other, _Function):668 input = _intersect_sequences(tuple(self.input), tuple(other.input))669 output = _intersect_sequences(670 tuple(self.output), tuple(other.output)671 )672 return _Function(input, output)673 return super().__and__(other)674 def get_type_of_attribute(self, name: str) -> '_Function':675 if name == '__call__':676 return self677 raise AttributeError(self, name)678 @property679 def attributes(self) -> Mapping[str, 'StackEffect']:680 return {'__call__': self}681 def apply_substitution(682 self, sub: 'concat.typecheck.Substitutions'683 ) -> '_Function':684 return _Function(sub(self.input), sub(self.output))685 def bind(self) -> '_Function':686 return _Function(self.input[:-1], self.output)687class QuotationType(_Function):688 def __init__(self, fun_type: _Function) -> None:689 super().__init__(fun_type.input, fun_type.output)690 def is_subtype_of(691 self,692 supertype: Type,693 _sub: Optional['concat.typecheck.Substitutions'] = None,694 ) -> bool:695 if super().is_subtype_of(supertype, _sub):696 return True697 if supertype == iterable_type:698 return True699 return False700 def constrain_and_bind_supertype_variables(701 self, supertype: Type, rigid_variables: Set['_Variable']702 ) -> 'Substitutions':703 if (704 isinstance(supertype, ObjectType)705 and supertype.head == iterable_type706 ):707 # FIXME: Don't present new variables every time.708 # FIXME: Account for the types of the elements of the quotation.709 in_var = IndividualVariable()710 out_var = IndividualVariable()711 quotation_iterable_type = iterable_type[712 _Function([in_var], [out_var]),713 ]714 return quotation_iterable_type.constrain_and_bind_supertype_variables(715 supertype, rigid_variables716 )717 return super().constrain_and_bind_supertype_variables(718 supertype, rigid_variables719 )720 def constrain_and_bind_subtype_variables(721 self, supertype: Type, rigid_variables: Set['_Variable']722 ) -> 'Substitutions':723 if (724 isinstance(supertype, ObjectType)725 and supertype.head == iterable_type726 ):727 # FIXME: Don't present new variables every time.728 # FIXME: Account for the types of the elements of the quotation.729 in_var = IndividualVariable()730 out_var = IndividualVariable()731 quotation_iterable_type = iterable_type[732 _Function([in_var], [out_var]),733 ]734 return quotation_iterable_type.constrain_and_bind_subtype_variables(735 supertype, rigid_variables736 )737 return super().constrain_and_bind_subtype_variables(738 supertype, rigid_variables739 )740 def apply_substitution(741 self, sub: 'concat.typecheck.Substitutions'742 ) -> 'QuotationType':743 return QuotationType(super().apply_substitution(sub))744def _intersect_sequences(745 seq1: Sequence['StackItemType'], seq2: Sequence['StackItemType']746) -> Sequence['StackItemType']:747 raise NotImplementedError('stop using _IntersectionType')748# FIXME: This should be a method on types749def inst(sigma: _Function) -> IndividualType:750 """This is based on the inst function described by Kleffner."""751 if isinstance(sigma, _Function):752 input = [753 inst(type) if isinstance(type, _Function) else type754 for type in sigma.input755 ]756 output = [757 inst(type) if isinstance(type, _Function) else type758 for type in sigma.output759 ]760 return _Function(input, output)761 raise builtins.TypeError(type(sigma))762StackItemType = Union[SequenceVariable, IndividualType]763def _free_type_variables_of_mapping(764 attributes: Mapping[str, Type]765) -> OrderedSet[_Variable]:766 ftv: OrderedSet[_Variable] = OrderedSet([])767 for sigma in attributes.values():768 ftv |= sigma.free_type_variables()769 return ftv770def init_primitives():771 pass772TypeArguments = Sequence[Union[StackItemType, TypeSequence]]773class ObjectType(IndividualType):774 """The representation of types of objects, based on a gradual typing paper.775 That paper is "Design and Evaluation of Gradual Typing for Python"776 (Vitousek et al. 2014)."""777 def __init__(778 self,779 self_type: IndividualVariable,780 # Attributes can be universally quantified since ObjectType allows it.781 attributes: Dict[str, IndividualType],782 type_parameters: Sequence[_Variable] = (),783 nominal_supertypes: Sequence[IndividualType] = (),784 nominal: bool = False,785 _type_arguments: TypeArguments = (),786 _head: Optional['ObjectType'] = None,787 **_other_kwargs,788 ) -> None:789 # There should be no need to make the self_type variable unique because790 # it is treated as a bound variable in apply_substitution. In other791 # words, it is removed from any substitution received.792 self._self_type = self_type793 self._attributes = attributes794 self._type_parameters = type_parameters795 self._nominal_supertypes = nominal_supertypes796 self._nominal = nominal797 self._type_arguments: TypeArguments = _type_arguments798 self._head = _head or self799 self._internal_name: Optional[str] = None800 self._internal_name = self._head._internal_name801 self._other_kwargs = _other_kwargs.copy()802 if '_type_arguments' in self._other_kwargs:803 del self._other_kwargs['_type_arguments']804 if 'nominal' in self._other_kwargs:805 del self._other_kwargs['nominal']806 self._instantiations: Dict[TypeArguments, ObjectType] = {}807 def apply_substitution(808 self,809 sub: 'concat.typecheck.Substitutions',810 _should_quantify_over_type_parameters=True,811 ) -> 'ObjectType':812 from concat.typecheck import Substitutions813 if _should_quantify_over_type_parameters:814 sub = Substitutions(815 {816 a: i817 for a, i in sub.items()818 # Don't include self_type in substitution, it is bound.819 if a not in self._type_parameters820 and a is not self._self_type821 }822 )823 # if no free type vars will be substituted, just return self824 if not any(825 free_var in sub for free_var in self.free_type_variables()826 ):827 return self828 else:829 sub = Substitutions(830 {a: i for a, i in sub.items() if a is not self._self_type}831 )832 # if no free type vars will be substituted, just return self833 if not any(834 free_var in sub835 for free_var in {836 *self.free_type_variables(),837 *self._type_parameters,838 }839 ):840 return self841 attributes = cast(842 Dict[str, IndividualType],843 {attr: sub(t) for attr, t in self._attributes.items()},844 )845 nominal_supertypes = [846 sub(supertype) for supertype in self._nominal_supertypes847 ]848 type_arguments = [849 cast(Union[StackItemType, TypeSequence], sub(type_argument))850 for type_argument in self._type_arguments851 ]852 subbed_type = type(self)(853 self._self_type,854 attributes,855 type_parameters=self._type_parameters,856 nominal_supertypes=nominal_supertypes,857 nominal=self._nominal,858 _type_arguments=type_arguments,859 # head is only used to keep track of where a type came from, so860 # there's no need to substitute it861 _head=self._head,862 **self._other_kwargs,863 )864 if self._internal_name is not None:865 subbed_type.set_internal_name(self._internal_name)866 return subbed_type867 def is_subtype_of(self, supertype: 'Type') -> bool:868 from concat.typecheck import Substitutions869 if supertype in self._nominal_supertypes or self is supertype:870 return True871 if isinstance(supertype, (_Function, PythonFunctionType)):872 if '__call__' not in self._attributes:873 return False874 return self._attributes['__call__'] <= supertype875 if not isinstance(supertype, ObjectType):876 return super().is_subtype_of(supertype)877 if self._arity != supertype._arity:878 return False879 if self._arity == 0 and supertype is object_type:880 return True881 if supertype._nominal and self._head is not supertype._head:882 return False883 # instantiate these types in a way such that alpha equivalence is not884 # an issue885 # NOTE: I assume the parameters are in the same order, which is886 # fragile.887 parameter_pairs = zip(self.type_parameters, supertype.type_parameters)888 if not all(type(a) == type(b) for a, b in parameter_pairs):889 return False890 self = self.instantiate()891 supertype = supertype.instantiate()892 parameter_sub = Substitutions(893 {894 **dict(zip(self.type_arguments, supertype.type_arguments)),895 self.self_type: supertype.self_type,896 }897 )898 self = parameter_sub(self)899 for attr, attr_type in supertype._attributes.items():900 if attr not in self._attributes:901 return False902 sub = concat.typecheck.Substitutions(903 {self._self_type: supertype._self_type}904 )905 if not (906 cast(IndividualType, sub(self._attributes[attr])) <= attr_type907 ):908 return False909 return True910 def constrain_and_bind_supertype_variables(911 self, supertype: Type, rigid_variables: Set['_Variable']912 ) -> 'Substitutions':913 from concat.typecheck import Substitutions914 if (915 isinstance(supertype, IndividualVariable)916 and supertype not in rigid_variables917 ):918 return Substitutions({supertype: self})919 elif isinstance(supertype, (SequenceVariable, TypeSequence)):920 raise TypeError(921 '{} is an individual type, but {} is a sequence type'.format(922 self, supertype923 )924 )925 elif isinstance(supertype, StackEffect):926 if self._arity != 0:927 raise TypeError(928 'type constructor {} expected at least one argument and cannot be a stack effect (expected effect {})'.format(929 self, supertype930 )931 )932 # We know self is not a type constructor here, so there's no need933 # to worry about variable binding934 return self.get_type_of_attribute(935 '__call__'936 ).constrain_and_bind_supertype_variables(937 supertype, rigid_variables938 )939 elif not isinstance(supertype, ObjectType):940 raise NotImplementedError(supertype)941 if self._arity != supertype._arity:942 raise TypeError(943 '{} and {} do not have the same arity'.format(self, supertype)944 )945 # every object type with zero arity is a subtype of object_type946 if self._arity == 0 and supertype == object_type:947 return Substitutions()948 # Don't forget that there's nominal subtyping too.949 if supertype._nominal:950 if (951 supertype not in self._nominal_supertypes952 and supertype != self953 and self._head != supertype._head954 ):955 raise TypeError(956 '{} is not a subtype of {}'.format(self, supertype)957 )958 # constraining to an optional type959 if (960 supertype._head == optional_type961 and supertype._arity == 0962 and self._arity == 0963 ):964 try:965 return self.constrain_and_bind_supertype_variables(966 none_type, rigid_variables967 )968 except TypeError:969 return self.constrain_and_bind_supertype_variables(970 supertype._type_arguments[0], rigid_variables971 )972 # don't constrain the type arguments, constrain those based on973 # the attributes974 sub = Substitutions()975 for name in supertype._attributes:976 type = self.get_type_of_attribute(name)977 # We must not bind any type parameters in self or supertype!978 rigid_variables = (979 rigid_variables980 | set(self.type_parameters)981 | set(supertype.type_parameters)982 )983 sub = type.constrain_and_bind_supertype_variables(984 supertype.get_type_of_attribute(name), rigid_variables985 )(sub)986 return sub987 def constrain_and_bind_subtype_variables(988 self, supertype: Type, rigid_variables: Set['_Variable']989 ) -> 'Substitutions':990 from concat.typecheck import Substitutions991 if isinstance(supertype, IndividualVariable):992 raise TypeError(993 '{} is unknown here and cannot be a supertype of {}'.format(994 supertype, self995 )996 )997 elif isinstance(supertype, (SequenceVariable, TypeSequence)):998 raise TypeError(999 '{} is an individual type, but {} is a sequence type'.format(1000 self, supertype1001 )1002 )1003 elif isinstance(supertype, StackEffect):1004 if self._arity != 0:1005 raise TypeError(1006 'type constructor {} expected at least one argument and cannot be a stack effect (expected effect {})'.format(1007 self, supertype1008 )1009 )1010 # We know self is not a type constructor here, so there's no need1011 # to worry about variable binding1012 return self.get_type_of_attribute(1013 '__call__'1014 ).constrain_and_bind_subtype_variables(supertype, rigid_variables)1015 elif not isinstance(supertype, ObjectType):1016 raise NotImplementedError(supertype)1017 if self._arity != supertype._arity:1018 raise TypeError(1019 '{} and {} do not have the same arity'.format(self, supertype)1020 )1021 # every object type with zero arity is a subtype of object_type1022 if self._arity == 0 and supertype == object_type:1023 return Substitutions()1024 # Don't forget that there's nominal subtyping too.1025 if supertype._nominal:1026 if (1027 supertype not in self._nominal_supertypes1028 and supertype != self1029 and self._head != supertype._head1030 ):1031 raise TypeError(1032 '{} is not a subtype of {}'.format(self, supertype)1033 )1034 # constraining to an optional type1035 if (1036 supertype._head == optional_type1037 and supertype._arity == 01038 and self._arity == 01039 ):1040 try:1041 return self.constrain_and_bind_subtype_variables(1042 none_type, rigid_variables1043 )1044 except TypeError:1045 return self.constrain_and_bind_subtype_variables(1046 supertype._type_arguments[0], rigid_variables1047 )1048 # don't constrain the type arguments, constrain those based on1049 # the attributes1050 sub = Substitutions()1051 for name in supertype._attributes:1052 type = self.get_type_of_attribute(name)1053 # We must not bind any type parameters in self or supertype!1054 rigid_variables = (1055 rigid_variables1056 | set(self.type_parameters)1057 | set(supertype.type_parameters)1058 )1059 sub = type.constrain_and_bind_subtype_variables(1060 supertype.get_type_of_attribute(name), rigid_variables1061 )(sub)1062 return sub1063 def get_type_of_attribute(self, attribute: str) -> IndividualType:1064 if attribute not in self._attributes:1065 raise AttributeError(self, attribute)1066 self_sub = concat.typecheck.Substitutions({self._self_type: self})1067 return self_sub(self._attributes[attribute])1068 def __repr__(self) -> str:1069 return '{}({!r}, {!r}, {!r}, {!r}, {!r}, {!r}, {!r})'.format(1070 type(self).__qualname__,1071 self._self_type,1072 self._attributes,1073 self._type_parameters,1074 self._nominal_supertypes,1075 self._nominal,1076 self._type_arguments,1077 None if self._head is self else self._head,1078 )1079 def free_type_variables(self) -> OrderedSet[_Variable]:1080 ftv = _free_type_variables_of_mapping(self.attributes)1081 for arg in self.type_arguments:1082 ftv |= arg.free_type_variables()1083 # QUESTION: Include supertypes?1084 ftv -= {self.self_type, *self.type_parameters}1085 return ftv1086 def __str__(self) -> str:1087 if self._internal_name is not None:1088 if len(self._type_arguments) > 0:1089 return (1090 self._internal_name1091 + '['1092 + ', '.join(map(str, self._type_arguments))1093 + ']'1094 )1095 return self._internal_name1096 assert self._internal_name is None1097 return '{}({}, {}, {}, {}, {}, {}, {})'.format(1098 type(self).__qualname__,1099 self._self_type,1100 _mapping_to_str(self._attributes),1101 _iterable_to_str(self._type_parameters),1102 _iterable_to_str(self._nominal_supertypes),1103 self._nominal,1104 _iterable_to_str(self._type_arguments),1105 None if self._head is self else self._head,1106 )1107 def set_internal_name(self, name: str) -> None:1108 self._internal_name = name1109 _hash_variable = None1110 def __hash__(self) -> int:1111 from concat.typecheck import Substitutions1112 if ObjectType._hash_variable is None:1113 ObjectType._hash_variable = IndividualVariable()1114 sub = Substitutions({self._self_type: ObjectType._hash_variable})1115 type_to_hash = sub(self)1116 return hash(1117 (1118 tuple(type_to_hash._attributes.items()),1119 tuple(type_to_hash._type_parameters),1120 tuple(type_to_hash._nominal_supertypes),1121 type_to_hash._nominal,1122 # FIXME: I get 'not hashable' errors about this.1123 # tuple(type_to_hash._type_arguments),1124 None if type_to_hash._head == self else type_to_hash._head,1125 )1126 )1127 def __getitem__(1128 self, type_arguments: Sequence[StackItemType]1129 ) -> 'ObjectType':1130 from concat.typecheck import Substitutions1131 if self._arity != len(type_arguments):1132 raise TypeError(1133 'type constructor {} given {} arguments, expected {} arguments'.format(1134 self, len(type_arguments), self._arity1135 )1136 )1137 type_arguments = tuple(type_arguments)1138 if type_arguments in self._instantiations:1139 return self._instantiations[type_arguments]1140 sub = Substitutions(zip(self._type_parameters, type_arguments))1141 result = self.apply_substitution(1142 sub, _should_quantify_over_type_parameters=False1143 )1144 # HACK: We remove the parameters and add arguments through mutation.1145 result._type_parameters = ()1146 result._type_arguments = type_arguments1147 self._instantiations[type_arguments] = result1148 return result1149 def instantiate(self) -> 'ObjectType':1150 # Avoid overwriting the type arguments if type is already instantiated.1151 if self._arity == 0:1152 return self1153 fresh_variables = [type(a)() for a in self._type_parameters]1154 return self[fresh_variables]1155 @property1156 def attributes(self) -> Dict[str, IndividualType]:1157 return self._attributes1158 @property1159 def self_type(self) -> IndividualVariable:1160 return self._self_type1161 @property1162 def type_arguments(self) -> TypeArguments:1163 return self._type_arguments1164 @property1165 def head(self) -> 'ObjectType':1166 return self._head1167 @property1168 def type_parameters(self) -> Sequence[_Variable]:1169 return self._type_parameters1170 @property1171 def nominal_supertypes(self) -> Sequence[IndividualType]:1172 return self._nominal_supertypes1173 @property1174 def _arity(self) -> int:1175 return len(self._type_parameters)1176class ClassType(ObjectType):1177 """The representation of types of classes, like in "Design and Evaluation of Gradual Typing for Python" (Vitousek et al. 2014)."""1178 def is_subtype_of(self, supertype: Type) -> bool:1179 if (1180 not supertype.has_attribute('__call__')1181 or '__init__' not in self._attributes1182 ):1183 return super().is_subtype_of(supertype)1184 bound_init = self._attributes['__init__'].bind()1185 return bound_init <= supertype1186class PythonFunctionType(ObjectType):1187 def __init__(1188 self,1189 self_type: IndividualVariable,1190 *args,1191 _overloads: Sequence[1192 Tuple[Sequence[StackItemType], IndividualType]1193 ] = (),1194 type_parameters=(),1195 **kwargs,1196 ) -> None:1197 self._kwargs = kwargs.copy()1198 # HACK: I shouldn't have to manipulate arguments like this1199 if 'type_parameters' in self._kwargs:1200 del self._kwargs['type_parameters']1201 super().__init__(1202 self_type,1203 *args,1204 **self._kwargs,1205 _overloads=_overloads,1206 type_parameters=type_parameters,1207 )1208 assert (1209 self._arity == 01210 and len(self._type_arguments) == 21211 or self._arity == 21212 and len(self._type_arguments) == 01213 )1214 if self._arity == 0:1215 assert isinstance(self.input, collections.abc.Sequence)1216 self._args = list(args)1217 self._overloads = _overloads1218 if '_head' in self._kwargs:1219 del self._kwargs['_head']1220 self._head: PythonFunctionType1221 def __str__(self) -> str:1222 if not self._type_arguments:1223 return 'py_function_type'1224 return 'py_function_type[{}, {}]'.format(1225 _iterable_to_str(self.input), self.output1226 )1227 def get_type_of_attribute(self, attribute: str) -> IndividualType:1228 from concat.typecheck import Substitutions1229 sub = Substitutions({self._self_type: self})1230 if attribute == '__call__':1231 return self1232 else:1233 return super().get_type_of_attribute(attribute)1234 def __getitem__(1235 self, arguments: Tuple[TypeSequence, IndividualType]1236 ) -> 'PythonFunctionType':1237 assert self._arity == 21238 input = arguments[0]1239 output = arguments[1]1240 return PythonFunctionType(1241 self._self_type,1242 *self._args,1243 **{1244 **self._kwargs,1245 '_type_arguments': (input, output),1246 'type_parameters': (),1247 },1248 _overloads=[],1249 _head=self,1250 )1251 def apply_substitution(1252 self, sub: 'concat.typecheck.Substitutions'1253 ) -> 'PythonFunctionType':1254 if self._arity == 0:1255 type = py_function_type[1256 sub(TypeSequence(self.input)), sub(self.output)1257 ]1258 for overload in self._overloads:1259 # This is one of the few places where a type should be mutated.1260 type._add_overload(1261 [sub(i) for i in overload[0]], sub(overload[1])1262 )1263 return type1264 return self1265 @property1266 def input(self) -> Sequence[StackItemType]:1267 assert self._arity == 01268 if isinstance(self._type_arguments[0], SequenceVariable):1269 return (self._type_arguments[0],)1270 assert not isinstance(self._type_arguments[0], IndividualType)1271 return tuple(self._type_arguments[0])1272 @property1273 def output(self) -> IndividualType:1274 assert self._arity == 01275 assert isinstance(self._type_arguments[1], IndividualType)1276 return self._type_arguments[1]1277 def select_overload(1278 self, input_types: Sequence[StackItemType]1279 ) -> Tuple['PythonFunctionType', 'Substitutions']:1280 for overload in [(self.input, self.output), *self._overloads]:1281 try:1282 sub = TypeSequence(1283 input_types1284 ).constrain_and_bind_supertype_variables(1285 TypeSequence(overload[0]), set()1286 )1287 except TypeError:1288 continue1289 return (1290 sub(py_function_type[TypeSequence(overload[0]), overload[1]]),1291 sub,1292 )1293 raise TypeError(1294 'no overload of {} matches types {}'.format(self, input_types)1295 )1296 def with_overload(1297 self, input: Sequence[StackItemType], output: IndividualType1298 ) -> 'PythonFunctionType':1299 return PythonFunctionType(1300 self._self_type,1301 *self._args,1302 **self._kwargs,1303 _overloads=[*self._overloads, (input, output)],1304 _head=py_function_type,1305 )1306 def _add_overload(1307 self, input: Sequence[StackItemType], output: IndividualType1308 ) -> None:1309 self._overloads.append((input, output))1310 def bind(self) -> 'PythonFunctionType':1311 assert self._arity == 01312 inputs = self.input[1:]1313 output = self.output1314 return self._head[TypeSequence(inputs), output]1315 def is_subtype_of(self, supertype: Type) -> bool:1316 if isinstance(supertype, PythonFunctionType):1317 # NOTE: make sure types are of same kind (arity)1318 if len(self._type_parameters) != len(supertype._type_parameters):1319 return False1320 if len(self._type_parameters) == 2:1321 # both are py_function_type1322 return True1323 assert isinstance(supertype._type_arguments[0], TypeSequence)1324 assert isinstance(self._type_arguments[1], IndividualType)1325 return (1326 supertype._type_arguments[0] <= self._type_arguments[0]1327 and self._type_arguments[1] <= supertype._type_arguments[1]1328 )1329 else:1330 return super().is_subtype_of(supertype)1331class _NoReturnType(ObjectType):1332 def __init__(self) -> None:1333 x = IndividualVariable()1334 super().__init__(x, {})1335 def is_subtype_of(self, _: Type) -> Literal[True]:1336 return True1337 def apply_substitution(1338 self, sub: 'concat.typecheck.Substitutions'1339 ) -> '_NoReturnType':1340 return self1341 def __repr__(self) -> str:1342 return '{}()'.format(type(self).__qualname__)1343class _OptionalType(ObjectType):1344 def __init__(self, _type_arguments=[]) -> None:1345 x = IndividualVariable()1346 type_var = IndividualVariable()1347 if len(_type_arguments) > 0:1348 super().__init__(x, {}, [], _type_arguments=_type_arguments)1349 else:1350 super().__init__(x, {}, [type_var])1351 def __getitem__(1352 self, type_arguments: Sequence[StackItemType]1353 ) -> '_OptionalType':1354 assert len(type_arguments) == 11355 return _OptionalType(type_arguments)1356 # def constrain(self, supertype, )1357 def apply_substitution(1358 self, sub: 'concat.typecheck.Substitutions'1359 ) -> '_OptionalType':1360 return _OptionalType(tuple(sub(TypeSequence(self._type_arguments))))1361def _iterable_to_str(iterable: Iterable) -> str:1362 return '[' + ', '.join(map(str, iterable)) + ']'1363def _mapping_to_str(mapping: Mapping) -> str:1364 return (1365 '{'1366 + ', '.join(1367 '{}: {}'.format(key, value) for key, value in mapping.items()1368 )1369 + '}'1370 )1371# expose _Function as StackEffect1372StackEffect = _Function1373_x = IndividualVariable()1374float_type = ObjectType(_x, {}, nominal=True)1375no_return_type = _NoReturnType()1376object_type = ObjectType(_x, {}, nominal=True)1377object_type.set_internal_name('object_type')1378_arg_type_var = SequenceVariable()1379_return_type_var = IndividualVariable()1380py_function_type = PythonFunctionType(1381 _x, {}, type_parameters=[_arg_type_var, _return_type_var]1382)1383py_function_type.set_internal_name('py_function_type')1384_invert_result_var = IndividualVariable()1385invertible_type = ObjectType(1386 _x,1387 {'__invert__': py_function_type[TypeSequence([]), _invert_result_var]},1388 [_invert_result_var],1389)1390_sub_operand_type = IndividualVariable()1391_sub_result_type = IndividualVariable()1392# FIXME: Add reverse_substractable_type for __rsub__1393subtractable_type = ObjectType(1394 _x,1395 {1396 '__sub__': py_function_type[1397 TypeSequence([_sub_operand_type]), _sub_result_type1398 ]1399 },1400 [_sub_operand_type, _sub_result_type],1401)1402bool_type = ObjectType(_x, {}, nominal=True)1403bool_type.set_internal_name('bool_type')1404_int_add_type = py_function_type[TypeSequence([object_type]), _x]1405int_type = ObjectType(1406 _x,1407 {1408 '__add__': _int_add_type,1409 '__invert__': py_function_type[TypeSequence([]), _x],1410 '__sub__': _int_add_type,1411 '__invert__': py_function_type[TypeSequence([]), _x],1412 '__le__': py_function_type[TypeSequence([_x]), bool_type],1413 },1414 nominal=True,1415)1416int_type.set_internal_name('int_type')1417# FIXME: Use an iterator interface instead of _x1418_result_type = IndividualVariable()1419iterable_type = ObjectType(1420 _x, {'__iter__': py_function_type[TypeSequence([]), _x]}, [_result_type]1421)1422iterable_type.set_internal_name('iterable_type')1423context_manager_type = ObjectType(1424 _x,1425 {1426 # TODO: Add argument and return types. I think I'll need a special1427 # py_function representation for that.1428 '__enter__': py_function_type,1429 '__exit__': py_function_type,1430 },1431)1432context_manager_type.set_internal_name('context_manager_type')1433optional_type = _OptionalType()1434optional_type.set_internal_name('optional_type')1435none_type = ObjectType(_x, {})1436none_type.set_internal_name('none_type')1437dict_type = ObjectType(1438 _x, {'__iter__': py_function_type[TypeSequence([]), object_type]}1439)1440dict_type.set_internal_name('dict_type')1441file_type = ObjectType(1442 _x,1443 {1444 'seek': py_function_type[TypeSequence([int_type]), int_type],1445 'read': py_function_type,1446 '__enter__': py_function_type,1447 '__exit__': py_function_type,1448 },1449 [],1450 # context_manager_type is a structural supertype1451 [iterable_type],1452 nominal=True,1453)1454file_type.set_internal_name('file_type')1455_start_type_var, _stop_type_var, _step_type_var = (1456 IndividualVariable(),1457 IndividualVariable(),1458 IndividualVariable(),1459)1460slice_type = ObjectType(1461 _x, {}, [_start_type_var, _stop_type_var, _step_type_var], nominal=True1462)1463slice_type.set_internal_name('slice_type')1464_element_type_var = IndividualVariable()1465_list_getitem_type = py_function_type[1466 TypeSequence([int_type]), _element_type_var1467].with_overload((slice_type[(optional_type[int_type,],) * 3],), _x)1468list_type = ObjectType(1469 _x,1470 {1471 '__getitem__': _list_getitem_type,1472 # FIXME: __iter__ should return an iterator.1473 '__iter__': py_function_type[TypeSequence([]), object_type],1474 },1475 [_element_type_var],1476 nominal=True,1477)1478list_type.set_internal_name('list_type')1479_str_getitem_type = py_function_type[1480 TypeSequence([int_type]), _x1481].with_overload(1482 [1483 slice_type[1484 optional_type[int_type,],1485 optional_type[int_type,],1486 optional_type[int_type,],1487 ]1488 ],1489 _x,1490)1491str_type = ObjectType(1492 _x,1493 {1494 '__getitem__': _str_getitem_type,1495 '__add__': py_function_type[TypeSequence([object_type]), _x],1496 'find': py_function_type[1497 TypeSequence(1498 [_x, optional_type[int_type,], optional_type[int_type,]]1499 ),1500 int_type,1501 ],1502 },1503 nominal=True,1504)1505str_type.set_internal_name('str_type')1506ellipsis_type = ObjectType(_x, {})1507not_implemented_type = ObjectType(_x, {})1508tuple_type = ObjectType(1509 _x,1510 {'__getitem__': py_function_type}1511 # iterable_type is a structural supertype1512)1513tuple_type.set_internal_name('tuple_type')1514base_exception_type = ObjectType(_x, {})1515module_type = ObjectType(_x, {})1516_index_type_var = IndividualVariable()1517_result_type_var = IndividualVariable()1518subscriptable_type = ObjectType(1519 IndividualVariable(),1520 {1521 '__getitem__': py_function_type[1522 TypeSequence([_index_type_var]), _result_type_var1523 ],1524 },1525 [_index_type_var, _result_type_var],...
Sequence.py
Source:Sequence.py
1class Sequence(object):2 def __init__(self):3 self.IdSpeaker = ''4 self.IdSession = ''5 self.device = ''6 self.typeSequence = ''7 #self.digits = '';8 self.digitsById = []910 def __init__(self, speakerId, sessionId,device, typeSequence,digitsByID):11 self.IdSpeaker = speakerId12 self.IdSession = sessionId13 self.device = device14 self.typeSequence = typeSequence15 #self.digits = digits;16 self.digitsById = digitsByID171819if __name__ == "__main__":
...
__init__.py
Source:__init__.py
1from ._family import TypeFamily2from .mapping import TypeMapping3from .sequence import TypeSequence4__all__ = [5 "TypeFamily",6 "TypeSequence",7 "TypeMapping",...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!