data-manipulation 0.40__tar.gz → 0.42__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {data_manipulation-0.40/data_manipulation.egg-info → data_manipulation-0.42}/PKG-INFO +4 -1
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/_version.py +3 -3
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/base.py +23 -10
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/beautifulsoup_.py +2 -4
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/boto3_.py +5 -7
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/cryptography_.py +2 -5
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/django_.py +3 -5
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/kerberos_.py +2 -3
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/mysql_connector_python_.py +7 -7
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/pandas_.py +25 -4
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/psycopg2_.py +1 -4
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/psycopg_.py +1 -4
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/pyspark_.py +5 -4
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/smtplib_.py +6 -4
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/sqlalchemy_.py +1 -5
- {data_manipulation-0.40 → data_manipulation-0.42/data_manipulation.egg-info}/PKG-INFO +4 -1
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation.egg-info/requires.txt +3 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/setup.py +3 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/LICENSE +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/MANIFEST.in +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/README.md +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/__init__.py +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/flask_.py +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/geopandas_.py +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/openldap_.py +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/prometheus_.py +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation.egg-info/SOURCES.txt +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation.egg-info/dependency_links.txt +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation.egg-info/top_level.txt +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/setup.cfg +0 -0
- {data_manipulation-0.40 → data_manipulation-0.42}/versioneer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: data_manipulation
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.42
|
|
4
4
|
Summary: Powerful data manipulation
|
|
5
5
|
Home-page: https://github.com/shawnngtq/data-manipulation
|
|
6
6
|
Author: Shawn Ng
|
|
@@ -24,7 +24,10 @@ Requires-Dist: boto3
|
|
|
24
24
|
Requires-Dist: django
|
|
25
25
|
Requires-Dist: flask
|
|
26
26
|
Requires-Dist: geopandas
|
|
27
|
+
Requires-Dist: ipython
|
|
28
|
+
Requires-Dist: loguru
|
|
27
29
|
Requires-Dist: mysql-connector-python
|
|
30
|
+
Requires-Dist: numpy
|
|
28
31
|
Requires-Dist: pandas
|
|
29
32
|
Requires-Dist: psycopg
|
|
30
33
|
Requires-Dist: psycopg2
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2024-
|
|
11
|
+
"date": "2024-08-03T10:19:19+0800",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "30171014f9c6ac9bcb9c5aad60d40e662d35ab79",
|
|
15
|
+
"version": "0.42"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import itertools
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
2
4
|
import subprocess
|
|
5
|
+
from ast import literal_eval
|
|
6
|
+
from distutils.util import strtobool
|
|
3
7
|
from typing import List
|
|
8
|
+
from urllib.parse import urlencode
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
logger = logging.getLogger(__file__)
|
|
10
|
+
from loguru import logger
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
# DATA STRUCTURE
|
|
@@ -38,7 +42,6 @@ def clean_string(
|
|
|
38
42
|
str
|
|
39
43
|
Uppercase cleaned string
|
|
40
44
|
"""
|
|
41
|
-
import re
|
|
42
45
|
|
|
43
46
|
if remove_parenthesis:
|
|
44
47
|
string = re.sub(r"\(.*\)", "", string)
|
|
@@ -69,7 +72,6 @@ def get_string_case_combination(str_: str) -> list:
|
|
|
69
72
|
list
|
|
70
73
|
Case combinations
|
|
71
74
|
"""
|
|
72
|
-
import itertools
|
|
73
75
|
|
|
74
76
|
return list(map("".join, itertools.product(*zip(str_.upper(), str_.lower()))))
|
|
75
77
|
|
|
@@ -119,6 +121,22 @@ def get_country_name_variation() -> dict:
|
|
|
119
121
|
return variations
|
|
120
122
|
|
|
121
123
|
|
|
124
|
+
def get_country_code_variation() -> dict:
|
|
125
|
+
variations = {
|
|
126
|
+
"BA": ["BOSNIA"],
|
|
127
|
+
"BW": ["AFRICA"],
|
|
128
|
+
"CN": ["REPUBLIC OF CHINA"],
|
|
129
|
+
"CZ": ["CZECH REPUBLIC"],
|
|
130
|
+
"KR": ["REPUBLIC OF KOREA"],
|
|
131
|
+
"MK": ["MACEDONIA"],
|
|
132
|
+
"RU": ["RUSSIAN FEDERATION"],
|
|
133
|
+
"SK": ["SLAVONIC", "SLOVAK REPUBLIC"],
|
|
134
|
+
"TR": ["TURKEY", "TURKIYE"],
|
|
135
|
+
"US": ["UNITED STATES"],
|
|
136
|
+
}
|
|
137
|
+
return variations
|
|
138
|
+
|
|
139
|
+
|
|
122
140
|
def list_tuple_without_none(list_tuple: list | tuple) -> list | tuple:
|
|
123
141
|
"""
|
|
124
142
|
Return the given list / tuple without None variation
|
|
@@ -188,7 +206,6 @@ def string_boolean_to_int(boolean_str_rep: str) -> int:
|
|
|
188
206
|
int
|
|
189
207
|
_description_
|
|
190
208
|
"""
|
|
191
|
-
from distutils.util import strtobool
|
|
192
209
|
|
|
193
210
|
int_ = strtobool(string_str_to_str(boolean_str_rep))
|
|
194
211
|
return int_
|
|
@@ -223,7 +240,6 @@ def string_dlt_to_dlt(dlt_str_rep: str) -> dict | list | tuple:
|
|
|
223
240
|
dict | list | tuple
|
|
224
241
|
_description_
|
|
225
242
|
"""
|
|
226
|
-
from ast import literal_eval
|
|
227
243
|
|
|
228
244
|
dlt = literal_eval(dlt_str_rep)
|
|
229
245
|
return dlt
|
|
@@ -302,7 +318,6 @@ def get_path_files(path: str, keywords: list) -> list:
|
|
|
302
318
|
list
|
|
303
319
|
Sorted list
|
|
304
320
|
"""
|
|
305
|
-
import os
|
|
306
321
|
|
|
307
322
|
list_ = []
|
|
308
323
|
for file in sorted(os.listdir(path)):
|
|
@@ -335,7 +350,6 @@ def remove_path_file(path: str, keyword: str, n: int = 2) -> None:
|
|
|
335
350
|
>>> get_path_files("test_base_folder", ["py"])
|
|
336
351
|
['test4.py', 'test5.py']
|
|
337
352
|
"""
|
|
338
|
-
import os
|
|
339
353
|
|
|
340
354
|
to_delete = get_path_files(path=path, keywords=[keyword])[:-n]
|
|
341
355
|
for file in to_delete:
|
|
@@ -385,7 +399,6 @@ def create_encode_url(url: str, query_params: dict = {}) -> str:
|
|
|
385
399
|
str
|
|
386
400
|
encoded url
|
|
387
401
|
"""
|
|
388
|
-
from urllib.parse import urlencode
|
|
389
402
|
|
|
390
403
|
return f"{url}{urlencode(query_params)}"
|
|
391
404
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import re
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
logger = logging.getLogger(__file__)
|
|
4
|
+
from loguru import logger
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def preprocess(html: str) -> Optional[str]:
|
|
@@ -25,7 +24,6 @@ def preprocess(html: str) -> Optional[str]:
|
|
|
25
24
|
Optional[str]
|
|
26
25
|
cleaned html
|
|
27
26
|
"""
|
|
28
|
-
import re
|
|
29
27
|
|
|
30
28
|
# remove leading and trailing whitespaces
|
|
31
29
|
pattern = re.compile("(^[\s]+)|([\s]+$)", re.MULTILINE)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
|
+
from email.mime.application import MIMEApplication
|
|
3
|
+
from email.mime.multipart import MIMEMultipart
|
|
4
|
+
from email.mime.text import MIMEText
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
logger = logging.getLogger(__file__)
|
|
6
|
+
from loguru import logger
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
def send_aws_ses_email(
|
|
@@ -42,10 +44,6 @@ def send_aws_ses_email(
|
|
|
42
44
|
---------
|
|
43
45
|
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses/client/send_raw_email.html
|
|
44
46
|
"""
|
|
45
|
-
import os
|
|
46
|
-
from email.mime.application import MIMEApplication
|
|
47
|
-
from email.mime.multipart import MIMEMultipart
|
|
48
|
-
from email.mime.text import MIMEText
|
|
49
47
|
|
|
50
48
|
from botocore.exceptions import BotoCoreError, ClientError
|
|
51
49
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
2
|
|
|
3
3
|
from cryptography.fernet import Fernet
|
|
4
|
-
|
|
5
|
-
logging.basicConfig(level=logging.INFO)
|
|
6
|
-
logger = logging.getLogger(__file__)
|
|
4
|
+
from loguru import logger
|
|
7
5
|
|
|
8
6
|
|
|
9
7
|
def generate_fernet_key(output_directory: str, output_filename: str) -> bytes:
|
|
@@ -22,7 +20,6 @@ def generate_fernet_key(output_directory: str, output_filename: str) -> bytes:
|
|
|
22
20
|
bytes
|
|
23
21
|
Fernet key in bytes
|
|
24
22
|
"""
|
|
25
|
-
import os
|
|
26
23
|
|
|
27
24
|
key = None
|
|
28
25
|
if os.path.isdir(output_directory):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
logger = logging.getLogger(__file__)
|
|
4
|
+
from loguru import logger
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def init_django(django_dir: str, project_name: str) -> None:
|
|
@@ -15,8 +15,6 @@ def init_django(django_dir: str, project_name: str) -> None:
|
|
|
15
15
|
project_name : str
|
|
16
16
|
Django project name
|
|
17
17
|
"""
|
|
18
|
-
import os
|
|
19
|
-
import sys
|
|
20
18
|
|
|
21
19
|
import django
|
|
22
20
|
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import subprocess
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
logger = logging.getLogger(__file__)
|
|
3
|
+
from loguru import logger
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
def keytab_valid(
|
|
@@ -24,6 +22,7 @@ def keytab_valid(
|
|
|
24
22
|
subprocess.CompletedProcess
|
|
25
23
|
Subprocess object
|
|
26
24
|
"""
|
|
25
|
+
|
|
27
26
|
output = subprocess.run(
|
|
28
27
|
f"kinit -kt {keytab_filepath} {principal_name}",
|
|
29
28
|
capture_output=True,
|
{data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation/mysql_connector_python_.py
RENAMED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
from typing import Optional, Union
|
|
3
2
|
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
logging.basicConfig(level=logging.INFO)
|
|
7
|
-
logger = logging.getLogger(__file__)
|
|
3
|
+
from loguru import logger
|
|
8
4
|
|
|
9
5
|
|
|
10
6
|
def create_connection(
|
|
@@ -13,7 +9,7 @@ def create_connection(
|
|
|
13
9
|
user: str,
|
|
14
10
|
password: str,
|
|
15
11
|
port=3306,
|
|
16
|
-
)
|
|
12
|
+
):
|
|
17
13
|
"""
|
|
18
14
|
Return MySQL connection
|
|
19
15
|
|
|
@@ -37,6 +33,8 @@ def create_connection(
|
|
|
37
33
|
mysql.connector.connection_cext.CMySQLConnection
|
|
38
34
|
Connection object
|
|
39
35
|
"""
|
|
36
|
+
import mysql.connector
|
|
37
|
+
|
|
40
38
|
connection = None
|
|
41
39
|
try:
|
|
42
40
|
connection = mysql.connector.connect(
|
|
@@ -53,7 +51,7 @@ def create_connection(
|
|
|
53
51
|
|
|
54
52
|
|
|
55
53
|
def execute_query(
|
|
56
|
-
connection
|
|
54
|
+
connection,
|
|
57
55
|
sql_query: str,
|
|
58
56
|
data: Union[dict, tuple],
|
|
59
57
|
commit=True,
|
|
@@ -77,6 +75,8 @@ def execute_query(
|
|
|
77
75
|
Optional[int]
|
|
78
76
|
Query id should be int
|
|
79
77
|
"""
|
|
78
|
+
import mysql.connector
|
|
79
|
+
|
|
80
80
|
cursor = connection.cursor()
|
|
81
81
|
try:
|
|
82
82
|
cursor.execute(sql_query, data)
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import subprocess
|
|
3
2
|
from itertools import combinations
|
|
4
3
|
|
|
5
4
|
import numpy as np
|
|
6
5
|
import pandas as pd
|
|
7
6
|
from IPython.display import display
|
|
8
|
-
|
|
9
|
-
logging.basicConfig(level=logging.INFO)
|
|
10
|
-
logger = logging.getLogger(__file__)
|
|
7
|
+
from loguru import logger
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
# CONFIG
|
|
@@ -23,6 +20,30 @@ def config_pandas_display():
|
|
|
23
20
|
pd.set_option("display.expand_frame_repr", True)
|
|
24
21
|
|
|
25
22
|
|
|
23
|
+
# JUPYTER
|
|
24
|
+
def is_running_in_jupyter():
|
|
25
|
+
"""
|
|
26
|
+
Running in jupyter?
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
bool
|
|
31
|
+
True means running in jupyter env
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
# Check if the IPython module is available
|
|
35
|
+
from IPython import get_ipython
|
|
36
|
+
|
|
37
|
+
# Check if we are in a notebook environment
|
|
38
|
+
if "IPKernelApp" in get_ipython().config:
|
|
39
|
+
return True
|
|
40
|
+
else:
|
|
41
|
+
return False
|
|
42
|
+
# IPython module not found, not running in Jupyter Notebook
|
|
43
|
+
except ImportError:
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
|
|
26
47
|
# COLUMN
|
|
27
48
|
def add_type_columns(dataframe):
|
|
28
49
|
"""
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import math
|
|
2
|
+
import multiprocessing
|
|
3
|
+
import os
|
|
4
|
+
|
|
2
5
|
import pyspark
|
|
3
6
|
import pyspark.sql.functions as F
|
|
4
7
|
|
|
@@ -44,9 +47,6 @@ def config_spark_local(autoset=True):
|
|
|
44
47
|
-------
|
|
45
48
|
None
|
|
46
49
|
"""
|
|
47
|
-
import math
|
|
48
|
-
import multiprocessing
|
|
49
|
-
import os
|
|
50
50
|
|
|
51
51
|
def round_down_or_one(x):
|
|
52
52
|
if math.floor(x) == 0:
|
|
@@ -360,6 +360,7 @@ def group_count(dataframe, columns, n=10):
|
|
|
360
360
|
|
|
361
361
|
Examples
|
|
362
362
|
--------
|
|
363
|
+
>>> import pandas as pd
|
|
363
364
|
>>> data = {'id': [1, 1, 1, 2, 2, 3], 'value': [5, 2, 5, 2135, 124390, 213]}
|
|
364
365
|
>>> df = spark.createDataFrame(pd.DataFrame(data))
|
|
365
366
|
>>> group_count(df, ["id"]).show()
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import smtplib
|
|
3
|
+
from email.mime.multipart import MIMEMultipart
|
|
4
|
+
from email.mime.text import MIMEText
|
|
5
|
+
|
|
6
|
+
|
|
1
7
|
def send_email(
|
|
2
8
|
logname: str,
|
|
3
9
|
message_subject: str,
|
|
@@ -24,10 +30,6 @@ def send_email(
|
|
|
24
30
|
smtp_address: str
|
|
25
31
|
SMTP address
|
|
26
32
|
"""
|
|
27
|
-
import logging
|
|
28
|
-
import smtplib
|
|
29
|
-
from email.mime.multipart import MIMEMultipart
|
|
30
|
-
from email.mime.text import MIMEText
|
|
31
33
|
|
|
32
34
|
if all(
|
|
33
35
|
isinstance(i, str)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: data_manipulation
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.42
|
|
4
4
|
Summary: Powerful data manipulation
|
|
5
5
|
Home-page: https://github.com/shawnngtq/data-manipulation
|
|
6
6
|
Author: Shawn Ng
|
|
@@ -24,7 +24,10 @@ Requires-Dist: boto3
|
|
|
24
24
|
Requires-Dist: django
|
|
25
25
|
Requires-Dist: flask
|
|
26
26
|
Requires-Dist: geopandas
|
|
27
|
+
Requires-Dist: ipython
|
|
28
|
+
Requires-Dist: loguru
|
|
27
29
|
Requires-Dist: mysql-connector-python
|
|
30
|
+
Requires-Dist: numpy
|
|
28
31
|
Requires-Dist: pandas
|
|
29
32
|
Requires-Dist: psycopg
|
|
30
33
|
Requires-Dist: psycopg2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_manipulation-0.40 → data_manipulation-0.42}/data_manipulation.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|