Module digint.userint
userint
Holds the UserInt
and ExtendedUserInt
classes.
Classes
class ExtendedUserInt (x: int)
-
A class the extends
UserInt
, adding some basic quality of life attributes.Expand source code
class ExtendedUserInt(UserInt): """ `ExtendedUserInt` A class the extends `UserInt`, adding some basic quality of life attributes. """ def __init__(self, x:int): super().__init__(x) self.__x:int = x self.__high:Optional[int] = None self.__low:Optional[int] = None self.on_changed:Optional[Callable[['ExtendedUserInt', int], Any]] = None """ `on_changed` The `Callable` call back to be called **after** the `x` property is set, providing a reference to the current instance after the change is applied, and the `int` value `x` was previous to the change. When set to `None` (as by default), no callback will be triggered. """ @property def x(self) -> int: """ `x` The explicit value of the intiger. """ return self.__x @x.setter def x(self, value:int): if self.limit_low is not None: value = max(value, self.limit_low) if self.limit_high is not None: value = min(value, self.limit_high) old = self.__x self.__x = value if callable(self.on_changed): self.on_changed(self, old) # pylint:disable=not-callable @property def limit_high(self) -> Optional[int]: """ limit_high The high limit for the value of `x`, if any. `None` means there is no limit. Raises `ValueError` when the high limit is lower than the low limit, if both are not `None`. """ return self.__high @limit_high.setter def limit_high(self, value:Optional[int]): if value is not None and self.limit_low is not None and self.limit_low > value: raise ValueError("A high limit must not be less than the low limit") self.__high = value if self.__high is not None and self.x > self.__high: self.x = self.__high @property def limit_low(self) -> Optional[int]: """ limit_low The low limit for the value of `x`, if any. `None` means there is no limit. Raises `ValueError` when the low limit is higher than the high limit, if both are not `None`. """ return self.__low @limit_low.setter def limit_low(self, value:Optional[int]): if value is not None and self.limit_high is not None and self.limit_high < value: raise ValueError("A low limit must not be greater than the high limit") self.__low = value if self.__low is not None and self.x > self.__low: self.x = self.__low @property def sign(self) -> int: """ `sign` `-1` if `x` is negative, `1` if `x` is positive, `0` if `x` is `0`. """ return 0 if self.x == 0 else (1 if self.x > 0 else -1) @sign.setter def sign(self, value:int): value = max(min(value, 1), -1) if value == 0: self.x = 0 elif self.sign != value: self.x *= -1 def fixed_sign_invert(self) -> int: """ `fixed_sign_invert` Returns: The absolute value of this intiger, inverted, with its sign restored after. If this intiger is 0, the value returned is `~0` (`0` inverted), not `0`. """ return (~abs(self.x)) * (-1 if self.x < 0 else 1) def fixed_sign_and(self, value:int) -> int: """ `fixed_sign_and` Returns: The absolute value of this intiger, and-ed with the given `value`, with its sign restored after. """ return (abs(self.x) & value) * (-1 if self.x < 0 else 1) def fixed_sign_or(self, value:int) -> int: """ `fixed_sign_or` Returns: The absolute value of this intiger, or-ed with the given `value`, with its sign restored after. """ return (abs(self.x) | value) * (-1 if self.x < 0 else 1) def fixed_sign_xor(self, value:int) -> int: """ `fixed_sign_xor` Returns: The absolute value of this intiger, xor-ed with the given `value`, with its sign restored after. """ return (abs(self.x) ^ value) * (-1 if self.x < 0 else 1)
Ancestors
- UserInt
- typing.SupportsInt
- typing.SupportsFloat
- typing.SupportsAbs
- typing.SupportsComplex
- typing.SupportsRound
- typing.SupportsIndex
- typing.Protocol
- typing.Generic
- collections.abc.Hashable
Subclasses
Instance variables
prop limit_high : Optional[int]
-
limit_high
The high limit for the value of
x
, if any.None
means there is no limit. RaisesValueError
when the high limit is lower than the low limit, if both are notNone
.Expand source code
@property def limit_high(self) -> Optional[int]: """ limit_high The high limit for the value of `x`, if any. `None` means there is no limit. Raises `ValueError` when the high limit is lower than the low limit, if both are not `None`. """ return self.__high
prop limit_low : Optional[int]
-
limit_low
The low limit for the value of
x
, if any.None
means there is no limit. RaisesValueError
when the low limit is higher than the high limit, if both are notNone
.Expand source code
@property def limit_low(self) -> Optional[int]: """ limit_low The low limit for the value of `x`, if any. `None` means there is no limit. Raises `ValueError` when the low limit is higher than the high limit, if both are not `None`. """ return self.__low
var on_changed
-
on_changed
The
Callable
call back to be called after thex
property is set, providing a reference to the current instance after the change is applied, and theint
valuex
was previous to the change.When set to
None
(as by default), no callback will be triggered. prop sign : int
-
sign
-1
ifx
is negative,1
ifx
is positive,0
ifx
is0
.Expand source code
@property def sign(self) -> int: """ `sign` `-1` if `x` is negative, `1` if `x` is positive, `0` if `x` is `0`. """ return 0 if self.x == 0 else (1 if self.x > 0 else -1)
prop x : int
-
x
…Expand source code
@property def x(self) -> int: """ `x` The explicit value of the intiger. """ return self.__x
Methods
def bit_count(self) ‑> int
-
Inherited from:
UserInt
.bit_count
bit_count
… def bit_length(self) ‑> int
-
Inherited from:
UserInt
.bit_length
bit_count
… def fixed_sign_and(self, value: int) ‑> int
-
fixed_sign_and
Returns
The absolute value of this intiger, and-ed with the given
value
, with its sign restored after. def fixed_sign_invert(self) ‑> int
-
fixed_sign_invert
Returns
The absolute value of this intiger, inverted, with its sign restored after. If this intiger is 0, the value returned is
~0
(0
inverted), not0
. def fixed_sign_or(self, value: int) ‑> int
-
fixed_sign_or
Returns
The absolute value of this intiger, or-ed with the given
value
, with its sign restored after. def fixed_sign_xor(self, value: int) ‑> int
-
fixed_sign_xor
Returns
The absolute value of this intiger, xor-ed with the given
value
, with its sign restored after. def is_integer(self) ‑> bool
-
Inherited from:
UserInt
.is_integer
is_integer
… def to_bytes(self, length:
, byteorder: Literal['little', 'big'], *, signed: bool = False) ‑> bytes -
Inherited from:
UserInt
.to_bytes
to_bytes
…
class UserInt (x: int)
-
A class making a extendable intiger type, using the x attribute. Based off of the intent of objects like
UserList
, for theint
type.(Source: Some of the following docstring descriptions are derived form the official python docs: https://docs.python.org/3/library/stdtypes.html)
Expand source code
@attr_forward_operators("x", "xor", "lshift", "rshift", replace_existing=True, set_inline=True) @attr_forward_operators("x", "and_", "or_", replace_existing=True, set_inline=True) @attr_forward_operators("x", "invert", replace_existing=True) @attr_forward_operators("x", "neg", "abs", "pos", replace_existing=True) @attr_forward_operators("x", "floordiv", "mod", "pow", set_inline=True) @attr_forward_operators("x", "add", "sub", "mul", "truediv", set_inline=True) @total_ordering @attr_forward_operators("x", "lt", "eq", "gt", "le", "ge", replace_existing=True) class UserInt(*tuple(__USERINT_ABCS)): """ `UserInt` A class making a extendable intiger type, using the x attribute. Based off of the intent of objects like `UserList`, for the `int` type. (Source: Some of the following docstring descriptions are derived form the official python docs: https://docs.python.org/3/library/stdtypes.html) """ def __init__(self, x:int): self.__x:int = x @property def x(self) -> int: """ `x` The explicit value of the intiger. """ return self.__x @x.setter def x(self, value:int): self.__x = value def __int__(self): return self.x __index__ = __int__ __trunc__ = __int__ __floor__ = __int__ __ceil__ = __int__ def __hash__(self): return hash(self.x) def __bool__(self): return bool(self.x) def __float__(self): return float(self.x) def __complex__(self): return complex(self.x) def __str__(self): return str(self.x) def __repr__(self): return repr(self.x) def __format__(self, s): return format(self.x, s) def __round__(self, ndigits:Union[None, int] = None) -> int: return round(self.x, ndigits) def bit_count(self) -> int: """ `bit_count` Number of ones in the binary representation of the absolute value of self. Also known as the population count. """ return self.x.bit_count() def bit_length(self) -> int: """ `bit_count` Number of bits necessary to represent self in binary. """ return self.x.bit_length() def to_bytes(self, length:SupportsIndex, byteorder:Literal['little', 'big'], *, signed:bool = False ) -> bytes: """ `to_bytes` Arguments: Convert the 'int' into an array of 'bytes' representing the intiger. Wraps `int.to_bytes()` Arguments: `length` -- Length of bytes object to use. An `OverflowError` is raised if the integer is not representable with the given number of bytes. `byteorder` -- The byte order used to represent the integer. If `byteorder` is `'big'`, the most significant byte is at the beginning of the byte array. If `byteorder` is `'little'`, the most significant byte is at the end of the byte array. To request the native byte order of the host system, use `sys.byteorder` as the byte order value. `signed` -- Determines whether two's complement is used to represent the integer. If signed is `False` and a negative integer is given, an `OverflowError` is raised. """ return self.x.to_bytes(length, byteorder, signed=signed) def is_integer(self) -> bool: """ `is_integer` Always returns True. Exists for duck type compatibility with `float.is_integer()`. """ return True # these are all handled by the decorators, but type checkers miss that sometimes def __abs__(self): ... def __neg__(self): ... def __pos__(self): ... def __invert__(self): ...
Ancestors
- typing.SupportsInt
- typing.SupportsFloat
- typing.SupportsAbs
- typing.SupportsComplex
- typing.SupportsRound
- typing.SupportsIndex
- typing.Protocol
- typing.Generic
- collections.abc.Hashable
Subclasses
Instance variables
prop x : int
-
x
The explicit value of the intiger.
Expand source code
@property def x(self) -> int: """ `x` The explicit value of the intiger. """ return self.__x
Methods
def bit_count(self) ‑> int
-
bit_count
Number of ones in the binary representation of the absolute value of self.
Also known as the population count.
def bit_length(self) ‑> int
-
bit_count
Number of bits necessary to represent self in binary.
def is_integer(self) ‑> bool
-
is_integer
Always returns True. Exists for duck type compatibility with
float.is_integer()
. def to_bytes(self, length:
, byteorder: Literal['little', 'big'], *, signed: bool = False) ‑> bytes -
to_bytes
Arguments: Convert the 'int' into an array of 'bytes' representing the intiger. Wraps
int.to_bytes()
Arguments
length
– Length of bytes object to use. AnOverflowError
is raised if the integer is not representable with the given number of bytes.byteorder
– The byte order used to represent the integer. Ifbyteorder
is'big'
, the most significant byte is at the beginning of the byte array. Ifbyteorder
is'little'
, the most significant byte is at the end of the byte array. To request the native byte order of the host system, usesys.byteorder
as the byte order value.signed
– Determines whether two's complement is used to represent the integer. If signed isFalse
and a negative integer is given, anOverflowError
is raised.
class attr_forward_operators (instance_attr_name: str, *opperator_names: str, set_undundered: bool = False, replace_existing: bool = False, set_inline: bool = False)
-
Used to set an attribute of a class's opperators as the operators of it's containing class as well.
Expand source code
class attr_forward_operators: # pylint:disable=invalid-name """ `attr_forward_operators` Used to set an attribute of a class's opperators as the operators of it's containing class as well. """ class partial_opperator: # pylint:disable=invalid-name """ `partial_opperator` Used to get partial callable to a specific opperator of a attribute of the target class. """ def __init__(self, operator_module_attr_name:str, instance_attr_name:str): self.op_func:Callable = getattr(operator, operator_module_attr_name) self.instance_attr_name:str = instance_attr_name def __call__(self, inst_self, *args, **kwargs): return self.op_func(getattr(inst_self, self.instance_attr_name), *args, **kwargs) def callable_method(self) -> partialmethod: """ `callable_method` Returns: A partial callable method to the operator. """ return partialmethod(self) class partial_inline_opperator: # pylint:disable=invalid-name """ `partial_inline_opperator` Similar to `partial_opperator`, but specifically compatable with inline opperators instead. """ def __init__(self, operator_module_attr_name:str, instance_attr_name:str): self.op_func:Callable = getattr(operator, operator_module_attr_name) self.instance_attr_name:str = instance_attr_name def __call__(self, inst_self, *args, **kwargs): setattr(inst_self, self.instance_attr_name, self.op_func(getattr(inst_self, self.instance_attr_name), *args, **kwargs)) return inst_self def callable_method(self) -> partialmethod: """ `callable_method` Returns: A partial callable method to the inline operator. """ return partialmethod(self) @staticmethod def undunder(name:str) -> str: """ `undunder` Removes underscores form an attribute name. Arguments: name -- The attribute to remove underscores from. Returns: The name with underscores removed. """ return name.strip("_") @staticmethod def dunder(name:str) -> str: """ `dunder` Add the proper amount of underscores to an attribute name. Arguments: name -- The attribute to add underscores to. Returns: The name with underscores added. """ return f"__{attr_forward_operators.undunder(name)}__" @staticmethod def inline_name(name:str) -> str: """ `inline_name` Gets returns the inline name for the given opperator. Arguments: name -- The operator to get the inline name of. Returns: The inline opperator name. """ return f"i{attr_forward_operators.undunder(name)}" @staticmethod def inline_name_dunder(name:str) -> str: """ `inline_name_dunder` Gets returns the inline double underscored name for the given opperator. Arguments: name -- The operator to get the underscored inline name of. Returns: The underscored inline opperator name. """ return f"__i{attr_forward_operators.undunder(name)}__" def __init__(self, instance_attr_name:str, *opperator_names:str, set_undundered:bool = False, replace_existing:bool = False, set_inline:bool = False ): self.instance_attr_name:str = instance_attr_name self.opperator_names:Tuple[str, ...] = opperator_names self.set_undundered:bool = set_undundered self.set_inline:bool = set_inline self.replace_existing:bool = replace_existing def __call__(self, cls:Type) -> Type: for op_name in self.opperator_names: dundered = self.dunder(op_name) undundered = self.undunder(op_name) operator_name = None if hasattr(operator, op_name) and callable(getattr(operator, op_name)): operator_name = op_name elif hasattr(operator, undundered): operator_name = undundered elif hasattr(operator, dundered): operator_name = dundered if operator_name is None: raise NameError(f"Operator {op_name} was not found in the operators module") op = self.partial_opperator(operator_name, self.instance_attr_name) targets = {dundered : op.callable_method()} if self.set_undundered: targets[undundered] = op.callable_method() if self.set_inline: iop = self.partial_inline_opperator(operator_name,self.instance_attr_name) targets[self.inline_name_dunder(op_name)] = iop.callable_method() if self.set_undundered: targets[self.inline_name(op_name)] = iop.callable_method() if not self.replace_existing: for target_name in targets: if hasattr(cls, target_name): raise PermissionError(f"Attempted to overwrite prexisting method {op_name}") for name, func in targets.items(): setattr(cls, name, func) return cls
Class variables
var partial_inline_opperator
-
partial_inline_opperator
Similar to
partial_opperator
, but specifically compatable with inline opperators instead. var partial_opperator
-
partial_opperator
Used to get partial callable to a specific opperator of a attribute of the target class.
Static methods
def dunder(name: str) ‑> str
-
dunder
Add the proper amount of underscores to an attribute name.
Arguments
name – The attribute to add underscores to.
Returns
The name with underscores added.
def inline_name(name: str) ‑> str
-
inline_name
Gets returns the inline name for the given opperator.
Arguments
name – The operator to get the inline name of.
Returns
The inline opperator name.
def inline_name_dunder(name: str) ‑> str
-
inline_name_dunder
Gets returns the inline double underscored name for the given opperator.
Arguments
name – The operator to get the underscored inline name of.
Returns
The underscored inline opperator name.
def undunder(name: str) ‑> str
-
undunder
Removes underscores form an attribute name.
Arguments
name – The attribute to remove underscores from.
Returns
The name with underscores removed.