|
12 | 12 | import subprocess |
13 | 13 | import sys |
14 | 14 | import tempfile |
| 15 | +import timeit |
15 | 16 | import traceback |
16 | 17 | import types |
17 | 18 | from collections import UserDict |
| 19 | +from datetime import datetime |
18 | 20 | from enum import IntEnum |
19 | 21 | from functools import wraps |
20 | 22 | from itertools import groupby, islice |
|
72 | 74 | "get_hash_int", |
73 | 75 | "iter_weights", |
74 | 76 | "get_size", |
| 77 | + "base_encode", |
| 78 | + "base_decode", |
| 79 | + "gen_id", |
| 80 | + "timeti", |
75 | 81 | ] |
76 | 82 |
|
77 | 83 |
|
@@ -1766,6 +1772,126 @@ def get_size(obj, seen=None, iterate_unsafe=False) -> int: |
1766 | 1772 | return size |
1767 | 1773 |
|
1768 | 1774 |
|
| 1775 | +def base_encode( |
| 1776 | + num: int, |
| 1777 | + alphabet: str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", |
| 1778 | +) -> str: |
| 1779 | + """Encode a number to a base-N string. |
| 1780 | +
|
| 1781 | + Args: |
| 1782 | + num (int): The number to encode. |
| 1783 | + alphabet (str, optional): Defaults to "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". |
| 1784 | +
|
| 1785 | + Returns: |
| 1786 | + str: The encoded string. |
| 1787 | +
|
| 1788 | + Examples: |
| 1789 | + >>> base_encode(0) |
| 1790 | + '0' |
| 1791 | + >>> base_encode(1) |
| 1792 | + '1' |
| 1793 | + >>> base_encode(10000000000000) |
| 1794 | + '2Q3rKTOE' |
| 1795 | + >>> base_encode(10000000000000, "0123456789") |
| 1796 | + '10000000000000' |
| 1797 | + """ |
| 1798 | + length = len(alphabet) |
| 1799 | + result = "" |
| 1800 | + while num: |
| 1801 | + num, i = divmod(num, length) |
| 1802 | + result = f"{alphabet[i]}{result}" |
| 1803 | + return result or alphabet[0] |
| 1804 | + |
| 1805 | + |
| 1806 | +def base_decode( |
| 1807 | + string: str, |
| 1808 | + alphabet: str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", |
| 1809 | +) -> int: |
| 1810 | + """Decode a base-N string to a number. |
| 1811 | +
|
| 1812 | + Args: |
| 1813 | + string (str): The string to decode. |
| 1814 | + alphabet (str, optional): Defaults to "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". |
| 1815 | +
|
| 1816 | + Returns: |
| 1817 | + int: The decoded number. |
| 1818 | +
|
| 1819 | + Examples: |
| 1820 | + >>> base_decode("0") |
| 1821 | + 0 |
| 1822 | + >>> base_decode("1") |
| 1823 | + 1 |
| 1824 | + >>> base_decode("2Q3rKTOE") |
| 1825 | + 10000000000000 |
| 1826 | + >>> base_decode("10000000000000", "0123456789") |
| 1827 | + 10000000000000 |
| 1828 | + """ |
| 1829 | + length = len(alphabet) |
| 1830 | + result = 0 |
| 1831 | + for char in string: |
| 1832 | + result = result * length + alphabet.index(char) |
| 1833 | + return result |
| 1834 | + |
| 1835 | + |
| 1836 | +def gen_id(rand_len=4) -> str: |
| 1837 | + """Generate a unique ID based on the current time and random bytes |
| 1838 | +
|
| 1839 | + Args: |
| 1840 | + rand_len (int, optional): Defaults to 4. |
| 1841 | +
|
| 1842 | + Returns: |
| 1843 | + str: The generated ID. |
| 1844 | +
|
| 1845 | + Examples: |
| 1846 | + >>> a, b = gen_id(), gen_id() |
| 1847 | + >>> a != b |
| 1848 | + True |
| 1849 | + >>> import time |
| 1850 | + >>> ids = [time.sleep(0.000001) or gen_id() for _ in range(1000)] |
| 1851 | + >>> len(set(ids)) |
| 1852 | + 1000 |
| 1853 | + >>> ids = [gen_id() for _ in range(10000)] |
| 1854 | + >>> len(set(ids)) < 10000 |
| 1855 | + True |
| 1856 | + """ |
| 1857 | + now = datetime.now() |
| 1858 | + s1 = now.strftime("%y%m%d_%H%M%S") |
| 1859 | + s2 = base_encode(now.microsecond) |
| 1860 | + s2 = f"{s2:>04}{os.urandom(rand_len // 2).hex()}" |
| 1861 | + return f"{s1}_{s2}" |
| 1862 | + |
| 1863 | + |
| 1864 | +def timeti( |
| 1865 | + stmt: Union[str, Callable] = "pass", |
| 1866 | + setup="pass", |
| 1867 | + timer=timeit.default_timer, |
| 1868 | + number=1000000, |
| 1869 | + globals=None, |
| 1870 | +) -> int: |
| 1871 | + """Return the number of iterations per second for a given statement. |
| 1872 | +
|
| 1873 | + Args: |
| 1874 | + stmt (str, optional): Defaults to "pass". |
| 1875 | + setup (str, optional): Defaults to "pass". |
| 1876 | + timer (optional): Defaults to timeit.default_timer. |
| 1877 | + number (int, optional): Defaults to 1000000. |
| 1878 | + globals (dict, optional): Defaults to None. |
| 1879 | +
|
| 1880 | + Returns: |
| 1881 | + int: The number of iterations per second. |
| 1882 | +
|
| 1883 | + Examples: |
| 1884 | + >>> timeti("1 / 1") > 1000000 |
| 1885 | + True |
| 1886 | + >>> timeti(lambda : 1 + 1, number=100000) > 100000 |
| 1887 | + True |
| 1888 | + """ |
| 1889 | + result = timeit.timeit( |
| 1890 | + stmt=stmt, setup=setup, timer=timer, number=number, globals=globals |
| 1891 | + ) |
| 1892 | + return int(1 / (result / number)) |
| 1893 | + |
| 1894 | + |
1769 | 1895 | if __name__ == "__main__": |
1770 | 1896 | __name__ = "morebuiltins.utils" |
1771 | 1897 | import doctest |
|
0 commit comments