summaryrefslogtreecommitdiff
path: root/discord_rpc/util
diff options
context:
space:
mode:
authorJesusaves <cpntb1@ymail.com>2024-02-05 11:17:23 -0300
committerJesusaves <cpntb1@ymail.com>2024-02-05 11:17:23 -0300
commit29ffe5de3c308013742b5bd97f7d75b09bd3b427 (patch)
tree7199cecaf204701770de171d007e561589b19762 /discord_rpc/util
parentf6b8c0c64757c73b6f2063d3a6d93ce2f8f527d5 (diff)
downloadtkinter-29ffe5de3c308013742b5bd97f7d75b09bd3b427.tar.gz
tkinter-29ffe5de3c308013742b5bd97f7d75b09bd3b427.tar.bz2
tkinter-29ffe5de3c308013742b5bd97f7d75b09bd3b427.tar.xz
tkinter-29ffe5de3c308013742b5bd97f7d75b09bd3b427.zip
Some button aligning, a CI template, and Discord RPC
Diffstat (limited to 'discord_rpc/util')
-rw-r--r--discord_rpc/util/__init__.py0
-rw-r--r--discord_rpc/util/backoff.py35
-rw-r--r--discord_rpc/util/limits.py32
-rw-r--r--discord_rpc/util/types.py349
-rw-r--r--discord_rpc/util/utils.py180
5 files changed, 596 insertions, 0 deletions
diff --git a/discord_rpc/util/__init__.py b/discord_rpc/util/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/discord_rpc/util/__init__.py
diff --git a/discord_rpc/util/backoff.py b/discord_rpc/util/backoff.py
new file mode 100644
index 0000000..650a871
--- /dev/null
+++ b/discord_rpc/util/backoff.py
@@ -0,0 +1,35 @@
+from __future__ import absolute_import
+import random
+from .types import Int32, Int64
+
+
+class Backoff(object):
+ _min_amt = None
+ _max_amt = None
+ _current = None
+ _fails = Int32()
+
+ def __init__(self, min_amt, max_amt):
+ min_amt = max(min_amt, 1)
+ max_amt = max(max_amt, 1)
+ self._min_amt = Int64(min_amt)
+ self._max_amt = Int64(max_amt)
+ self._current = Int64(min_amt)
+
+ def reset(self):
+ self._fails = Int32(0)
+ self._current = self._min_amt.get_copy()
+
+ def next_delay(self):
+ self._fails += 1
+ delay = Int64(self._current.get_number() * 2.0 * random.random())
+ self._current = Int64(min(self._current.get_number() + delay.get_number(), self._max_amt))
+ return self._current
+
+ @property
+ def fails(self):
+ return self._fails
+
+ @property
+ def current(self):
+ return self._current
diff --git a/discord_rpc/util/limits.py b/discord_rpc/util/limits.py
new file mode 100644
index 0000000..6e84b30
--- /dev/null
+++ b/discord_rpc/util/limits.py
@@ -0,0 +1,32 @@
+def get_min_max(bit_size, unsigned=False):
+ if unsigned:
+ bit_min = 0
+ bit_max = (2**bit_size) - 1
+ else:
+ bit_min = -(2**(bit_size - 1))
+ bit_max = 2**(bit_size - 1) - 1
+ return bit_min, bit_max
+
+
+# limits for c types
+CHAR_MIN = -128
+CHAR_MAX = 127
+UCHAR_MAX = 255
+
+SHORT_MIN = -32768
+SHORT_MAX = 32767
+USHORT_MAX = 65535
+
+INT_MIN = -2147483648
+INT_MAX = 2147483647
+UINT_MAX = 4294967295
+INT32_MIN = INT_MIN
+INT32_MAX = INT_MAX
+UINT32_MAX = UINT_MAX
+
+LONG_MIN = -9223372036854775808
+LONG_MAX = 9223372036854775807
+ULONG_MAX = 18446744073709551615
+INT64_MIN = LONG_MIN
+INT64_MAX = LONG_MAX
+UINT64_MAX = ULONG_MAX
diff --git a/discord_rpc/util/types.py b/discord_rpc/util/types.py
new file mode 100644
index 0000000..fdfd246
--- /dev/null
+++ b/discord_rpc/util/types.py
@@ -0,0 +1,349 @@
+from __future__ import absolute_import
+from .limits import INT32_MIN, INT32_MAX, UINT32_MAX, INT64_MIN, INT64_MAX, UINT64_MAX
+
+
+_number_types = [int]
+try:
+ _number_types.append(float)
+except NameError:
+ pass
+try:
+ _number_types.append(long)
+except NameError:
+ pass
+_number_types = tuple(_number_types)
+
+
+class UnderflowError(ArithmeticError):
+ pass
+
+
+class Number(object):
+ _min = None
+ _max = None
+ _bits = None
+ _raise_exceptions = False
+
+ def __init__(self, number=0, raise_exceptions=False):
+ self._raise_exceptions = raise_exceptions
+ if isinstance(number, Number):
+ number = number.get_number()
+ else:
+ # validate number, ret_val should only be number, not a class
+ number = self._check_number(number, number_only=True)
+ if not isinstance(number, _number_types):
+ raise TypeError('Number must be of type int/float/long!')
+ self._number = number
+
+ def _check_number(self, num, number_only=False):
+ if self._max is not None and self._min is not None:
+ if self._raise_exceptions:
+ if num > self._max:
+ raise OverflowError()
+ elif num < self._min:
+ raise UnderflowError()
+ if self._min == 0:
+ if not number_only:
+ return self.__class__(num & self._max)
+ else:
+ return num & self._max
+ else:
+ if num & (1 << (self._bits-1)):
+ if not number_only:
+ return self.__class__(num | ~self._max)
+ else:
+ return num | ~self._max
+ else:
+ if not number_only:
+ return self.__class__(num & self._max)
+ else:
+ return num & self._max
+ else:
+ # there are no min/max to check with, so just return the number
+ if not number_only:
+ return self.__class__(num)
+ else:
+ return num
+
+ def __lt__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._number < other
+
+ def __le__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._number <= other
+
+ def __eq__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._number == other
+
+ def __ne__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._number != other
+
+ def __gt__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._number > other
+
+ def __ge__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._number >= other
+
+ def __bool__(self):
+ return self._number
+
+ def __repr__(self):
+ return "{class_name}({number})".format(class_name=self.__class__.__name__, number=self._number)
+
+ def __str__(self):
+ return str(self._number)
+
+ def __cmp__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ if self._number == other:
+ return 0
+ elif self._number < other:
+ return -1
+ elif self._number > other:
+ return 1
+
+ def __nonzero__(self):
+ return self._number != 0
+
+ def __add__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number + other)
+
+ def __sub__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number - other)
+
+ def __mul__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number * other)
+
+ def __div__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number / other)
+
+ def __truediv__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self.__div__(other)
+
+ def __floordiv__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number // other)
+
+ def __mod__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number % other)
+
+ def __divmod__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(divmod(self._number, other))
+
+ def __pow__(self, power, modulo=None):
+ if isinstance(power, Number):
+ power = power.get_number()
+ if modulo is not None and isinstance(modulo, Number):
+ modulo = modulo.get_number()
+ return self._check_number(pow(self._number, power, modulo))
+
+ def __lshift__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number << other)
+
+ def __rshift__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number >> other)
+
+ def __and__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number & other)
+
+ def __xor__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number ^ other)
+
+ def __or__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(self._number | other)
+
+ def __radd__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other + self._number)
+
+ def __rsub__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other - self._number)
+
+ def __rmul__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other * self._number)
+
+ def __rdiv__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other / self._number)
+
+ def __rtruediv__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self.__rdiv__(other)
+
+ def __rfloordiv__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other // self._number)
+
+ def __rmod__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other % self._number)
+
+ def __rdivmod__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(divmod(other, self._number))
+
+ def __rpow__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(pow(other, self._number))
+
+ def __rlshift__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other << self._number)
+
+ def __rrshift__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other >> self._number)
+
+ def __rand__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other & self._number)
+
+ def __rxor__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other ^ self._number)
+
+ def __ror__(self, other):
+ if isinstance(other, Number):
+ other = other.get_number()
+ return self._check_number(other | self._number)
+
+ def __neg__(self):
+ return self._check_number(-self._number)
+
+ def __pos__(self):
+ return self._check_number(+self._number)
+
+ def __abs__(self):
+ return self._check_number(abs(self._number))
+
+ def __invert__(self):
+ return self._check_number(~self._number)
+
+ def __complex__(self):
+ return complex(self._number)
+
+ def __int__(self):
+ return int(self._number)
+
+ def __long__(self):
+ return long(self._number)
+
+ def __float__(self):
+ return float(self._number)
+
+ def __oct__(self):
+ return oct(self._number)
+
+ def __hex__(self):
+ return hex(self._number)
+
+ def __round__(self, ndigits=None):
+ if ndigits is not None and isinstance(ndigits, Number):
+ ndigits = ndigits.get_number()
+ return round(self._number, ndigits)
+
+ def __trunc__(self):
+ from math import trunc
+ return trunc(self._number)
+
+ def __floor__(self):
+ from math import floor
+ return floor(self._number)
+
+ def __ceil__(self):
+ from math import ceil
+ return ceil(self._number)
+
+ def get_number(self):
+ return self._number
+
+ def get_copy(self):
+ return self.__class__(self._number)
+
+
+class _Int(Number):
+ def __init__(self, number=0, raise_exceptions=False):
+ if isinstance(number, Number):
+ number = number.get_number()
+ number = int(number)
+ Number.__init__(self, number, raise_exceptions)
+
+ def _check_number(self, num, number_only=False):
+ if isinstance(num, Number):
+ num = num.get_number()
+ num = int(num)
+ return Number._check_number(self, num, number_only)
+
+
+class Int32(_Int):
+ _min = INT32_MIN
+ _max = INT32_MAX
+ _bits = 32
+
+
+class Int64(_Int):
+ _min = INT64_MIN
+ _max = INT64_MAX
+ _bits = 64
+
+
+class UInt32(_Int):
+ _min = 0
+ _max = UINT32_MAX
+
+
+class UInt64(_Int):
+ _min = 0
+ _max = UINT64_MAX
diff --git a/discord_rpc/util/utils.py b/discord_rpc/util/utils.py
new file mode 100644
index 0000000..8142596
--- /dev/null
+++ b/discord_rpc/util/utils.py
@@ -0,0 +1,180 @@
+from copy import deepcopy
+import json
+from os import getenv, getpid, path
+import platform
+from sys import version_info, argv
+
+
+class Empty(Exception):
+ pass
+
+
+class DummyQueue(object):
+ """
+ Dummy queue thread that does nothing. Should only be used if imports fail.
+ """
+
+ def __init__(self, maxsize=0):
+ pass
+
+ def qsize(self):
+ return 0
+
+ def empty(self):
+ return True
+
+ def full(self):
+ return False
+
+ def put(self, obj, *args, **kwargs):
+ pass
+
+ def put_nowait(self, obj):
+ pass
+
+ def get(self, *args, **kwargs):
+ raise Empty
+
+ def get_nowait(self):
+ raise Empty
+
+ def task_done(self):
+ pass
+
+ def join(self):
+ pass
+
+
+def is_python3():
+ return version_info[0] == 3
+
+
+def is_windows():
+ return platform.system() == 'Windows'
+
+
+def is_linux():
+ return platform.system() == 'Linux'
+
+
+def is_mac_osx():
+ # this may not be accurate, just going off of what I find off the internet
+ return platform.system() == 'Darwin'
+
+
+def get_temp_path():
+ if is_windows():
+ return None
+ for val in ('XDG_RUNTIME_DIR', 'TMPDIR', 'TMP', 'TEMP'):
+ tmp = getenv(val)
+ if tmp is not None:
+ return tmp
+ return '/tmp'
+
+
+def get_process_id():
+ return getpid()
+
+
+def is_callable(obj):
+ try:
+ # for Python 2.x or Python 3.2+
+ return callable(obj)
+ except Exception:
+ # for Python version: 3 - 3.2
+ return hasattr(obj, '__call__')
+
+
+# python 2 + 3 compatibility
+if is_python3():
+ unicode = str
+ bytes = bytes
+else:
+ bytes = str
+ unicode = unicode
+
+
+def to_bytes(obj):
+ if isinstance(obj, type(b'')):
+ return obj
+ if hasattr(obj, 'encode') and is_callable(obj.encode):
+ return obj.encode('ascii', 'replace')
+ raise TypeError('Could not convert object type "{}" to bytes!'.format(type(obj)))
+
+
+def to_unicode(obj):
+ if isinstance(obj, type(u'')):
+ return obj
+ if hasattr(obj, 'decode') and is_callable(obj.decode):
+ return obj.decode(encoding='utf-8')
+ raise TypeError('Could not convert object type "{}" to unicode!'.format(type(obj)))
+
+
+def iter_keys(obj):
+ if not isinstance(obj, dict):
+ raise TypeError('Object must be of type dict!')
+ if is_python3():
+ return obj.keys()
+ return obj.iterkeys()
+
+
+def iter_items(obj):
+ if not isinstance(obj, dict):
+ raise TypeError('Object must be of type dict!')
+ if is_python3():
+ return obj.items()
+ return obj.iteritems()
+
+
+def iter_values(obj):
+ if not isinstance(obj, dict):
+ raise TypeError('Object must be of type dict!')
+ if is_python3():
+ return obj.values()
+ return obj.itervalues()
+
+
+def _py_dict(obj):
+ if not isinstance(obj, dict):
+ raise TypeError('Object must be of type dict!')
+ new_dict = dict()
+ for name, val in iter_items(obj):
+ if isinstance(name, type(b'')) and is_python3():
+ name = to_unicode(name)
+ elif isinstance(name, type(u'')) and not is_python3():
+ name = to_bytes(name)
+ if isinstance(val, dict):
+ val = _py_dict(val)
+ elif isinstance(val, type(b'')) and is_python3():
+ val = to_unicode(val)
+ elif isinstance(val, type(u'')) and not is_python3():
+ val = to_bytes(val)
+ new_dict[name] = val
+ return deepcopy(new_dict)
+
+
+def json2dict(obj):
+ if isinstance(obj, dict):
+ return deepcopy(_py_dict(obj))
+ if obj is None:
+ return dict()
+ if hasattr(obj, 'strip'):
+ if obj.strip() == '':
+ return dict()
+ else:
+ return deepcopy(_py_dict(deepcopy(json.loads(obj))))
+ raise TypeError('Object must be of string type!')
+
+
+if not is_python3():
+ range = xrange
+else:
+ range = range
+
+
+def get_executable_directory():
+ return path.abspath(path.dirname(argv[0]))
+
+
+def get_executable_path():
+ return path.join(get_executable_directory(), argv[0])