ccfx 1.0.5__py3-none-any.whl → 1.0.7__py3-none-any.whl
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.
- ccfx/ccfx.py +28 -0
- ccfx/sqliteConnection.py +120 -23
- {ccfx-1.0.5.dist-info → ccfx-1.0.7.dist-info}/METADATA +2 -1
- ccfx-1.0.7.dist-info/RECORD +11 -0
- ccfx-1.0.5.dist-info/RECORD +0 -11
- {ccfx-1.0.5.dist-info → ccfx-1.0.7.dist-info}/WHEEL +0 -0
- {ccfx-1.0.5.dist-info → ccfx-1.0.7.dist-info}/licenses/LICENSE +0 -0
- {ccfx-1.0.5.dist-info → ccfx-1.0.7.dist-info}/top_level.txt +0 -0
ccfx/ccfx.py
CHANGED
@@ -37,6 +37,7 @@ from tqdm import tqdm
|
|
37
37
|
import yt_dlp
|
38
38
|
from typing import Optional
|
39
39
|
from datetime import datetime, timedelta
|
40
|
+
from PIL import Image
|
40
41
|
|
41
42
|
# functions
|
42
43
|
def listFiles(path: str, ext: Optional[str] = None) -> list:
|
@@ -1593,6 +1594,33 @@ def showProgress(count: int, end: int, message: str, barLength: int = 100) -> No
|
|
1593
1594
|
print()
|
1594
1595
|
|
1595
1596
|
|
1597
|
+
def dualProgress(primaryCount: int, primaryEnd: int,
|
1598
|
+
secondaryCount: int, secondaryEnd: int,
|
1599
|
+
barLength: int = 40,
|
1600
|
+
message: str = '') -> None:
|
1601
|
+
'''
|
1602
|
+
Draw two full progress bars every frame, overwriting previous frame.
|
1603
|
+
Bars are redrawn entirely each call.
|
1604
|
+
'''
|
1605
|
+
|
1606
|
+
primaryPercent = float(primaryCount / primaryEnd * 100) if primaryEnd > 0 else 100
|
1607
|
+
secondaryPercent = float(secondaryCount / secondaryEnd * 100) if secondaryEnd > 0 else 100
|
1608
|
+
|
1609
|
+
filledPrimary = int(barLength * primaryCount / primaryEnd) if primaryEnd > 0 else barLength
|
1610
|
+
filledSecondary = int((barLength - filledPrimary) * secondaryCount / secondaryEnd) if secondaryEnd > 0 else barLength
|
1611
|
+
|
1612
|
+
startSection = filledPrimary
|
1613
|
+
middleSection = filledSecondary
|
1614
|
+
endSection = barLength - startSection - middleSection
|
1615
|
+
|
1616
|
+
bar = '█' * startSection + '░' * middleSection + '-' * endSection
|
1617
|
+
formattedPrimaryPercent = f'{primaryPercent:03.1f}'
|
1618
|
+
formattedSecondaryPercent = f'{secondaryPercent:03.1f}'
|
1619
|
+
print(f'\r{bar} {formattedPrimaryPercent.rjust(6)}% | {formattedSecondaryPercent.rjust(6)}% | {message} ', end='', flush=True)
|
1620
|
+
if primaryCount == primaryEnd and secondaryCount == secondaryEnd:
|
1621
|
+
print(f'\r{bar} {formattedPrimaryPercent.rjust(6)}% | {formattedSecondaryPercent.rjust(6)}% ', end='', flush=True)
|
1622
|
+
|
1623
|
+
|
1596
1624
|
def listAllFiles(folder, extension="*"):
|
1597
1625
|
list_of_files = []
|
1598
1626
|
# Getting the current work directory (cwd)
|
ccfx/sqliteConnection.py
CHANGED
@@ -17,7 +17,7 @@ import pandas
|
|
17
17
|
|
18
18
|
# classes
|
19
19
|
class sqliteConnection:
|
20
|
-
def __init__(self, sqlite_database, connect = False):
|
20
|
+
def __init__(self, sqlite_database, connect = False) -> None:
|
21
21
|
self.db_name = sqlite_database
|
22
22
|
self.connection = None
|
23
23
|
self.cursor = None
|
@@ -25,13 +25,13 @@ class sqliteConnection:
|
|
25
25
|
if connect:
|
26
26
|
self.connect()
|
27
27
|
|
28
|
-
def connect(self, v=True):
|
28
|
+
def connect(self, v=True) -> None:
|
29
29
|
self.connection = sqlite3.connect(self.db_name)
|
30
30
|
self.cursor = self.connection.cursor()
|
31
31
|
if v:
|
32
32
|
self.report("\t-> connection to " + self.db_name + " established...")
|
33
33
|
|
34
|
-
def updateValue(self, table_name, col_name, new_value, col_where1, val_1, v=False):
|
34
|
+
def updateValue(self, table_name, col_name, new_value, col_where1, val_1, v=False) -> None:
|
35
35
|
"""
|
36
36
|
Updates a single value in a specified table where the condition matches.
|
37
37
|
|
@@ -56,7 +56,7 @@ class sqliteConnection:
|
|
56
56
|
raise Exception(f"Error updating value: {str(e)}")
|
57
57
|
|
58
58
|
|
59
|
-
def createTable(self, table_name, initial_field_name, data_type):
|
59
|
+
def createTable(self, table_name, initial_field_name, data_type) -> None:
|
60
60
|
'''
|
61
61
|
can be text, real, etc
|
62
62
|
'''
|
@@ -67,7 +67,100 @@ class sqliteConnection:
|
|
67
67
|
except:
|
68
68
|
self.report("\t! table exists")
|
69
69
|
|
70
|
-
def
|
70
|
+
def newTable(self, tableName, columnsDict, columnOrder=None, notNull=None, foreignKeys=None) -> None:
|
71
|
+
"""
|
72
|
+
Create a new table based on dictionary of columns and types.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
tableName (str): Name of the table to create
|
76
|
+
columnsDict (dict): Dictionary with column names as keys and data types as values
|
77
|
+
options:
|
78
|
+
INTEGER, REAL, TEXT, BLOB, etc.
|
79
|
+
Example: {'id': 'INTEGER PRIMARY KEY', 'name': 'TEXT', 'age': 'INTEGER'}
|
80
|
+
|
81
|
+
columnOrder (list, optional): List specifying the order of columns
|
82
|
+
Example: ['name', 'age', 'id']
|
83
|
+
|
84
|
+
notNull (list, optional): List of column names that should have NOT NULL constraint
|
85
|
+
Example: ['name', 'age']
|
86
|
+
|
87
|
+
foreignKeys (dict, optional): Dictionary defining foreign key constraints
|
88
|
+
Format Option 1: {currentTableField: {foreignTable: foreignField}, 'onDelete': 'CASCADE'}
|
89
|
+
Format Option 2: {currentTableField: {foreignTable: foreignField, 'onDelete': 'CASCADE'}}
|
90
|
+
|
91
|
+
onDelete options: CASCADE, SET NULL, RESTRICT, NO ACTION, SET DEFAULT
|
92
|
+
Examples:
|
93
|
+
{'user_id': {'users': 'id'}, 'onDelete': 'CASCADE'}
|
94
|
+
{'user_id': {'users': 'id', 'onDelete': 'SET NULL'}}
|
95
|
+
|
96
|
+
"""
|
97
|
+
try:
|
98
|
+
# Determine column order
|
99
|
+
if columnOrder:
|
100
|
+
# Use specified order, but include any columns not in the order list at the end
|
101
|
+
orderedColumns = []
|
102
|
+
for col in columnOrder:
|
103
|
+
if col in columnsDict:
|
104
|
+
orderedColumns.append(col)
|
105
|
+
# Add any remaining columns not in the order list
|
106
|
+
for col in columnsDict:
|
107
|
+
if col not in orderedColumns:
|
108
|
+
orderedColumns.append(col)
|
109
|
+
else:
|
110
|
+
orderedColumns = list(columnsDict.keys())
|
111
|
+
|
112
|
+
# Build column definitions
|
113
|
+
columnDefinitions = []
|
114
|
+
for col in orderedColumns:
|
115
|
+
definition = f"{col} {columnsDict[col]}"
|
116
|
+
|
117
|
+
# Add NOT NULL constraint if specified
|
118
|
+
if notNull and col in notNull:
|
119
|
+
definition += " NOT NULL"
|
120
|
+
|
121
|
+
columnDefinitions.append(definition)
|
122
|
+
|
123
|
+
# Handle foreign key constraints
|
124
|
+
if foreignKeys:
|
125
|
+
onDeleteClause = ""
|
126
|
+
if 'onDelete' in foreignKeys:
|
127
|
+
onDeleteClause = f" ON DELETE {foreignKeys['onDelete']}"
|
128
|
+
|
129
|
+
for currentField, foreignRef in foreignKeys.items():
|
130
|
+
if currentField != 'onDelete': # Skip the onDelete key
|
131
|
+
if isinstance(foreignRef, dict):
|
132
|
+
# Check if onDelete is specified at field level
|
133
|
+
if 'onDelete' in foreignRef:
|
134
|
+
fieldOnDelete = f" ON DELETE {foreignRef['onDelete']}"
|
135
|
+
# Get the actual foreign table and field (skip onDelete key)
|
136
|
+
foreignTable = None
|
137
|
+
foreignField = None
|
138
|
+
for key, value in foreignRef.items():
|
139
|
+
if key != 'onDelete':
|
140
|
+
foreignTable = key
|
141
|
+
foreignField = value
|
142
|
+
break
|
143
|
+
else:
|
144
|
+
# Use global onDelete clause and assume dict format {table: field}
|
145
|
+
fieldOnDelete = onDeleteClause
|
146
|
+
foreignTable = list(foreignRef.keys())[0]
|
147
|
+
foreignField = foreignRef[foreignTable]
|
148
|
+
|
149
|
+
if foreignTable and foreignField:
|
150
|
+
foreignKeyDef = f"FOREIGN KEY ({currentField}) REFERENCES {foreignTable}({foreignField}){fieldOnDelete}"
|
151
|
+
columnDefinitions.append(foreignKeyDef)
|
152
|
+
|
153
|
+
# Create the SQL statement
|
154
|
+
columnsSQL = ', '.join(columnDefinitions)
|
155
|
+
sql = f"CREATE TABLE {tableName} ({columnsSQL})"
|
156
|
+
|
157
|
+
self.cursor.execute(sql)
|
158
|
+
self.report(f"\t-> created table {tableName} in {self.db_name}")
|
159
|
+
|
160
|
+
except Exception as e:
|
161
|
+
self.report(f"\t! error creating table {tableName}: {str(e)}")
|
162
|
+
|
163
|
+
def renameTable(self, old_table_name, new_table_name, v=False) -> None:
|
71
164
|
"""
|
72
165
|
this function gives a new name to an existing table and saves the changes
|
73
166
|
"""
|
@@ -77,7 +170,7 @@ class sqliteConnection:
|
|
77
170
|
self.report("\t-> renamed " + old_table_name + " to " + new_table_name)
|
78
171
|
self.commitChanges()
|
79
172
|
|
80
|
-
def tableExists(self, table_name):
|
173
|
+
def tableExists(self, table_name) -> bool:
|
81
174
|
self.cursor.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='{table_name}'".format(
|
82
175
|
table_name=table_name))
|
83
176
|
if self.cursor.fetchone()[0] == 1:
|
@@ -85,7 +178,7 @@ class sqliteConnection:
|
|
85
178
|
else:
|
86
179
|
return False
|
87
180
|
|
88
|
-
def deleteRows(self, table_to_clean, col_where=None, col_where_value=None, v=False):
|
181
|
+
def deleteRows(self, table_to_clean, col_where=None, col_where_value=None, v=False) -> None:
|
89
182
|
"""
|
90
183
|
|
91
184
|
"""
|
@@ -103,17 +196,17 @@ class sqliteConnection:
|
|
103
196
|
if v:
|
104
197
|
self.report("\t-> removed all rows from " + table_to_clean)
|
105
198
|
|
106
|
-
def deleteTable(self, table_name):
|
199
|
+
def deleteTable(self, table_name) -> None:
|
107
200
|
"""
|
108
201
|
this function deletes the specified table
|
109
202
|
"""
|
110
203
|
self.cursor.execute('''DROP TABLE ''' + table_name)
|
111
204
|
self.report("\t-> deleted table " + table_name + " from " + self.db_name)
|
112
|
-
|
113
|
-
def dropTable(self, table_name):
|
205
|
+
|
206
|
+
def dropTable(self, table_name) -> None:
|
114
207
|
self.deleteTable(table_name)
|
115
208
|
|
116
|
-
def undoChanges(self):
|
209
|
+
def undoChanges(self) -> None:
|
117
210
|
"""
|
118
211
|
This function reverts the database to status before last commit
|
119
212
|
"""
|
@@ -121,7 +214,7 @@ class sqliteConnection:
|
|
121
214
|
self.connection.rollback()
|
122
215
|
self.commitChanges()
|
123
216
|
|
124
|
-
def readTableAsDict(self, table_name, key_column = 'id'):
|
217
|
+
def readTableAsDict(self, table_name, key_column: str = 'id') -> dict:
|
125
218
|
# Execute a SQL query to fetch all rows from your table
|
126
219
|
self.cursor = self.connection.execute(f"SELECT * FROM {table_name}")
|
127
220
|
|
@@ -134,7 +227,7 @@ class sqliteConnection:
|
|
134
227
|
|
135
228
|
return data
|
136
229
|
|
137
|
-
def getColumnsWithTypes(self, table_name):
|
230
|
+
def getColumnsWithTypes(self, table_name) -> dict:
|
138
231
|
c = self.cursor
|
139
232
|
|
140
233
|
# Prepare and execute a PRAGMA table_info statement
|
@@ -145,7 +238,7 @@ class sqliteConnection:
|
|
145
238
|
|
146
239
|
return columns_with_types
|
147
240
|
|
148
|
-
def insertDictPartial(self, table_name, data_dict):
|
241
|
+
def insertDictPartial(self, table_name, data_dict) -> None:
|
149
242
|
c = self.cursor
|
150
243
|
|
151
244
|
# Get the column names from the table
|
@@ -168,7 +261,7 @@ class sqliteConnection:
|
|
168
261
|
self.commitChanges()
|
169
262
|
|
170
263
|
|
171
|
-
def report(self, string, printing=False):
|
264
|
+
def report(self, string, printing=False) -> None:
|
172
265
|
if printing:
|
173
266
|
print(f"\t> {string}")
|
174
267
|
else:
|
@@ -176,7 +269,7 @@ class sqliteConnection:
|
|
176
269
|
sys.stdout.flush()
|
177
270
|
|
178
271
|
|
179
|
-
def createTableFromDict(self, table_name, columns_with_types):
|
272
|
+
def createTableFromDict(self, table_name, columns_with_types) -> None:
|
180
273
|
|
181
274
|
# Prepare a CREATE TABLE statement
|
182
275
|
fields = ', '.join(f'{column} {data_type}' for column, data_type in columns_with_types.items())
|
@@ -187,7 +280,7 @@ class sqliteConnection:
|
|
187
280
|
self.commitChanges()
|
188
281
|
|
189
282
|
|
190
|
-
def insertDict(self, table_name, data):
|
283
|
+
def insertDict(self, table_name, data) -> None:
|
191
284
|
|
192
285
|
# Prepare an INSERT INTO statement for each dictionary
|
193
286
|
for id, row in data.items():
|
@@ -204,7 +297,7 @@ class sqliteConnection:
|
|
204
297
|
|
205
298
|
|
206
299
|
|
207
|
-
def readTableColumns(self, table_name, column_list="all"):
|
300
|
+
def readTableColumns(self, table_name, column_list="all") -> list:
|
208
301
|
"""
|
209
302
|
this function takes a list to be a string separated by commmas and
|
210
303
|
a table and puts the columns in the table into a variable
|
@@ -225,7 +318,7 @@ class sqliteConnection:
|
|
225
318
|
self.report("\t-> read selected table columns from " + table_name)
|
226
319
|
return list_of_tuples
|
227
320
|
|
228
|
-
def insertField(self, table_name, field_name, data_type, to_new_line=False, messages=True):
|
321
|
+
def insertField(self, table_name, field_name, data_type, to_new_line=False, messages=True) -> None:
|
229
322
|
"""
|
230
323
|
This will insert a new field into your sqlite database
|
231
324
|
|
@@ -244,7 +337,7 @@ class sqliteConnection:
|
|
244
337
|
"\r\t-> inserted into table {0} field {1} ".format(table_name, field_name))
|
245
338
|
sys.stdout.flush()
|
246
339
|
|
247
|
-
def insertRow(self, table_name, ordered_content_list = [], dictionary_obj = {}, messages=False):
|
340
|
+
def insertRow(self, table_name, ordered_content_list = [], dictionary_obj = {}, messages=False) -> None:
|
248
341
|
"""
|
249
342
|
ordered_list such as ['ha','he','hi']
|
250
343
|
list should have data as strings
|
@@ -263,7 +356,7 @@ class sqliteConnection:
|
|
263
356
|
if messages:
|
264
357
|
self.report("\t-> inserted row into " + table_name)
|
265
358
|
|
266
|
-
def insertRows(self, table_name, list_of_tuples, messages=False):
|
359
|
+
def insertRows(self, table_name, list_of_tuples, messages=False) -> None:
|
267
360
|
"""
|
268
361
|
list_of_tuples such as [('ha','he','hi')'
|
269
362
|
('ha','he','hi')]
|
@@ -274,7 +367,7 @@ class sqliteConnection:
|
|
274
367
|
if messages:
|
275
368
|
self.report("\t-> inserted rows into " + table_name)
|
276
369
|
|
277
|
-
def dumpCSV(self, table_name, file_name, index=False, v=False):
|
370
|
+
def dumpCSV(self, table_name, file_name, index=False, v=False) -> None:
|
278
371
|
'''
|
279
372
|
save table to csv
|
280
373
|
'''
|
@@ -300,7 +393,11 @@ class sqliteConnection:
|
|
300
393
|
self.report(
|
301
394
|
"\t-> saved {0} changes to ".format(number_of_changes) + self.db_name)
|
302
395
|
|
303
|
-
def
|
396
|
+
def commit(self, v=False) -> None:
|
397
|
+
'''proxy to commitChanges'''
|
398
|
+
self.commitChanges(v)
|
399
|
+
|
400
|
+
def closeConnection(self, commit=True) -> None:
|
304
401
|
'''
|
305
402
|
disconnects from the database
|
306
403
|
'''
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ccfx
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.7
|
4
4
|
Summary: This package simplifies regular common actions for quick prototyping in a user friendly way
|
5
5
|
Author-email: Celray James CHAWANDA <celray@chawanda.com>
|
6
6
|
License-Expression: MIT
|
@@ -25,6 +25,7 @@ Requires-Dist: py7zr
|
|
25
25
|
Requires-Dist: mutagen
|
26
26
|
Requires-Dist: requests
|
27
27
|
Requires-Dist: tqdm
|
28
|
+
Requires-Dist: pillow
|
28
29
|
Dynamic: license-file
|
29
30
|
|
30
31
|
# ccfx
|
@@ -0,0 +1,11 @@
|
|
1
|
+
ccfx/__init__.py,sha256=UK62VcGS84SJyGVg1bK4FltZj7OkpdoyhoFWeXcKsX0,144
|
2
|
+
ccfx/ccfx.py,sha256=xXIUnZT2h7wbFwomnvE6SfKK9f-kxbYBViZCWDiOXCU,76230
|
3
|
+
ccfx/excel.py,sha256=vm_cm4huKKx4_Nstr5neJzhBLmoZjg8qxjzz4hcF5hg,4754
|
4
|
+
ccfx/mssqlConnection.py,sha256=C3HxzgZHmHy_de9EbMaXzR8NrkJxwHc8a00qzxQu_gs,8984
|
5
|
+
ccfx/sqliteConnection.py,sha256=pOT9BBEAcm2kmoS0yBkUi4m9srQVe62J4xG5bnddvis,16207
|
6
|
+
ccfx/word.py,sha256=AGa64jX5Zl5qotZh5L0QmrsjTnktIBhmj_ByRKZ88vw,3061
|
7
|
+
ccfx-1.0.7.dist-info/licenses/LICENSE,sha256=EuxaawJg_OOCLfikkCGgfXPZmxR-x_5PH7_2e9M-3eA,1099
|
8
|
+
ccfx-1.0.7.dist-info/METADATA,sha256=xYz28mGhcj0RjcOhkdbcrVuSy1ywKa-7Ty5IJWMm_go,11282
|
9
|
+
ccfx-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
10
|
+
ccfx-1.0.7.dist-info/top_level.txt,sha256=_cSvSA1WX2K8TgoV3iBJUdUZZqMKJbOPLNnKLYSLHaw,5
|
11
|
+
ccfx-1.0.7.dist-info/RECORD,,
|
ccfx-1.0.5.dist-info/RECORD
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
ccfx/__init__.py,sha256=UK62VcGS84SJyGVg1bK4FltZj7OkpdoyhoFWeXcKsX0,144
|
2
|
-
ccfx/ccfx.py,sha256=PuukzvGKeuaZg-09gC_EVEqqL60snOhOs29-ld780Bk,74774
|
3
|
-
ccfx/excel.py,sha256=vm_cm4huKKx4_Nstr5neJzhBLmoZjg8qxjzz4hcF5hg,4754
|
4
|
-
ccfx/mssqlConnection.py,sha256=C3HxzgZHmHy_de9EbMaXzR8NrkJxwHc8a00qzxQu_gs,8984
|
5
|
-
ccfx/sqliteConnection.py,sha256=jEJ94D5ySt84N7AeDpa27Rclt1NaKhkX6nYzidwApIg,11104
|
6
|
-
ccfx/word.py,sha256=AGa64jX5Zl5qotZh5L0QmrsjTnktIBhmj_ByRKZ88vw,3061
|
7
|
-
ccfx-1.0.5.dist-info/licenses/LICENSE,sha256=EuxaawJg_OOCLfikkCGgfXPZmxR-x_5PH7_2e9M-3eA,1099
|
8
|
-
ccfx-1.0.5.dist-info/METADATA,sha256=ZDKztXjB8snaimpN1MY6-1TN6_6w1F9LanS7xHp_eRM,11260
|
9
|
-
ccfx-1.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
10
|
-
ccfx-1.0.5.dist-info/top_level.txt,sha256=_cSvSA1WX2K8TgoV3iBJUdUZZqMKJbOPLNnKLYSLHaw,5
|
11
|
-
ccfx-1.0.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|