neue Datei: .gitignore
neue Datei: README.md neue Datei: pyproject.toml neue Datei: src/jeb_utils/__init__.py neue Datei: src/jeb_utils/auth_utils.py neue Datei: src/jeb_utils/crypto_utils.py neue Datei: src/jeb_utils/exceptions.py neue Datei: src/jeb_utils/jeb_utils.py neue Datei: src/jeb_utils/jebp_utils.py neue Datei: src/jeb_utils/utils.py
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import os
|
||||
from typing import Tuple, Literal, Sequence
|
||||
|
||||
__all__ = [
|
||||
'is_number',
|
||||
'int_to_bytes',
|
||||
'bits_to_byte',
|
||||
'byte_to_bits',
|
||||
'get_next_lower_integer_multiple',
|
||||
'find_nearest_lower_number',
|
||||
'create_file_if_not_exists',
|
||||
]
|
||||
|
||||
def is_number(string: str, base: int = 10) -> bool:
|
||||
'''
|
||||
Checks whether the string is a number.
|
||||
|
||||
:param string: The string
|
||||
:type string: str
|
||||
:param base: The base
|
||||
:type base: int
|
||||
|
||||
:return: ``True`` if the string is a number, otherwise ``False``
|
||||
:rtype: bool
|
||||
'''
|
||||
if not string:
|
||||
return False
|
||||
try:
|
||||
int(string, base)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def int_to_bytes(n: int, signed: bool = False) -> bytes:
|
||||
'''
|
||||
Converts the integer into bytes (dynamic length).
|
||||
|
||||
:param n: The integer
|
||||
:type n: int
|
||||
:param signed: Whether the integer is signed or not.
|
||||
:type signed: bool
|
||||
|
||||
:return: The bytes
|
||||
:rtype: bytes
|
||||
'''
|
||||
n = int(n)
|
||||
length = (n.bit_length() + 7) // 8
|
||||
if length == 0:
|
||||
length = 1
|
||||
return n.to_bytes(length, signed=signed)
|
||||
|
||||
def _bits_to_byte(bits: Tuple[Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1]]) -> bytes:
|
||||
if len(bits) != 8:
|
||||
raise ValueError('bits must be a tuple of 8 bits')
|
||||
byte = 0
|
||||
for bit in bits:
|
||||
if int(bit) not in (0, 1):
|
||||
raise ValueError('each bit must be 0 or 1')
|
||||
byte = (byte << 1) | int(bit)
|
||||
return byte
|
||||
|
||||
def bits_to_byte(*bits: Literal[0, 1]) -> bytes:
|
||||
'''
|
||||
Converts the bits into a single byte.
|
||||
|
||||
:param bits: The bits
|
||||
:type bits: int
|
||||
|
||||
:raises ValueError: If there are more than 8 bits specified or a bit is neither ``0`` nor ``1``.
|
||||
|
||||
:return: The byte
|
||||
:rtype: bytes
|
||||
'''
|
||||
if len(bits) > 8:
|
||||
raise ValueError('a maximum of 8 bits can be converted to a byte')
|
||||
while len(bits) < 8:
|
||||
bits = (0,) + bits
|
||||
return bytes([_bits_to_byte(bits)])
|
||||
|
||||
def byte_to_bits(b: bytes) -> Tuple[Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1], Literal[0, 1]]:
|
||||
'''
|
||||
Converts the byte to a tuple of bits.
|
||||
|
||||
:param b: The byte
|
||||
:type b: bytes
|
||||
|
||||
:raises ValueError: If more than one byte is specified or ``b`` is neither a bytestring nor a bytearray,
|
||||
|
||||
:return: The bits
|
||||
:rtype: tuple
|
||||
'''
|
||||
if not isinstance(b, (bytes, bytearray)) or len(b) != 1:
|
||||
raise ValueError('input must be a single byte')
|
||||
byte = b[0]
|
||||
return tuple((byte >> i) & 1 for i in reversed(range(8)))
|
||||
|
||||
def get_next_lower_integer_multiple(value: int, multiple: int) -> int:
|
||||
'''
|
||||
Returns the next lower integer multiple.
|
||||
|
||||
:param value: The value
|
||||
:type value: int
|
||||
:param multiple: The factor
|
||||
:type multiple: int
|
||||
|
||||
:return: The next lower integer multiple
|
||||
:rtype: int
|
||||
'''
|
||||
return value - (value % multiple)
|
||||
|
||||
def find_nearest_lower_number(number_list: Sequence, target: int | float) -> int | float:
|
||||
'''
|
||||
Finds the nearest lower number to the target from the list.
|
||||
|
||||
:param number_list: The list
|
||||
:type number_list: Sequence
|
||||
:param target: The target
|
||||
:type target: int | float
|
||||
|
||||
:return: The nearest lower number to the target from the list.
|
||||
:rtype: int | float
|
||||
'''
|
||||
nearest = None
|
||||
for number in number_list:
|
||||
if number <= target:
|
||||
if nearest is None or number > nearest:
|
||||
nearest = number
|
||||
return nearest
|
||||
|
||||
def create_file_if_not_exists(path: str, content: bytes = b''):
|
||||
'''
|
||||
Creates a file if it does not exist.
|
||||
|
||||
:param path: The file path
|
||||
:type path: str
|
||||
:param content: Optional, the content of the file if it is newly created.
|
||||
:type content: bytes
|
||||
'''
|
||||
if not os.path.exists(path):
|
||||
with open(path, 'wb') as f:
|
||||
f.write(content)
|
||||
f.close()
|
||||
Reference in New Issue
Block a user