# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['pypipr']

package_data = \
{'': ['*']}

install_requires = \
['colorama',
 'cssselect',
 'lxml',
 'pint>=0.21,<0.22',
 'pyyaml>=6.0,<7.0',
 'requests>=2.30.0,<3.0.0',
 'tzdata']

extras_require = \
{':platform_system == "Linux"': ['getch']}

setup_kwargs = {
    'name': 'pypipr',
    'version': '0.1.115',
    'description': 'The Python Package Index Project',
    'long_description': '\n# About\nThe Python Package Index Project (pypipr)\n\npypi : https://pypi.org/project/pypipr\n\n\n# Setup\nInstall with pip\n```\npython -m pip install pypipr\n```\n\nImport with * for fastest access\n```python\nfrom pypipr.pypipr import *\n```\n\n# CONSTANT\n\n`LINUX`\n\n`WINDOWS`\n\n# FUNCTION\n\n## avg\n\n`avg`\n\nSimple Average Function karena tidak disediakan oleh python  \n\n```python  \nn = [1, 22, 2, 3, 13, 2, 123, 12, 31, 2, 2, 12, 2, 1]  \nprint(avg(n))  \n```\n\nOutput:\n```py\n16.285714285714285\n```\n\n## basename\n\n`basename`\n\nMengembalikan nama file dari path  \n\n```python  \nprint(basename("/ini/nama/folder/ke/file.py"))  \n```\n\nOutput:\n```py\nfile.py\n```\n\n## batchmaker\n\n`batchmaker`\n\nAlat Bantu untuk membuat teks yang berulang.  \nGunakan {[start][separator][finish]([separator][step])}.  \n```  \n[start] dan [finish]    -> bisa berupa huruf maupun angka  \n([separator][step])     -> bersifat optional  \n[separator]             -> selain huruf dan angka  \n[step]                  -> berupa angka positif  \n```  \n\n```python  \ns = "Urutan {1/6/3} dan {10:9} dan {j k} dan {Z - A - 15} saja."  \nprint(generator.batchmaker(s))  \nprint(batchmaker(s))  \n```\n\nOutput:\n```py\n<generator object generator.batchmaker at 0x0000014075FE6190>\n(\'Urutan 1 dan 10 dan j dan Z saja.\', \'Urutan 1 dan 10 dan j dan K saja.\', \'Urutan 1 dan 10 dan k dan Z saja.\', \'Urutan 1 dan 10 dan k dan K saja.\', \'Urutan 1 dan 9 dan j dan Z saja.\', \'Urutan 1 dan 9 dan j dan K saja.\', \'Urutan 1 dan 9 dan k dan Z saja.\', \'Urutan 1 dan 9 dan k dan K saja.\', \'Urutan 4 dan 10 dan j dan Z saja.\', \'Urutan 4 dan 10 dan j dan K saja.\', \'Urutan 4 dan 10 dan k dan Z saja.\', \'Urutan 4 dan 10 dan k dan K saja.\', \'Urutan 4 dan 9 dan j dan Z saja.\', \'Urutan 4 dan 9 dan j dan K saja.\', \'Urutan 4 dan 9 dan k dan Z saja.\', \'Urutan 4 dan 9 dan k dan K saja.\')\n```\n\n## calculate\n\n`calculate`\n\nMengembalikan hasil dari perhitungan teks menggunakan modul pint.  \nMendukung perhitungan matematika dasar dengan satuan.  \n\nReturn value:  \n- Berupa class Quantity dari modul pint  \n\nFormat:  \n- f"{result:~P}"            -> pretty  \n- f"{result:~H}"            -> html  \n- result.to_base_units()    -> SI  \n- result.to_compact()       -> human readable  \n\n```python  \nfx = "3 meter * 10 cm * 3 km"  \nres = calculate(fx)  \nprint(res)  \nprint(res.to_base_units())  \nprint(res.to_compact())  \nprint(f"{res:~P}")  \nprint(f"{res:~H}")  \n```\n\nOutput:\n```py\n90 centimeter * kilometer * meter\n900.0 meter ** 3\n900.0 meter ** 3\n90 cm·km·m\n90 cm km m\n```\n\n## chunck_array\n\n`chunck_array`\n\nMembagi array menjadi potongan-potongan dengan besaran yg diinginkan  \n\n```python  \narray = [2, 3, 12, 3, 3, 42, 42, 1, 43, 2, 42, 41, 4, 24, 32, 42, 3, 12, 32, 42, 42]  \nprint(generator.chunck_array(array, 5))  \nprint(chunck_array(array, 5))  \n```\n\nOutput:\n```py\n<generator object generator.chunck_array at 0x0000014075FE60B0>\n([2, 3, 12, 3, 3], [42, 42, 1, 43, 2], [42, 41, 4, 24, 32], [42, 3, 12, 32, 42], [42])\n```\n\n## console_run\n\n`console_run`\n\nMenjalankan command seperti menjalankan command di Command Terminal  \n\n```py  \nconsole_run(\'dir\')  \nconsole_run(\'ls\')  \n```\n\n## create_folder\n\n`create_folder`\n\nMembuat folder.  \nMembuat folder secara recursive dengan permission.  \n\n```py  \ncreate_folder("contoh_membuat_folder")  \ncreate_folder("contoh/membuat/folder/recursive")  \ncreate_folder("./contoh_membuat_folder/secara/recursive")  \n```\n\n## datetime_from_string\n\n`datetime_from_string`\n\nParse iso_string menjadi datetime object  \n\n```python  \nprint(datetime_from_string("2022-12-12 15:40:13").isoformat())  \nprint(datetime_from_string("2022-12-12 15:40:13", timezone="Asia/Jakarta").isoformat())  \n```\n\nOutput:\n```py\n2022-12-12T15:40:13+00:00\n2022-12-12T15:40:13+07:00\n```\n\n## datetime_now\n\n`datetime_now`\n\nMemudahkan dalam membuat Datetime untuk suatu timezone tertentu  \n\n```python  \nprint(datetime_now("Asia/Jakarta"))  \nprint(datetime_now("GMT"))  \nprint(datetime_now("Etc/GMT+7"))  \n```\n\nOutput:\n```py\n2023-06-05 19:12:27.671717+07:00\n2023-06-05 12:12:27.672714+00:00\n2023-06-05 05:12:27.675718-07:00\n```\n\n## dict_first\n\n`dict_first`\n\nMengambil nilai (key, value) pertama dari dictionary dalam bentuk tuple.  \n\n```python  \nd = {  \n    "key2": "value2",  \n    "key3": "value3",  \n    "key1": "value1",  \n}  \nprint(dict_first(d, remove=True))  \nprint(dict_first(d))  \n```\n\nOutput:\n```py\n(\'key2\', \'value2\')\n(\'key3\', \'value3\')\n```\n\n## dirname\n\n`dirname`\n\nMengembalikan nama folder dari path.  \nTanpa trailing slash di akhir.  \n\n```python  \nprint(dirname("/ini/nama/folder/ke/file.py"))  \n```\n\nOutput:\n```py\n/ini/nama/folder/ke\n```\n\n## exit_if_empty\n\n`exit_if_empty`\n\nKeluar dari program apabila seluruh variabel  \nsetara dengan empty  \n\n```py  \nvar1 = None  \nvar2 = \'0\'  \nexit_if_empty(var1, var2)  \n```\n\n## explode\n\n`explode`\n\nMemecah text menjadi list berdasarkan separator.  \n\n```python  \nt = \'/ini/contoh/path/\'  \nprint(explode(t, separator=\'/\'))  \n```\n\nOutput:\n```py\n[\'\', \'ini\', \'contoh\', \'path\', \'\']\n```\n\n## filter_empty\n\n`filter_empty`\n\n## get_class_method\n\n`get_class_method`\n\nMengembalikan berupa tuple yg berisi list dari method dalam class  \n\n```python  \nclass ExampleGetClassMethod:  \n    def a():  \n        return [x for x in range(10)]  \n\n    def b():  \n        return [x for x in range(10)]  \n\n    def c():  \n        return [x for x in range(10)]  \n\n    def d():  \n        return [x for x in range(10)]  \n\nprint(get_class_method(ExampleGetClassMethod))  \n```\n\nOutput:\n```py\n(<function ExampleGetClassMethod.a at 0x000001407619FCA0>, <function ExampleGetClassMethod.b at 0x000001407619FC10>, <function ExampleGetClassMethod.c at 0x000001407619FD30>, <function ExampleGetClassMethod.d at 0x000001407619FDC0>)\n```\n\n## get_filemtime\n\n`get_filemtime`\n\nMengambil informasi last modification time file dalam nano seconds  \n\n```python  \nprint(get_filemtime(__file__))  \n```\n\nOutput:\n```py\n1685966815090366000\n```\n\n## get_filesize\n\n`get_filesize`\n\nMengambil informasi file size dalam bytes  \n\n```python  \nprint(get_filesize(__file__))  \n```\n\nOutput:\n```py\n43701\n```\n\n## github_pull\n\n`github_pull`\n\nMenjalankan command `git pull`  \n\n```py  \ngithub_pull()  \n```\n\n## github_push\n\n`github_push`\n\nMenjalankan command status, add, commit dan push  \n\n```py  \ngithub_push(\'Commit Message\')  \n```\n\n## iexec\n\n`iexec`\n\nimprove exec() python function untuk mendapatkan outputnya  \n\n```python  \nprint(iexec(\'print(9*9)\'))  \n```\n\nOutput:\n```py\n81\n\n```\n\n## implode\n\n`implode`\n\nSimplify Python join functions like PHP function.  \nIterable bisa berupa sets, tuple, list, dictionary.  \n\n```python  \narr = {\'asd\',\'dfs\',\'weq\',\'qweqw\'}  \nprint(implode(arr, \', \'))  \n\narr = \'/ini/path/seperti/url/\'.split(\'/\')  \nprint(implode(arr, \',\'))  \nprint(implode(arr, \',\', remove_empty=True))  \n\narr = {\'a\':\'satu\', \'b\':(12, 34, 56), \'c\':\'tiga\', \'d\':\'empat\'}  \nprint(implode(arr, separator=\'</li>\\n<li>\', start=\'<li>\', end=\'</li>\', recursive_flat=True))  \nprint(implode(arr, separator=\'</div>\\n<div>\', start=\'<div>\', end=\'</div>\'))  \nprint(implode(10, \' \'))  \n```\n\nOutput:\n```py\nasd, weq, qweqw, dfs\n,ini,path,seperti,url,\nini,path,seperti,url\n<li>satu</li>\n<li>12</li>\n<li>34</li>\n<li>56</li>\n<li>tiga</li>\n<li>empat</li>\n<div>satu</div>\n<div><div>12</div>\n<div>34</div>\n<div>56</div></div>\n<div>tiga</div>\n<div>empat</div>\n10\n```\n\n## input_char\n\n`input_char`\n\nMeminta masukan satu huruf tanpa menekan Enter.  \n\n```py  \ninput_char("Input char : ")  \ninput_char("Input char : ", default=\'Y\')  \ninput_char("Input Char without print : ", echo_char=False)  \n```\n\n## iopen\n\n`iopen`\n\nMembaca atau Tulis pada path yang bisa merupakan FILE maupun URL.  \n\nBaca File :  \n- Membaca seluruh file.  \n- Jika berhasil content dapat diparse dengan regex.  \n- Apabila File berupa html, dapat diparse dengan css atau xpath.  \n\nTulis File :  \n- Menulis pada file.  \n- Jika file tidak ada maka akan dibuat.  \n- Jika file memiliki content maka akan di overwrite.  \n\nMembaca URL :  \n- Mengakses URL dan mengembalikan isi html nya berupa teks.  \n- Content dapat diparse dengan regex, css atau xpath.  \n\nTulis URL :  \n- Mengirimkan data dengan metode POST ke url.  \n- Jika berhasil dan response memiliki content, maka dapat diparse dengan regex, css atau xpath.  \n\n\n```python  \n# FILE  \nprint(iopen("__iopen.txt", "mana aja"))  \nprint(iopen("__iopen.txt", regex="(\\w+)"))  \n# URL  \nprint(iopen("https://www.google.com/", css_select="a"))  \nprint(iopen("https://www.google.com/", dict(coba="dulu"), xpath="//a"))  \n```\n\nOutput:\n```py\n8\n[\'mana\', \'aja\']\n[<Element a at 0x14076050ae0>, <Element a at 0x14075c850e0>, <Element a at 0x14076016900>, <Element a at 0x14076121b30>, <Element a at 0x14075f06720>, <Element a at 0x14075f064a0>, <Element a at 0x14075f06900>, <Element a at 0x14075f066d0>, <Element a at 0x140761005e0>, <Element a at 0x14076100b80>, <Element a at 0x140761006d0>, <Element a at 0x1407619b130>, <Element a at 0x140761bcdb0>, <Element a at 0x140761bcea0>, <Element a at 0x140761bc9f0>, <Element a at 0x140761bce00>, <Element a at 0x140761bce50>, <Element a at 0x140761bcef0>]\nFalse\n```\n\n## irange\n\n`irange`\n\nImprove python range() function untuk pengulangan menggunakan huruf  \n\n```python  \nprint(generator.irange(\'a\', \'z\'))  \nprint(irange(\'H\', \'a\'))  \nprint(irange(\'1\', \'5\', 3))  \nprint(irange(\'1\', 5, 3))  \n# print(irange(\'a\', 5, 3))  \nprint(irange(-10, 4, 3))  \nprint(irange(1, 5))  \n```\n\nOutput:\n```py\n<generator object generator.irange at 0x0000014075FE6350>\n[\'H\', \'I\', \'J\', \'K\', \'L\', \'M\', \'N\', \'O\', \'P\', \'Q\', \'R\', \'S\', \'T\', \'U\', \'V\', \'W\', \'X\', \'Y\', \'Z\', \'[\', \'\\\\\', \']\', \'^\', \'_\', \'`\', \'a\']\n[\'1\', \'4\']\n[1, 4]\n[-10, -7, -4, -1, 2]\n[1, 2, 3, 4, 5]\n```\n\n## is_empty\n\n`is_empty`\n\nMengecek apakah variable setara dengan nilai kosong pada empty.  \n\nPengecekan nilai yang setara menggunakan simbol \'==\', sedangkan untuk  \npengecekan lokasi memory yang sama menggunakan keyword \'is\'  \n\n```python  \nprint(is_empty("teks"))  \nprint(is_empty(True))  \nprint(is_empty(False))  \nprint(is_empty(None))  \nprint(is_empty(0))  \nprint(is_empty([]))  \n```\n\nOutput:\n```py\nFalse\nFalse\nTrue\nTrue\nTrue\nTrue\n```\n\n## is_iterable\n\n`is_iterable`\n\nMengecek apakah suatu variabel bisa dilakukan forloop atau tidak  \n\n```python  \ns = \'ini string\'  \nprint(is_iterable(s))  \n\nl = [12,21,2,1]  \nprint(is_iterable(l))  \n\nr = range(100)  \nprint(is_iterable(r))  \n\nd = {\'a\':1, \'b\':2}  \nprint(is_iterable(d.values()))  \n```\n\nOutput:\n```py\nFalse\nTrue\nTrue\nTrue\n```\n\n## is_valid_url\n\n`is_valid_url`\n\nMengecek apakah path merupakan URL yang valid atau tidak.  \nCara ini merupakan cara yang paling efektif.  \n\n```python  \nprint(is_valid_url("https://chat.openai.com/?model=text-davinci-002-render-sha"))  \nprint(is_valid_url("https://chat.openai.com/?model/=text-dav/inci-002-render-sha"))  \n```\n\nOutput:\n```py\nTrue\nTrue\n```\n\n## iscandir\n\n`iscandir`\n\nMempermudah scandir untuk mengumpulkan folder dan file.  \n\n```python  \nprint(generator.iscandir())  \nprint(iscandir("./", recursive=False, scan_file=False))  \n```\n\nOutput:\n```py\n<generator object generator.iscandir at 0x0000014075FE6350>\n(WindowsPath(\'.git\'), WindowsPath(\'.pytest_cache\'), WindowsPath(\'.vscode\'), WindowsPath(\'dist\'), WindowsPath(\'pypipr\'))\n```\n\n## log\n\n`log`\n\nDecorator untuk mempermudah pembuatan log karena tidak perlu mengubah fungsi yg sudah ada.  \nMelakukan print ke console untuk menginformasikan proses yg sedang berjalan didalam program.  \n\n```py  \n@log  \ndef some_function():  \n    pass  \n\n@log()  \ndef some_function_again():  \n    pass  \n\n@log("Calling some function")  \ndef some_function_more():  \n    pass  \n\nsome_function()  \nsome_function_again()  \nsome_function_more()  \n```\n\n## print_colorize\n\n`print_colorize`\n\nPrint text dengan warna untuk menunjukan text penting  \n\n```py  \nprint_colorize("Print some text")  \nprint_colorize("Print some text", color=colorama.Fore.RED)  \n```\n\n## print_dir\n\n`print_dir`\n\nPrint property dan method yang tersedia pada variabel  \n\n```python  \np = pathlib.Path("https://www.google.com/")  \nprint_dir(p, colorize=False)  \n```\n\nOutput:\n```py\n           __bytes__ : b\'https:\\\\www.google.com\'\n           __class__ : .\n             __dir__ : [\'__module__\', \'__doc__\', \'__slots__\', \'is_mount\', \'__new__\', \'_init\', \'_make_child_relpath\', \'__enter__\', \'__exit__\', \'_opener\', \'_raw_open\', \'cwd\', \'home\', \'samefile\', \'iterdir\', \'glob\', \'rglob\', \'absolute\', \'resolve\', \'stat\', \'owner\', \'group\', \'open\', \'read_bytes\', \'read_text\', \'write_bytes\', \'write_text\', \'readlink\', \'touch\', \'mkdir\', \'chmod\', \'lchmod\', \'unlink\', \'rmdir\', \'lstat\', \'link_to\', \'rename\', \'replace\', \'symlink_to\', \'exists\', \'is_dir\', \'is_file\', \'is_symlink\', \'is_block_device\', \'is_char_device\', \'is_fifo\', \'is_socket\', \'expanduser\', \'_accessor\', \'__reduce__\', \'_parse_args\', \'_from_parts\', \'_from_parsed_parts\', \'_format_parsed_parts\', \'_make_child\', \'__str__\', \'__fspath__\', \'as_posix\', \'__bytes__\', \'__repr__\', \'as_uri\', \'_cparts\', \'__eq__\', \'__hash__\', \'__lt__\', \'__le__\', \'__gt__\', \'__ge__\', \'__class_getitem__\', \'drive\', \'root\', \'anchor\', \'name\', \'suffix\', \'suffixes\', \'stem\', \'with_name\', \'with_stem\', \'with_suffix\', \'relative_to\', \'is_relative_to\', \'parts\', \'joinpath\', \'__truediv__\', \'__rtruediv__\', \'parent\', \'parents\', \'is_absolute\', \'is_reserved\', \'match\', \'_cached_cparts\', \'_drv\', \'_hash\', \'_parts\', \'_pparts\', \'_root\', \'_str\', \'__getattribute__\', \'__setattr__\', \'__delattr__\', \'__ne__\', \'__init__\', \'__reduce_ex__\', \'__subclasshook__\', \'__init_subclass__\', \'__format__\', \'__sizeof__\', \'__dir__\', \'__class__\', \'_flavour\']\n             __doc__ : Path subclass for Windows systems.\n\n    On a Windows system, instantiating a Path should return this object.\n    \n           __enter__ : https:\\www.google.com\n          __fspath__ : https:\\www.google.com\n            __hash__ : -8589791309141689556\n            __init__ : None\n   __init_subclass__ : None\n          __module__ : pathlib\n          __reduce__ : (<class \'pathlib.WindowsPath\'>, (\'https:\', \'www.google.com\'))\n            __repr__ : WindowsPath(\'https:/www.google.com\')\n          __sizeof__ : 80\n           __slots__ : ()\n             __str__ : https:\\www.google.com\n    __subclasshook__ : NotImplemented\n           _accessor : <pathlib._NormalAccessor object at 0x00000140753BE1C0>\n      _cached_cparts : [\'https:\', \'www.google.com\']\n             _cparts : [\'https:\', \'www.google.com\']\n                _drv : \n            _flavour : <pathlib._WindowsFlavour object at 0x00000140753B1A00>\n               _hash : -8589791309141689556\n               _init : None\n              _parts : [\'https:\', \'www.google.com\']\n               _root : \n                _str : https:\\www.google.com\n            absolute : C:\\Users\\ToshibaM840\\Desktop\\website\\pypipr\\https:\\www.google.com\n              anchor : \n            as_posix : https:/www.google.com\n                 cwd : C:\\Users\\ToshibaM840\\Desktop\\website\\pypipr\n               drive : \n          expanduser : https:\\www.google.com\n                home : C:\\Users\\ToshibaM840\n         is_absolute : False\n         is_reserved : False\n             iterdir : <generator object Path.iterdir at 0x0000014075FD2890>\n            joinpath : https:\\www.google.com\n                name : www.google.com\n              parent : https:\n             parents : <WindowsPath.parents>\n               parts : (\'https:\', \'www.google.com\')\n                root : \n                stem : www.google\n              suffix : .com\n            suffixes : [\'.google\', \'.com\']\n```\n\n## print_log\n\n`print_log`\n\nAkan melakukan print ke console.  \nBerguna untuk memberikan informasi proses program yg sedang berjalan.  \n\n```py  \nprint_log("Standalone Log")  \n```\n\n## random_bool\n\n`random_bool`\n\nMenghasilkan nilai random True atau False.  \nFungsi ini merupakan fungsi tercepat untuk mendapatkan random bool.  \nFungsi ini sangat cepat, tetapi pemanggilan fungsi ini membutuhkan  \noverhead yg besar.  \n\n```python  \nprint(random_bool())  \n```\n\nOutput:\n```py\nTrue\n```\n\n## serialize\n\n`serialize`\n\nMengubah variabel data menjadi string untuk yang dapat dibaca untuk disimpan.  \nString yang dihasilkan berbentuk syntax YAML/JSON/HTML.  \n\n```python  \ndata = {  \n    \'a\': 123,  \n    \'t\': [\'disini\', \'senang\', \'disana\', \'senang\'],  \n    \'l\': (12, 23, [12, 42]),  \n}  \nprint(serialize(data))  \nprint(serialize(data, syntax=\'html\'))  \n```\n\nOutput:\n```py\na: 123\nl: !!python/tuple\n- 12\n- 23\n-   - 12\n    - 42\nt:\n- disini\n- senang\n- disana\n- senang\n\n<table>\n    <tbody>\n        <tr>\n            <th>a</th>\n            <td>\n                <span>123</span>\n            </td>\n        </tr>\n        <tr>\n            <th>t</th>\n            <td>\n                <ul>\n                    <li>\n                        <span>disini</span>\n                    </li>\n                    <li>\n                        <span>senang</span>\n                    </li>\n                    <li>\n                        <span>disana</span>\n                    </li>\n                    <li>\n                        <span>senang</span>\n                    </li>\n                </ul>\n            </td>\n        </tr>\n        <tr>\n            <th>l</th>\n            <td>\n                <ul>\n                    <li>\n                        <span>12</span>\n                    </li>\n                    <li>\n                        <span>23</span>\n                    </li>\n                    <li>\n                        <ul>\n                            <li>\n                                <span>12</span>\n                            </li>\n                            <li>\n                                <span>42</span>\n                            </li>\n                        </ul>\n                    </li>\n                </ul>\n            </td>\n        </tr>\n    </tbody>\n</table>\n\n```\n\n## serialize_html\n\n`serialize_html`\n\nSerialisasi python variabel menjadi HTML.  \n```  \nList -> <ul>...</ul>  \nDict -> <table>...</table>  \n```  \n\n```python  \ndata = {  \n    \'abc\': 123,  \n    \'list\': [1, 2, 3, 4, 5],  \n    \'dict\': {\'a\': 1, \'b\':2, \'c\':3},  \n}  \nprint(serialize_html(data))  \n```\n\nOutput:\n```py\n<table>\n  <tbody>\n    <tr>\n      <th>abc</th>\n      <td>\n        <span>123</span>\n      </td>\n    </tr>\n    <tr>\n      <th>list</th>\n      <td>\n        <ul>\n          <li>\n            <span>1</span>\n          </li>\n          <li>\n            <span>2</span>\n          </li>\n          <li>\n            <span>3</span>\n          </li>\n          <li>\n            <span>4</span>\n          </li>\n          <li>\n            <span>5</span>\n          </li>\n        </ul>\n      </td>\n    </tr>\n    <tr>\n      <th>dict</th>\n      <td>\n        <table>\n          <tbody>\n            <tr>\n              <th>a</th>\n              <td>\n                <span>1</span>\n              </td>\n            </tr>\n            <tr>\n              <th>b</th>\n              <td>\n                <span>2</span>\n              </td>\n            </tr>\n            <tr>\n              <th>c</th>\n              <td>\n                <span>3</span>\n              </td>\n            </tr>\n          </tbody>\n        </table>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n```\n\n## set_timeout\n\n`set_timeout`\n\nMenjalankan fungsi ketika sudah sekian detik.  \nApabila timeout masih berjalan tapi kode sudah selesai dieksekusi semua, maka  \nprogram tidak akan berhenti sampai timeout selesai, kemudian fungsi dijalankan,  \nkemudian program dihentikan.  \n\n```python  \nset_timeout(3, lambda: print("Timeout 3"))  \nx = set_timeout(7, lambda: print("Timeout 7"))  \nprint(x)  \nprint("menghentikan timeout 7")  \nx.cancel()  \n```\n\nOutput:\n```py\n<Timer(Thread-2, started 19244)>\nmenghentikan timeout 7\n```\n\n## sets_ordered\n\n`sets_ordered`\n\nHanya mengambil nilai unik dari suatu list  \n\n```python  \narray = [2, 3, 12, 3, 3, 42, 42, 1, 43, 2, 42, 41, 4, 24, 32, 42, 3, 12, 32, 42, 42]  \nprint(generator.sets_ordered(array))  \nprint(sets_ordered(array))  \n```\n\nOutput:\n```py\n<generator object generator.sets_ordered at 0x0000014075FD2740>\n[2, 3, 12, 42, 1, 43, 41, 4, 24, 32]\n```\n\n## str_cmp\n\n`str_cmp`\n\nMembandingakan string secara incase-sensitive menggunakan lower().  \nLebih cepat dibandingkan upper(), casefold(), re.fullmatch(), len().  \nperbandingan ini sangat cepat, tetapi pemanggilan fungsi ini membutuhkan  \noverhead yg besar.  \n```python  \nprint(str_cmp(\'teks1\', \'Teks1\'))  \n```\n\nOutput:\n```py\nTrue\n```\n\n## strtr\n\n`strtr`\n\nSTRing TRanslate mengubah string menggunakan kamus dari dict.  \nReplacement dapat berupa text biasa ataupun regex pattern.  \nApabila replacement berupa regex, gunakan raw string `r"..."`  \nUntuk regex capturing gunakan `(...)`, dan untuk mengaksesnya gunakan `\\1`, `\\2`, .., dst.  \n\n```python  \ntext = \'aku ini mau ke sini\'  \nreplacements = {  \n    "sini": "situ",  \n    r"(ini)": r"itu dan \\1",  \n}  \nprint(strtr(text, replacements))  \n```\n\nOutput:\n```py\naku itu dan ini mau ke situ\n```\n\n## to_str\n\n`to_str`\n\nMengubah value menjadi string literal  \n\n```python  \nprint(to_str(5))  \nprint(to_str([]))  \nprint(to_str(False))  \nprint(to_str(True))  \nprint(to_str(None))  \n```\n\nOutput:\n```py\n5\n\nFalse\nTrue\n\n```\n\n## unserialize\n\n`unserialize`\n\nMengubah string data hasil dari serialize menjadi variabel.  \nString data adalah berupa syntax YAML.  \n\n```python  \ndata = {  \n    \'a\': 123,  \n    \'t\': [\'disini\', \'senang\', \'disana\', \'senang\'],  \n    \'l\': (12, 23, [12, 42])  \n}  \ns = serialize(data)  \nprint(unserialize(s))  \n```\n\n## unserialize_html\n\n`unserialize_html`\n\nMengambil data yang berupa list `<ul>`, dan table `<table>` dari html  \ndan menjadikannya data python berupa list.  \nsetiap data yang ditemukan akan dibungkus dengan tuple sebagai separator.  \n```  \nlist (<ul>)     -> list         -> list satu dimensi  \ntable (<table>) -> list[list]   -> list satu dimensi didalam list  \n```  \napabila data berupa ul maka dapat dicek type(data) -> html_ul  \napabila data berupa ol maka dapat dicek type(data) -> html_ol  \napabila data berupa dl maka dapat dicek type(data) -> html_dl  \napabila data berupa table maka dapat dicek type(data) -> html_table  \n\n```python  \npprint.pprint(unserialize_html(iopen("https://harga-emas.org/")), depth=10)  \npprint.pprint(unserialize_html(iopen("https://harga-emas.org/1-gram/")), depth=10)  \n```\n\nOutput:\n```py\n([\'Home\', \'Emas 1 Gram\', \'History\', \'Trend\', \'Perak 1 Gram\'],\n [[\'Harga Emas Hari Ini - Senin, 05 Juni 2023\'],\n  [\'Spot Emas USD↓1.941,56 (-6,64) / oz\',\n   \'Kurs IDR15.140,00 / USD\',\n   \'Emas IDR↓945.078 (-3.232) / gr\'],\n  [\'LM Antam (Jual)1.057.000 / gr\', \'LM Antam (Beli)943.000 / gr\']],\n [[\'Harga Emas Hari Ini\'],\n  [\'Gram\', \'Gedung Antam Jakarta\', \'Pegadaian\'],\n  [\'per Gram (Rp)\', \'per Batangan (Rp)\', \'per Gram (Rp)\', \'per Batangan (Rp)\'],\n  [\'1000\',\n   \'998\',\n   \'997.600\',\n   \'1.022.540 (-3.075)\',\n   \'1.022.540.000 (-3.075.000)\'],\n  [\'500\', \'1.995\', \'997.640\', \'1.022.582 (-3.074)\', \'511.291.000 (-1.537.000)\'],\n  [\'250\', \'3.992\', \'998.060\', \'1.023.012 (-3.076)\', \'255.753.000 (-769.000)\'],\n  [\'100\', \'9.991\', \'999.120\', \'1.024.100 (-3.080)\', \'102.410.000 (-308.000)\'],\n  [\'50\', \'19.998\', \'999.900\', \'1.024.900 (-3.080)\', \'51.245.000 (-154.000)\'],\n  [\'25\', \'40.059\', \'1.001.480\', \'1.026.520 (-3.080)\', \'25.663.000 (-77.000)\'],\n  [\'10\', \'100.650\', \'1.006.500\', \'1.031.700 (-3.100)\', \'10.317.000 (-31.000)\'],\n  [\'5\', \'202.400\', \'1.012.000\', \'1.037.400 (-3.000)\', \'5.187.000 (-15.000)\'],\n  [\'3\', \'339.556\', \'1.018.667\', \'1.044.333 (-3.000)\', \'3.133.000 (-9.000)\'],\n  [\'2\', \'513.500\', \'1.027.000\', \'1.053.000 (-3.000)\', \'2.106.000 (-6.000)\'],\n  [\'1\', \'1.057.000\', \'1.057.000\', \'1.084.000 (-3.000)\', \'1.084.000 (-3.000)\'],\n  [\'0.5\', \'2.314.000\', \'1.157.000\', \'1.188.000 (-2.000)\', \'594.000 (-1.000)\'],\n  [\'Update harga LM Antam :05 Juni 2023, pukul 08:29Harga pembelian kembali \'\n   \':Rp. 943.000/gram\',\n   \'Update harga LM Pegadaian :03 Juni 2023\']],\n [[\'Spot Harga Emas Hari Ini (Market Open)\'],\n  [\'Satuan\', \'USD\', \'Kurs\\xa0Dollar\', \'IDR\'],\n  [\'Ounce\\xa0(oz)\', \'1.941,56 (-6,64)\', \'15.140,00\', \'29.395.218\'],\n  [\'Gram\\xa0(gr)\', \'62,42\', \'15.140,00\', \'945.078 (-3.232)\'],\n  [\'Kilogram\\xa0(kg)\', \'62.422,60\', \'15.140,00\', \'945.078.218\'],\n  [\'Update harga emas :05 Juni 2023, pukul 19:12Update kurs :13 Febuari 2023, \'\n   \'pukul 09:10\']],\n [[\'Gram\', \'UBS Gold 99.99%\'],\n  [\'Jual\', \'Beli\'],\n  [\'/ Batang\', \'/ Gram\', \'/ Batang\', \'/ Gram\'],\n  [\'100\',\n   \'96.235.000 (-750.000)\',\n   \'962.350 (-7.500)\',\n   \'94.400.000 (-400.000)\',\n   \'944.000 (-4.000)\'],\n  [\'50\',\n   \'48.170.000 (-375.000)\',\n   \'963.400 (-7.500)\',\n   \'47.200.000 (-200.000)\',\n   \'944.000 (-4.000)\'],\n  [\'25\',\n   \'24.188.000 (-187.000)\',\n   \'967.520 (-7.480)\',\n   \'23.600.000 (-100.000)\',\n   \'944.000 (-4.000)\'],\n  [\'10\',\n   \'9.725.000 (-75.000)\',\n   \'972.500 (-7.500)\',\n   \'9.440.000 (-40.000)\',\n   \'944.000 (-4.000)\'],\n  [\'5\',\n   \'4.915.000 (-37.000)\',\n   \'983.000 (-7.400)\',\n   \'4.720.000 (-20.000)\',\n   \'944.000 (-4.000)\'],\n  [\'1\',\n   \'1.016.000 (-7.000)\',\n   \'1.016.000 (-7.000)\',\n   \'944.000 (-4.000)\',\n   \'944.000 (-4.000)\'],\n  [\'\', \'Update :05 Juni 2023, pukul 10:52\']],\n [[\'Konversi Satuan\'],\n  [\'Satuan\', \'Ounce (oz)\', \'Gram (gr)\', \'Kilogram (kg)\'],\n  [\'Ounce\\xa0(oz)\', \'1\', \'31,1034767696\', \'0,0311034768\'],\n  [\'Gram\\xa0(gr)\', \'0,0321507466\', \'1\', \'0.001\'],\n  [\'Kilogram\\xa0(kg)\', \'32,1507466000\', \'1.000\', \'1\']],\n [[\'Pergerakan Harga Emas Dunia\'],\n  [\'Waktu\', \'Emas\'],\n  [\'Unit\', \'USD\', \'IDR\'],\n  [\'Angka\', \'+/-\', \'Angka\', \'+/-\'],\n  [\'Hari Ini\', \'Kurs\', \'\', \'\', \'15.140\', \'%\'],\n  [\'oz\', \'1.948,20\', \'-6,64-0,34%\', \'29.495.748\', \'-100.530-0,34%\'],\n  [\'gr\', \'62,64\', \'-0,21-0,34%\', \'948.310\', \'-3.232-0,34%\'],\n  [\'30 Hari\', \'Kurs\', \'\', \'\', \'15.140\', \'%\'],\n  [\'oz\', \'2.016,87\', \'-75,31-3,73%\', \'30.535.412\', \'-1.140.193-3,73%\'],\n  [\'gr\', \'64,84\', \'-2,42-3,73%\', \'981.736\', \'-36.658-3,73%\'],\n  [\'2 Bulan\', \'Kurs\', \'\', \'\', \'15.140\', \'%\'],\n  [\'oz\', \'2.012,83\', \'-71,27-3,54%\', \'30.474.246\', \'-1.079.028-3,54%\'],\n  [\'gr\', \'64,71\', \'-2,29-3,54\', \'979.770\', \'-34.692-3,54%\'],\n  [\'6 Bulan\', \'Kurs\', \'\', \'\', \'15.576\', \'-436-2,80%\'],\n  [\'oz\', \'1.781,44\', \'+160,12+8,99%\', \'27.747.709\', \'+1.647.509+5,94%\'],\n  [\'gr\', \'57,27\', \'+5,15+8,99%\', \'892.110\', \'+52.969+5,94%\'],\n  [\'1 Tahun\', \'Kurs\', \'\', \'\', \'14.526\', \'+614+4,23%\'],\n  [\'oz\', \'1.851,10\', \'+90,46+4,89%\', \'26.889.079\', \'+2.506.140+9,32%\'],\n  [\'gr\', \'59,51\', \'+2,91+4,89%\', \'864.504\', \'+80.574+9,32%\'],\n  [\'2 Tahun\', \'Kurs\', \'\', \'\', \'14.297\', \'+843+5,90%\'],\n  [\'oz\', \'1.891,24\', \'+50,32+2,66%\', \'27.039.077\', \'+2.356.141+8,71%\'],\n  [\'gr\', \'60,80\', \'+1,62+2,66%\', \'869.327\', \'+75.752+8,71%\'],\n  [\'3 Tahun\', \'Kurs\', \'\', \'\', \'14.100\', \'+1.040+7,38%\'],\n  [\'oz\', \'1.682,73\', \'+258,83+15,38%\', \'23.726.493\', \'+5.668.725+23,89%\'],\n  [\'gr\', \'54,10\', \'+8,32+15,38%\', \'762.824\', \'+182.254+23,89%\'],\n  [\'5 Tahun\', \'Kurs\', \'\', \'\', \'13.875\', \'+1.265+9,12%\'],\n  [\'oz\', \'1.299,44\', \'+642,12+49,42%\', \'18.029.730\', \'+11.365.488+63,04%\'],\n  [\'gr\', \'41,78\', \'+20,64+49,42%\', \'579.669\', \'+365.409+63,04%\']])\n([\'Home\', \'Emas 1 Gram\', \'History\', \'Trend\', \'Perak 1 Gram\'],\n [[\'\'],\n  [\'Emas 24 KaratHarga Emas 1 Gram\', \'\'],\n  [\'USD\', \'62,42↓\', \'-0,22-0,35%\'],\n  [\'KURS\', \'14.869,85↓\', \'-32,05-0,22%\'],\n  [\'IDR\', \'928.214,75↓\', \'-5.181,92-0,56%\'],\n  [\'Senin, 05 Juni 2023 19:12\']],\n [[\'\'],\n  [\'Emas 1 Gram (IDR)Emas 1 Gram (USD)Kurs USD-IDR\',\n   \'Hari Ini\',\n   \'1 Bulan\',\n   \'1 Tahun\',\n   \'5 Tahun\',\n   \'Max\',\n   \'\']],\n [[\'Pergerakkan Harga Emas 1 Gram\'],\n  [\'\', \'Penutupan Kemarin\', \'Pergerakkan Hari Ini\', \'Rata-rata\'],\n  [\'USD\', \'62,64\', \'62,42 - 62,64\', \'62,53\'],\n  [\'KURS\', \'14.901,90\', \'14.869,85 - 14.901,90\', \'14.885,88\'],\n  [\'IDR\', \'933.396,67\', \'928.214,75 - 933.396,67\', \'930.805,71\'],\n  [\'\'],\n  [\'\', \'Awal Tahun\', \'Pergerakkan YTD\', \'+/- YTD\'],\n  [\'USD\', \'58,64\', \'58,23 - 65,97\', \'+3,78 (6,45%)\'],\n  [\'KURS\', \'15.538,50\', \'14.669,40 - 15.629,15\', \'-668,65(-4,30%)\'],\n  [\'IDR\', \'911.153,72\', \'888.842,84 - 982.694,10\', \'+17.061,03 (1,87%)\'],\n  [\'\'],\n  [\'\', \'Tahun Lalu / 52 Minggu\', \'Pergerakkan 52 Minggu\', \'+/- 52 Minggu\'],\n  [\'USD\', \'59,51\', \'52,31 - 65,97\', \'+2,91 (4,89%)\'],\n  [\'KURS\', \'14.433,50\', \'14.431,75 - 15.785,40\', \'+436,35 (3,02%)\'],\n  [\'IDR\', \'858.998,88\', \'795.009,21 - 982.694,10\', \'+69.215,87 (8,06%)\']])\n```\n\n# CLASS\n\n## ComparePerformance\n\n`ComparePerformance`\n\nMenjalankan seluruh method dalam class,  \nKemudian membandingkan waktu yg diperlukan.  \nNilai 100 berarti yang tercepat.  \n  \n```python  \nclass ExampleComparePerformance(ComparePerformance):  \n    # number = 1  \n    z = 10  \n  \n    def a(self):  \n        return (x for x in range(self.z))  \n  \n    def b(self):  \n        return tuple(x for x in range(self.z))  \n  \n    def c(self):  \n        return [x for x in range(self.z)]  \n  \n    def d(self):  \n        return list(x for x in range(self.z))  \n  \npprint.pprint(ExampleComparePerformance().compare_result(), depth=100)  \nprint(ExampleComparePerformance().compare_performance())  \nprint(ExampleComparePerformance().compare_performance())  \nprint(ExampleComparePerformance().compare_performance())  \nprint(ExampleComparePerformance().compare_performance())  \nprint(ExampleComparePerformance().compare_performance())  \n```\n\nOutput:\n```py\n{\'a\': <generator object ExampleComparePerformance.a.<locals>.<genexpr> at 0x0000014075FD2B30>,\n \'b\': (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),\n \'c\': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n \'d\': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}\n{\'a\': 100, \'b\': 144, \'c\': 117, \'d\': 157}\n{\'a\': 100, \'b\': 146, \'c\': 115, \'d\': 166}\n{\'a\': 100, \'b\': 134, \'c\': 124, \'d\': 156}\n{\'a\': 100, \'b\': 140, \'c\': 112, \'d\': 151}\n{\'a\': 100, \'b\': 114, \'c\': 115, \'d\': 117}\n```\n\n## RunParallel\n\n`RunParallel`\n\nMenjalankan program secara bersamaan.  \n  \n- `class RunParallel` didesain hanya untuk pemrosesan data saja.  \n- Penggunaannya `class RunParallel` dengan cara membuat instance sub class beserta data yg akan diproses, kemudian panggil fungsi yg dipilih `run_asyncio / run_multi_threading / run_multi_processing`, kemudian dapatkan hasilnya.  \n- `class RunParallel` tidak didesain untuk menyimpan data, karena setiap module terutama module `multiprocessing` tidak dapat mengakses data kelas dari proses yg berbeda.  \n- Semua methods akan dijalankan secara paralel kecuali method dengan nama yg diawali underscore `_`  \n- Method untuk multithreading/multiprocessing harus memiliki 2 parameter, yaitu: `result: dict` dan `q: queue.Queue`. Parameter `result` digunakan untuk memberikan return value dari method, dan Parameter `q` digunakan untuk mengirim data antar proses.  \n- Method untuk asyncio harus menggunakan keyword `async def`, dan untuk perpindahan antar kode menggunakan `await asyncio.sleep(0)`, dan keyword `return` untuk memberikan return value.  \n- Return Value berupa dictionary dengan key adalah nama function, dan value adalah return value dari setiap fungsi  \n- Menjalankan Multiprocessing harus berada dalam blok `if __name__ == "__main__":` karena area global pada program akan diproses lagi. Terutama pada sistem operasi windows.  \n- `run_asyncio()` akan menjalankan kode dalam satu program, hanya saja alur program dapat berpindah-pindah menggunkan `await asyncio.sleep(0)`.  \n- `run_multi_threading()` akan menjalankan program dalam satu CPU, hanya saja dalam thread yang berbeda. Walaupun tidak benar-benar berjalan secara bersamaan namun bisa meningkatkan kecepatan penyelesaian program, dan dapat saling mengakses resource antar program.  Akses resource antar program bisa secara langsung maupun menggunakan parameter yang sudah disediakan yaitu `result: dict` dan `q: queue.Queue`.  \n- `run_multi_processing()` akan menjalankan program dengan beberapa CPU. Program akan dibuatkan environment sendiri yang terpisah dari program induk. Keuntungannya adalah program dapat benar-benar berjalan bersamaan, namun tidak dapat saling mengakses resource secara langsung. Akses resource menggunakan parameter yang sudah disediakan yaitu `result: dict` dan `q: queue.Queue`.  \n  \n```python  \nclass ExampleRunParallel(RunParallel):  \n    z = "ini"  \n  \n    def __init__(self) -> None:  \n        self.pop = random.randint(0, 100)  \n  \n    def _set_property_here(self, v):  \n        self.prop = v  \n  \n    def a(self, result: dict, q: queue.Queue):  \n        result["z"] = self.z  \n        result["pop"] = self.pop  \n        result["a"] = "a"  \n        q.put("from a 1")  \n        q.put("from a 2")  \n  \n    def b(self, result: dict, q: queue.Queue):  \n        result["z"] = self.z  \n        result["pop"] = self.pop  \n        result["b"] = "b"  \n        result["q_get"] = q.get()  \n  \n    def c(self, result: dict, q: queue.Queue):  \n        result["z"] = self.z  \n        result["pop"] = self.pop  \n        result["c"] = "c"  \n        result["q_get"] = q.get()  \n  \n    async def d(self):  \n        print("hello")  \n        await asyncio.sleep(0)  \n        print("hello")  \n  \n        result = {}  \n        result["z"] = self.z  \n        result["pop"] = self.pop  \n        result["d"] = "d"  \n        return result  \n  \n    async def e(self):  \n        print("world")  \n        await asyncio.sleep(0)  \n        print("world")  \n  \n        result = {}  \n        result["z"] = self.z  \n        result["pop"] = self.pop  \n        result["e"] = "e"  \n        return result  \n  \nif __name__ == "__main__":  \n    print(ExampleRunParallel().run_asyncio())  \n    print(ExampleRunParallel().run_multi_threading())  \n    print(ExampleRunParallel().run_multi_processing())  \n```\n\nOutput:\n```py\n```\n\n## __calculate__quantity__\n\n`__calculate__quantity__`\n\n## generator\n\n`generator`\n\nClass ini menyediakan beberapa fungsi yang bisa mengembalikan generator.  \nDigunakan untuk mengoptimalkan program.  \n  \nClass ini dibuat karena python generator yang disimpan dalam variabel  \nhanya dapat diakses satu kali.\n\n## html_dl\n\n`html_dl`\n\nClass ini digunakan untuk serialize dan unserialize html\n\n## html_ol\n\n`html_ol`\n\nClass ini digunakan untuk serialize dan unserialize html\n\n## html_table\n\n`html_table`\n\nClass ini digunakan untuk serialize dan unserialize html\n\n## html_ul\n\n`html_ul`\n\nClass ini digunakan untuk serialize dan unserialize html\n',
    'author': 'ufiapjj',
    'author_email': 'ufiapjj@gmail.com',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'None',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'python_requires': '>=3.9',
}


setup(**setup_kwargs)
