Форум сайта python.su
родитель:
class KspVar(KspObject): '''Abstract base class for every object can behave like variable: int, string or real(float) variables and arrays of KSP abstract methods required: @abstractmethod def _get_compiled(self) @abstractmethod def _set_runtime(self, val) @abstractmethod def _get_runtime(self) # can be used via super().val() @property @abstractmethod def val(self): if self.is_compiled(): return self._get_compiled() return self._get_runtime() also has property for getting and setting value as defaul value handler of instantiation via kwarg "value": _value Strongly reommended to assign kwarg "ref_type". In other case KspVar will be used as ref_type. ''' def __init__(self, name, value=None, ref_type=None, name_prefix='', name_postfix='', preserve_name=False, has_init=True, is_local=False, persist=False): super().__init__(name, name_prefix=name_prefix, name_postfix=name_postfix, preserve_name=preserve_name, has_init=has_init, is_local=is_local, has_executable=False) if ref_type: if not isinstance(ref_type, tuple): raise TypeError('ref_type has to be tuple of classes') for item in ref_type: if not isinstance(item, type): raise TypeError('ref_type has to be tuple' + ' of classes') self._ref_type = ref_type else: self._ref_type = self.__class__ if value is not None: self.__value = self._get_rutime_other(value) else: self.__value = [] self._persistent = persist self._read = False def _check_val_type(self, val): '''check if val is instance of ref_type. expands val if it is instance of KspVar returns val ''' if not isinstance(val, self.ref_type): raise TypeError(f'has to be one of: {self.ref_type}.' + f'val ({val}) is of type({type(val)})') if isinstance(val, KspVar): val = val.val return val def read(self): '''calls KSP function read_persistent_var() and adds make_persistent() function call at declaration if not any ''' if not self.in_init(): raise RuntimeError('can not be outside init') if self.is_local: raise RuntimeError('is local var') if self._read: warn('read has been called yet', category=Warning, stacklevel=2) Output().put(f'read_persistent_var({self.name()})') self._read = True @property def ref_type(self): '''getter. returns tuple of types''' return self._ref_type def _set_compiled(self, val): '''Puts AstAssign to Output() calls self._set_runtime with "val" rutime val ''' self._set_runtime(self._get_rutime_other(val)) Output().put(AstAssign(self, val).expand()) def _get_rutime_other(self, other): '''returns runtime representation of KspVar and AstBase or just passed value''' if not isinstance(other, self.ref_type): raise TypeError(f'has to be one of: {self.ref_type}.' + f'other is of type({type(other)})') if hasattr(other, 'get_value'): return other.get_value() if hasattr(other, '_get_runtime'): return other._get_runtime() return other @abstractmethod def _get_compiled(self): pass @abstractmethod def _set_runtime(self, val): pass @abstractmethod def _get_runtime(self): pass def __ilshift__(self, other): '''under compilation calls self._set_compiled otherwise calls self._set_runtime returns self''' self._check_val_type(other) if self.is_compiled(): self._set_compiled(other) return self self._set_runtime(other) return self def __rlshift__(self, other): '''under compilation calls self._get_compiled otherwise calls self._get_runtime ''' if self.is_compiled(): return self._get_compiled() return self._get_runtime() @property def val(self): '''under compilation calls self._get_compiled otherwise calls self._get_runtime ''' if self.is_compiled(): return self._get_compiled() return self._get_runtime() @property def _value(self): '''returns value passed in __init__ as "value" parameter''' return self.__value @_value.setter def _value(self, val): '''sets the value could be taken from _value property''' self._check_val_type(val) val = self._get_rutime_other(val) self.__value = val
class KspNumeric(KspVar): '''abstract base class for int and real KSP variables has to keep class variable "warning_types", consists tuple of classes for blocking magic methods. For example: warning_types = (KspIntVar, str, KspStrVar) ''' warning_types = None _warning_types_exc_str =\ "class var warning_types has to consist tuple of " +\ 'classes to warn within operations' # @classmethod # def warning_types(cls): # return cls.warning_types class TypeWarn(Warning): '''raised when type convertion is needed''' def __init__(self, val): super().__init__( f'Value {val} (type{type(val)}) ' + 'has to be converted within built-in func') def __new__(cls, *args, **kwargs): '''checks correct assignement of cls.warning_types''' if cls.warning_types is None: raise TypeError(cls._warning_types_exc_str) if not isinstance(cls.warning_types, tuple): raise TypeError(cls._warning_types_exc_str) for item in cls.warning_types: if not isinstance(item, type): raise TypeError(cls._warning_types_exc_str) obj = super().__new__(cls) # obj.__init__(*args, **kwargs) return obj def _generate_executable(self): raise NotImplementedError('has not to be called') def _warn_other(self, value): if isinstance(value, self.warning_types): raise self.TypeWarn(value) @abstractmethod def __truediv__(self, other): pass @abstractmethod def __rtruediv__(self, other): pass @abstractmethod def __itruediv__(self, other): pass @abstractmethod def __floordiv__(self, other): raise ArithmeticError('use regular / instead') @abstractmethod def __rfloordiv__(self, other): raise ArithmeticError('use regular / instead') @abstractmethod def __ifloordiv__(self, other): raise ArithmeticError('use regular / instead') def _expand_other(self, other): '''returns other, expanded via val property if is instance of KspVar''' if isinstance(other, self.warning_types): raise self.TypeWarn(other) if not isinstance(other, self.ref_type): raise TypeError(f'has to be one of {self.ref_type}') if isinstance(other, (int, str, float)): return other return other.val def __neg__(self): if self.is_compiled(): return AstNeg(self) return -self._get_runtime() def __invert__(self): if self.is_compiled(): return AstNot(self) return ~self._get_runtime() def __add__(self, other): self._warn_other(other) if self.is_compiled(): return AstAdd(self, other) other = self._get_runtime_other(other) return self._get_runtime() + other def __radd__(self, other): self._warn_other(other) if self.is_compiled(): return AstAdd(other, self) other = self._get_runtime_other(other) return self._get_runtime() + other def __iadd__(self, other): self._warn_other(other) if self.is_compiled(): self._set_compiled(AstAdd(self, other)) return self other = self._get_runtime_other(other) self._set_runtime(self._get_runtime() + other) return self def __sub__(self, other): self._warn_other(other) if self.is_compiled(): return AstSub(self, other) other = self._get_runtime_other(other) return self._get_runtime() - other def __rsub__(self, other): self._warn_other(other) if self.is_compiled(): return AstSub(other, self) other = self._get_runtime_other(other) return self._get_runtime() - other def __isub__(self, other): self._warn_other(other) if self.is_compiled(): self._set_compiled(AstSub(self, other)) return self other = self._get_runtime_other(other) self._set_runtime(self._get_runtime() - other) return self def __mul__(self, other): self._warn_other(other) if self.is_compiled(): return AstMul(self, other) other = self._get_runtime_other(other) return self._get_runtime() * other def __rmul__(self, other): self._warn_other(other) if self.is_compiled(): return AstMul(other, self) other = self._get_runtime_other(other) return self._get_runtime() * other def __imul__(self, other): self._warn_other(other) if self.is_compiled(): self._set_compiled(AstMul(self, other)) return self other = self._get_runtime_other(other) self._set_runtime(self._get_runtime() * other) return self def __and__(self, other): if self.is_compiled(): if self.is_bool(): return AstLogAnd(self, other) return AstBinAnd(self, other) other = self._get_runtime_other(other) if self.is_bool(): return self._get_runtime() and other return self._get_runtime() & other def __rand__(self, other): if self.is_compiled(): if self.is_bool(): return AstLogAnd(other, self) return AstBinAnd(other, self) other = self._get_runtime_other(other) if self.is_bool(): return self._get_runtime() and other return self._get_runtime() & other def __iand__(self, other): raise NotImplementedError def __or__(self, other): if self.is_compiled(): if self.is_bool(): return AstLogOr(self, other) return AstBinOr(self, other) other = self._get_runtime_other(other) if self.is_bool(): return self._get_runtime() or other return self._get_runtime() | other def __ror__(self, other): if self.is_compiled(): if self.is_bool(): return AstLogOr(other, self) return AstBinOr(other, self) other = self._get_runtime_other(other) if self.is_bool(): return self._get_runtime() or other return self._get_runtime() | other def __ior__(self, other): raise NotImplementedError def __eq__(self, other): if self.is_compiled(): return AstEq(self, other) other = self._get_runtime_other(other) return self._get_runtime() == other def __ne__(self, other): if self.is_compiled(): return AstNe(self, other) other = self._get_runtime_other(other) return self._get_runtime() != other def __lt__(self, other): if self.is_compiled(): return AstLt(self, other) other = self._get_runtime_other(other) return self._get_runtime() < other def __gt__(self, other): if self.is_compiled(): return AstGt(self, other) other = self._get_runtime_other(other) return self._get_runtime() > other def __le__(self, other): if self.is_compiled(): return AstLe(self, other) other = self._get_runtime_other(other) return self._get_runtime() <= other def __ge__(self, other): if self.is_compiled(): return AstGe(self, other) other = self._get_runtime_other(other) return self._get_runtime() >= other
Traceback (most recent call last): File "E:\packages\pyksp\pyksp\compiler\tests\test_base_types.py", line 678, in test_real self.assertEqual(x + 1.0, 2) File "E:\packages\pyksp\pyksp\compiler\tests/..\base_types.py", line 838, in __add__ other = self._get_runtime_other(other) AttributeError: 'TestRealVar' object has no attribute '_get_runtime_other'
Офлайн