Commit bfd52972 by irul

bulk commit (2)

1 parent d97d57cd
# Default ignored files
/shelf/
/workspace.xml
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="PyQt5.QtCore.pyqtSignal.connect" />
<option value="PyQt5.QtCore.pyqtBoundSignal.connect" />
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file \ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Default" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pyfunc-P76Q4EE3)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/pyfunc.iml" filepath="$PROJECT_DIR$/.idea/pyfunc.iml" />
</modules>
</component>
</project>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.10 (pyfunc-P76Q4EE3)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PackageRequirementsSettings">
<option name="requirementsPath" value="" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="GOOGLE" />
<option name="myDocStringFormat" value="Google" />
</component>
</module>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file \ No newline at end of file
0.1 2023-08-05
--------------
- First commit
Copyright (c) 2018 The Python Packaging Authority
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file \ No newline at end of file
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
[dev-packages]
[requires]
python_version = "3.9"
helper functions for python # PyFunc
Kumpulan fungsi-fungsi pendek untuk membantu mempercepat proses koding.
File mode changed
No preview for this file type
from . import jsonrpcf
from .datef import Datef
from .generalf import json_from_dict, json_to_dict, strip_data
from .numberf import Numberf
from .stringf import Stringf
def author():
"""Informasi pembuat program.
"""
return "irul <irul.sylva@gmail.com>"
No preview for this file type
import re
from datetime import datetime, timezone, timedelta
from dateutil.parser import parse, ParserError
ymdhms = '%Y-%m-%d %H:%M:%S'
dmyhms = '%d-%m-%Y %H:%M:%S'
ymd = '%Y-%m-%d'
dmy = '%d-%m-%Y'
hms = '%H:%M:%S'
def _replace(date, separator):
return re.sub("[-.:]", separator, date[:10]) + date[10:]
class Datef:
"""
**Datef** merupakan class yang menyedikan fungsi-fungsi *helper* untuk menangani
tipe data *datetime*. Class Datef memiliki satu parameter input yaitu ``dt``
yang menerima masukan tanggal dengan tipe *datetime*, *str*, dan *int*.
.. code-block:: python
d = Datef("2023-08-06 14:57:34")
# mendapatkan tanggal dengan tipe datetime
d.datetime()
# out: datetime.datetime(2023, 8, 6, 14, 57, 34)
# format tanggal menjadi YYYY-MM-DD
d.ymd()
# out: '2023-08-06'
# mendapatkan unix timestamp
d.unix_ts()
# out: 1691308654
# negatif test
d = Datef("sembarang")
# out: ValueError: Unknown string format: sembarang
"""
def __init__(self, dt):
if isinstance(dt, datetime):
# type datetime
parse_dt = dt
elif isinstance(dt, int):
# type timestamp
parse_dt = datetime.fromtimestamp(dt)
else:
# type string (date/timestamp)
try:
if dt.isdigit():
parse_dt = datetime.fromtimestamp(int(dt))
else:
parse_dt = parse(dt)
except ParserError as e:
raise ValueError(str(e))
try:
self.dt = datetime.strptime(datetime.strftime(parse_dt, ymdhms), ymdhms)
except ValueError:
raise ValueError("{} is not a valid date".format(dt))
def __repr__(self):
return self.ymdhms()
def __call__(self) -> datetime:
return self.dt
def datetime(self) -> datetime:
"""Fungsi ini mengembalikan tanggal dengan tipe *datetime*.
"""
return self.dt
def ymdhms(self, date_separator=None) -> str:
"""Fungsi ini mengembalikan tanggal dalam format string YYYY-MM-DD HH:MM:SS.
Args:
date_separator (str) : tanda pemisah tanggal (default: tanda minus)
"""
d = datetime.strftime(self.dt, ymdhms)
if date_separator is not None:
return _replace(d, date_separator)
return d
def dmyhms(self, date_separator=None) -> str:
"""Fungsi ini mengembalikan tanggal dalam format string DD-MM-YYYY HH:MM:SS.
Args:
date_separator (str) : tanda pemisah tanggal (default: tanda minus)
"""
d = datetime.strftime(self.dt, dmyhms)
if date_separator is not None:
return _replace(d, date_separator)
return d
def ymd(self, date_separator=None) -> str:
"""Fungsi ini mengembalikan tanggal dalam format string YYYY-MM-DD.
Args:
date_separator (str) : tanda pemisah tanggal (default: tanda minus)
"""
d = datetime.strftime(self.dt, ymd)
if date_separator is not None:
return _replace(d, date_separator)
return d
def dmy(self, date_separator=None) -> str:
"""Fungsi ini mengembalikan tanggal dalam format string DD-MM-YYYY.
Args:
date_separator (str) : tanda pemisah tanggal (default: tanda minus)
"""
d = datetime.strftime(self.dt, dmy)
if date_separator is not None:
return _replace(d, date_separator)
return d
def hms(self, date_separator=None) -> str:
"""Fungsi ini mengembalikan waktu/jam dalam format string HH:MM:SS.
Args:
date_separator (str) : tanda pemisah tanggal (default: tanda minus)
"""
t = datetime.strftime(self.dt, hms)
if date_separator is not None:
return _replace(t, date_separator)
return t
def unix_ts(self):
"""Fungsi ini mengembalikan tanggal dalam format *unix timestamp*.
"""
# DateTime to Unix timestamp milliseconds
# return int(datetime.timestamp(self.dt) * 1000)
return int(datetime.timestamp(self.dt))
def utc_ts(self):
"""Fungsi ini mengembalikan tanggal dalam format *utc timestamp*.
"""
utc_time = self.dt.replace(tzinfo=timezone.utc)
# DateTime to Utc timestamp milliseconds
# return int(utc_time.timestamp() * 1000)
return int(utc_time.timestamp())
@classmethod
def timedelta(cls, dt, **kwargs):
"""Fungsi ini digunakan untuk melakukan perhitungan ataupun manipulasi
terhadap nilai tanggal pada parameter ``dt`` yang dikirim. Untuk isian parameter
``**kwargs`` dapat diisi dengan nilai yang sama pada fungsi *timedelta* bawaan
librari *datetime*.
Args:
dt (datetime, str, int) : tanggal
**kwargs (any) : parameter timedelta
Returns:
Class Datef
.. code-block:: python
d = Datef.timedelta('2023-08-06', days=2)
d.ymd()
# out: '2023-08-08'
"""
d = cls(dt).datetime() + timedelta(**kwargs)
return cls(d)
@classmethod
def check(cls, dt):
"""Fungsi untuk mengecek apakah nilai tanggal valid atau tidak. Jika valid maka akan
mengembalikan tanggal dengan tipe *datetime*. Jika tidak valid maka akan mengembalikan
nilai *None*.
Args:
dt (datetime, str, int) : tanggal
"""
try:
return cls(dt).datetime()
except ValueError:
return
import json
def json_from_dict(val) -> str:
"""Fungsi untuk mengkonversi dict kebentuk string json
.. code-block:: python
j = json_from_dict({"a": "ok", "b": "yes", "d": datetime(2021,8,5), "e": None, "f": True})
j
# out: '{"a": "ok", "b": "yes", "d": "2021-08-05 00:00:00", "e": null, "f": true}'
# negatif test
j = json_from_dict(None)
# out: ValueError: Not a dict
"""
if not isinstance(val, dict):
raise ValueError("Not a dict")
try:
j = json.dumps(val, default=str)
json.loads(j)
return j
except Exception:
raise ValueError("Dumps dict to json failed")
def dict_to_json(val) -> str:
"""Fungsi alias dari **json_from_dict**.
Lihat :meth:`irul.pyfunc.generalf.json_from_dict`
"""
return json_from_dict(val)
def json_to_dict(val) -> dict:
"""Fungsi untuk mengkonversi string json kebentuk dict
.. code-block:: python
d = json_to_dict('{"a": "ok", "b": "yes", "d": "2021-08-05", "e": null, "f": true}')
d
# out: {'a': 'ok', 'b': 'yes', 'd': '2021-08-05', 'e': None, 'f': True}
# negatif test
d = json_to_dict('sembarang')
# out: ValueError: Load dict from json failed
"""
try:
return json.loads(val)
except Exception:
raise ValueError("Load dict from json failed")
def dict_from_json(val) -> dict:
"""Fungsi alias dari **json_to_dict**.
Lihat :meth:`irul.pyfunc.generalf.json_to_dict`
"""
return json_to_dict(val)
def strip_data(data: dict, num_fields: dict = None):
"""Fungsi untuk menghapus spasi pada string. Contoh menyusul.
"""
def do_strip(data: dict, num_fields: dict = None):
for key, val in data.items():
if hasattr(val, 'strip'):
data[key] = val.strip()
if not val or val == "None":
data[key] = 0 if key in num_fields.keys() else ""
if key in num_fields.keys():
data[key] = float(val)
selected_vals = {key: data[key] for key in num_fields.keys() if key in data}
num_vals = {k: num_fields.get(k)(v) for k, v in selected_vals.items()}
data.update(num_vals)
return data
if num_fields is None:
num_fields = {}
values = data.copy()
if isinstance(values, list):
list_values = []
for row in values:
list_values.append(do_strip(row, num_fields))
return list_values
return do_strip(values, num_fields)
import json
from random import randint
from pyramid_rpc.jsonrpc import JsonRpcError
class Jsonrpcf:
"""
**Class Jsonrpcf** ini berfungsi untuk mencatat log request dan response jsonrpc.
"""
def __init__(self, request, logger, req_id=None):
self.req = request
self.log = logger
self.env = request.environ
self.req_id = req_id if req_id is not None else \
randint(100000000, 999999999)
self.userid = self.env['HTTP_USERID']
self.client_ip = self.req.remote_addr
if 'HTTP_X_FORWARDED_FOR' in self.env:
self.client_ip = self.env['HTTP_X_FORWARDED_FOR'].split(',')[0]
self.log.info(f"JSONRPC-REQ REQ_ID={self.req_id} IP={self.client_ip} "
f"USER={self.userid} METHOD={self.req.rpc_method} "
f"PARAMS={json.dumps(self.req.rpc_args)}")
def resp_success(self, result: dict):
"""Mencatat response sukses jsonrpc.
"""
self.log.info(f"JSONRPC-RESP REQ_ID={self.req_id} RESULT={json.dumps(result)}")
return result
def resp_error(self, error: str | Exception):
"""Mencatat response gagal jsonrpc.
"""
d = error.as_dict() \
if hasattr(error, 'as_dict') else dict(message=str(error))
e = JsonRpcError(**d)
self.log.error(f"JSONRPC-RESP REQ_ID={self.req_id} ERROR={json.dumps(e.as_dict())}")
raise e
class Networkf:
def remote_addr(self, request):
"""Fungsi untuk mendapatkan ip dari client yang mengakses aplikasi.
"""
environ = request.environ
addr = request.remote_addr
if 'HTTP_X_FORWARDED_FOR' in environ:
addr = environ['HTTP_X_FORWARDED_FOR'].split(',')[0]
return addr
import re
def _mynumber(val):
try:
return int(val)
except ValueError:
try:
return float(val)
except ValueError:
raise Exception(f"{val} is not a valid number, try as_number or number_only function")
class Numberf:
"""
**Numberf** merupakan class yang menyedikan fungsi-fungsi *helper* untuk menangani
tipe data *numeric*. Class Numberf memiliki satu parameter input yaitu ``n``
yang menerima masukan angka dengan tipe *int*, *float*, atau *str*.
.. code-block:: python
n = Numberf("12500")
# mendapatkan angka dengan tipe int
print(n.number())
# out: 12500
# format angka menggunakan pemisah ribuan
print(n.thousand())
# out: 12.500
# negatif test
n = Numberf("12500x")
# out: ValueError: 12500x is not a valid number, try as_number or number_only function
"""
def __init__(self, n):
if isinstance(n, (int, float)):
self.n = n
else:
try:
self.n = _mynumber(n)
except Exception as e:
raise ValueError(str(e))
def __repr__(self):
return str(self.n)
def __call__(self):
return self.n
def number(self):
"""Mengembalikan nilai angka dalam tipe *int* atau *float*.
"""
return self.n
def thousand(self, dot_separator=True, **kwargs) -> str:
"""Mengembalikan angka dengan pemisah ribuan. Tanda pemisah dapat disesuaikan
antara koma atau menggunakan tanda titik.
Args:
dot_separator :
- True, maka pemisah ribuan menggunakan titik (default)
- False, pemisah ribuan menggunakan tanda koma
**kwargs:
- prefix : tambahkan prefix tertentu, misal Rp
- suffix : tambahkan suffix tertentu, misal ,-
Returns:
Angka yang diformat menggunakan pemisah ribuan
"""
fthousand = f"{self.n:,}" # comma separator for thousands
if dot_separator:
fthousand = fthousand \
.replace(",", "_") \
.replace(".", ",") \
.replace("_", ".")
if "prefix" in kwargs:
fthousand = "%s%s" % (kwargs["prefix"], fthousand)
if "suffix" in kwargs:
fthousand = "%s%s" % (fthousand, kwargs["suffix"])
return fthousand
@staticmethod
def number_only(val) -> str:
"""Fungsi ini mengembalikan angka saja dari nilai paramater yang
berisi *alphanumeric* atau tidak hanya angka saja isinya.
Args:
val: string angka campur aduk
Returns:
Angka dengam tipe data *str*
"""
return re.sub("[^0-9]", "", str(val))
@classmethod
def as_number(cls, val):
"""Fungsi ini mengembalikan angka saja dari nilai paramater yang
berisi *alphanumeric* atau tidak hanya angka saja isinya.
Args:
val: string angka campur aduk
Returns:
Angka dengan tipe data *int* atau *float*
"""
val = cls.number_only(str(val))
return cls(val)
@classmethod
def check(cls, val):
"""Fungsi untuk mengecek apakah isian angka valid atau tidak. Jika valid maka akan
mengembalikan angka dengan tipe *int* atau *float*. Jika tidak valid maka akan
mengembalikan nilai *None*.
Args:
val (str, int, float) : angka campur aduk
"""
try:
return cls(val).number()
except ValueError:
return
class Stringf:
"""
**Stringf** merupakan class yang menyedikan fungsi-fungsi *helper* untuk menangani
tipe data *str*. Class Stringf memiliki satu parameter input yaitu ``s``
yang menerima masukan berupa string.
.. code-block:: python
s = Stringf("Terimakasih bapak dan ibu guru")
# mendapatkan panjang karakter
s.len()
# out: 30
"""
def __init__(self, s: str):
self.s = str(s)
def __repr__(self):
# print(f"print {self.s = }")
return self.s
def string(self):
"""Mengembalikan nilai string.
"""
return self.s
def len(self):
"""Mengembalikan panjang string.
"""
return len(self.s)
@staticmethod
def concat(*args, **kwargs):
"""Fungsi ini digunakan untuk melakukan penggabungan string. Parameter ``*args``
dapat diisi dengan nilai bertipe *str*, *list*, *set*, *tuple*, dan atau *dict*.
Sedangkan parameter ``**kwargs`` dapat diisi dengan *key*: *separator* dan *value*:
tanda pemisah yang ingin digunakan.
.. code-block:: python
s = Stringf.concat(("a","b"),{"c","d"},["e","f"],{"next":"g"}, "mantul", separator=".")
print(s)
# out: a.b.d.c.e.f.g.mantul
"""
list_args = []
for r in args:
if isinstance(r, list):
list_args.extend(r)
elif isinstance(r, dict):
list_args.extend(r.values())
elif isinstance(r, (set, tuple)):
list_args.extend(list(r))
else:
list_args.append(r)
if "separator" in kwargs:
return kwargs["separator"].join(list_args)
return "".join(list_args)
Metadata-Version: 2.1
Name: irul-pyfunc
Version: 0.1
Summary: helper functions for python
Author: Khairul Anwar
Author-email: irul.sylva@gmail.com
License: PostgreSQL License
License-File: LICENSE
helper functions for python
0.1 2023-08-05
--------------
- First commit
LICENSE
README.md
setup.py
irul/__init__.py
irul/pyfunc/__init__.py
irul/pyfunc/datef.py
irul/pyfunc/general.py
irul/pyfunc/jsonrpcf.py
irul/pyfunc/stringf.py
irul_pyfunc.egg-info/PKG-INFO
irul_pyfunc.egg-info/SOURCES.txt
irul_pyfunc.egg-info/dependency_links.txt
irul_pyfunc.egg-info/entry_points.txt
irul_pyfunc.egg-info/not-zip-safe
irul_pyfunc.egg-info/requires.txt
irul_pyfunc.egg-info/top_level.txt
\ No newline at end of file \ No newline at end of file
[console_scripts]
http_forwarder = irul_package.scripts.http_forwarder:main
print_hello = irul_package.scripts.print_hello:main
ipython==8.14.0
pyramid-rpc==0.8
python-dateutil==2.8.2
import os
from setuptools import (
setup,
find_packages,
)
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, "README.md")) as f:
README = f.read()
with open(os.path.join(here, "CHANGES.txt")) as f:
CHANGES = f.read()
line = CHANGES.splitlines()[0]
version = line.split()[0]
requires = [
'ipython',
'pyramid-rpc',
'python-dateutil',
]
setup(
name="irul-pyfunc",
version=version,
description="Helper functions for python/pyramid",
long_description=README + "\n\n" + CHANGES,
author="Khairul Anwar",
author_email="irul.sylva@gmail.com",
license="PostgreSQL License",
packages=find_packages(),
install_requires=requires,
zip_safe=False,
entry_points={
"console_scripts": []
},
)
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!