-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path__init__.py
More file actions
778 lines (606 loc) · 23.2 KB
/
__init__.py
File metadata and controls
778 lines (606 loc) · 23.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# JSON.py
# Import some useful modules
import os
import datetime
import json
import inspect
class JSON():
def __init__(self):
# Import the classes
self.Import_Classes()
# Define the folders of the module
self.folders = self.Define_Folders(object = self, create_texts = False).folders
# Define the "Switches" dictionary
self.Define_Switches()
# Define the module texts
self.Define_Texts()
def Import_Classes(self):
import importlib
# ---------- #
# Define the list of modules to be imported
modules = [
"Define_Folders",
"Global_Switches",
"Language"
]
# Iterate through the list of modules
for module_title in modules:
# Import the module
module = importlib.import_module("." + module_title, "Utility")
# Get the sub-class
sub_class = getattr(module, module_title)
# If the module title is not "Define_Folders"
if module_title != "Define_Folders":
# Run the sub-class to define its variable
sub_class = sub_class()
# Add the sub-class to the current class
setattr(self, module_title, sub_class)
def Define_Switches(self):
# Get the "Switches" dictionary from the "Global_Switches" module
self.switches = self.Global_Switches.switches["Global"]
# Update the "Switches" dictionary, adding the "File" dictionary
self.switches.update({
"File": {
"Create": True,
"Edit": True
}
})
# If the "Testing" switch is True
if self.switches["Testing"] == True:
# Iterate through the switches inside the "File" dictionary
for switch in self.switches["File"]:
# Define them as False
self.switches["File"][switch] = False
def Define_Texts(self):
# Define the "Date" utility dictionary
self.folders["Apps"]["Module files"]["Utility"]["Date"] = {
"Texts": self.folders["Apps"]["Module files"]["Utility"]["root"] + "Date/Texts.json"
}
# Define the "Date texts" text dictionary
self.date_texts = self.To_Python(self.folders["Apps"]["Module files"]["Utility"]["Date"]["Texts"])
def Sanitize(self, path):
# Replace double backwards slashes with one forward slash
path = os.path.normpath(path).replace("\\", "/")
# If there is no forward slash in the path
# And the last character returned by the "splittext" method is an empty string
if (
"/" not in path[-1] and
os.path.splitext(path)[-1] == ""
):
# Add a forward slash to the end of the path
path += "/"
# Return the path
return path
def Verbose(self, text, item, verbose = None):
# If the "Verbose" switch is True
# And the verbose parameter is None
# Or the verbose parameter is True
if (
self.switches["Verbose"] == True and
verbose == None or
verbose == True
):
# Get the name of the method which ran this method (the "Verbose" one)
runner_method_name = inspect.stack()[1][3]
# Show the module name (JSON) and the method which ran this method (the "Verbose" one)
print()
print(self.module["Name"] + "." + runner_method_name + "():")
# Show the verbose text
print("\t" + text + ":")
# Show the verbose item
print("\t" + item)
def File_Exists(self, file):
# Sanitize the file path
file = self.Sanitize(file)
# Checks if the file exists and returns the boolean
return os.path.isfile(file)
def File_Open(self, file, mode = "r", encoding = "UTF8"):
# Open the file with the mode and encoding
return open(file, mode, encoding = encoding)
def File_Contents(self, file):
# Sanitize the file path
file = self.Sanitize(file)
# Define the contents dictionary
contents = {
"Lines": [],
"String": "",
"Size": 0,
"Length": 0
}
# If the file exists
if self.File_Exists(file) == True:
# Open the file handle in read mode (the default mode)
file_handle = self.File_Open(file)
# Iterate through the lines inside the file
for line in file_handle.readlines():
# Remove the line break from the line
line = line.replace("\n", "")
# Add the line to the list of lines
contents["Lines"].append(line)
# Reset cursor to the beginning of the file before getting the file string
file_handle.seek(0)
# Read the file and get its string
contents["String"] = file_handle.read()
# Close the file handle
file_handle.close()
# Get the size of the file
contents["Size"] = os.path.getsize(file)
# Get the length of the file
contents["Length"] = len(contents["Lines"])
# If the file does not exist
if self.File_Exists(file) == False:
# Show the verbose text saying that the file does not exist
self.Verbose(self.Language.language_texts["this_file_does_not_exists"], file)
# Return the contents dictionary
return contents
def Edit(self, file, text, next_line = True, verbose = None, full_verbose = False, edit = False):
# Sanitize the file path
file = self.Sanitize(file)
# Get the contents of the file
contents = self.File_Contents(file)
# Transform the text into the JSON format
text = self.From_Python(text)
# Get the verbose text for the file
verbose_text = self.Language.Check_Text_Difference(contents, text, full_verbose = full_verbose)
# Define the file text as the file plus two line breaks, one tab, and the verbose text
file_text = file + "\n" + \
"\n" + \
"\t" + verbose_text
# If the file exists
if self.File_Exists(file) == True:
# If the file "Edit" switch is True
# Or the edit parameter is True
if (
self.switches["File"]["Edit"] == True or
edit == True
):
# If the file text string is not equal to the parameter text
if contents["String"] != text:
# Open the file handle in write mode
edit = self.File_Open(file, "w")
# Write the text into the file
edit.write(text)
# Close the file handle
edit.close()
# Define the show text to tell the user that the file was edited
show_text = self.Language.language_texts["file, title()"] + " " + self.Language.language_texts["edited, masculine"]
# If the file "Edit" switch is False
# And the "edit" parameter is False
if (
self.switches["File"]["Edit"] == False and
edit == False
):
# Define the show text to tell the user that it was not possible to edit the file due to lack of permissions
show_text = self.Language.language_texts["it_was_not_possible_to_{}_the_file_permission_not_granted"].format(self.Language.language_texts["edit"])
# If the file text string is not equal to the parameter text
if contents["String"] != text:
# Show the verbose text
self.Verbose(show_text, file_text, verbose = verbose)
# If the file "Edit" switch is True
# And the "edit" parameter is True
if (
self.switches["File"]["Edit"] == True or
edit == True
):
return True
# If the file "Edit" switch is False
# And the "edit" parameter is False
if (
self.switches["File"]["Edit"] == False and
edit == False
):
return False
# If the file does not exist
if self.File_Exists(file) == False:
# Show the verbose text to tell the user that the file does not exist and return False
self.Verbose(self.Language.language_texts["this_file_does_not_exists"], file_text, verbose = verbose)
return False
def Dumps(self, items):
# Dump the items
items = json.dumps(items, indent = "\t", ensure_ascii = False)
# Return the items
return items
def From_Python(self, items, testing = False):
# Import some useful modules
from copy import deepcopy
import types
# If the items parameter is a dictionary
if type(items) == dict:
# Convert it into a dictionary using the "dict" function
items = dict(items)
# Iterate through the keys and values of the items dictionary
for key, value in items.items():
# If the type name of the value is either "Credentials" or "Resource"
# Or it is not a number, a dictionary, or a list
if (
type(value).__name__ in ["Credentials", "Resource"] or
type(value) not in [int, dict, list]
):
# Convert it to a string
items[key] = str(value)
# Get the name of the method which ran this method (the "From_Python" one)
runner_method_name = inspect.stack()[1][3]
# If the value is a dictionary
# And the runner method is "Show"
# And the local testing switch is True
if (
type(value) == dict and
runner_method_name == "Show" and
testing == True
):
# Convert the objects of the value into strings
value = self.Convert_Objects(value)
# Update the value inside the root dictionary
items[key] = value
# Make a copy of the items parameter
items_copy = deepcopy(items)
# If the items parameter is a datetime object
if self.Is_Datetime(items_copy) == True:
# Convert it into a list with the first item being the items converted into a date string
items_copy = [
self.Date_To_String(items_copy)
]
# If the items parameter is a dictionary
if type(items_copy) == dict:
# Iterate through its keys and values
for key, value in items_copy.items():
# Check the value for a datetime to convert it correctly
value = self.Check_Datetime(value)
# Update the value inside the root dictionary
items_copy[key] = value
# If the value is a dictionary
if type(value) == dict:
# Iterate through its sub-keys and sub-values
for sub_key, sub_value in value.items():
# Check the sub-value for a datetime to convert it correctly
sub_value = self.Check_Datetime(sub_value)
# Update the sub-value inside the root dictionary
value[sub_key] = sub_value
# If the sub-value is a dictionary
if type(sub_value) == dict:
# Iterate through its sub-sub-keys and sub-sub-values
for sub_sub_key, sub_sub_value in sub_value.items():
# Check the sub-sub-value for a datetime to convert it correctly
sub_sub_value = self.Check_Datetime(sub_sub_value)
# If the sub-sub-value is a dictionary
if type(sub_sub_value) == dict:
# Iterate through its sub-sub-sub-keys and sub-sub-sub-values
for sub_sub_sub_key, sub_sub_sub_value in sub_sub_value.items():
# Check the sub-sub-sub-value for a datetime to convert it correctly
sub_sub_sub_value = self.Check_Datetime(sub_sub_sub_value)
# If the sub-sub-sub-value is a dictionary
if type(sub_sub_sub_value) == dict:
# Iterate through its sub-sub-sub-sub-keys and sub-sub-sub-values
for sub_sub_sub_sub_key, sub_sub_sub_sub_value in sub_sub_sub_value.items():
# Check the sub-sub-sub-sub-value for a datetime to convert it correctly
sub_sub_sub_sub_value = self.Check_Datetime(sub_sub_sub_sub_value)
# Update the sub-sub-sub-value inside the root dictionary
sub_sub_sub_value[sub_sub_sub_sub_key] = sub_sub_sub_sub_value
# Update the sub-sub-sub-value inside the root dictionary
sub_sub_value[sub_sub_sub_key] = sub_sub_sub_value
# Update the sub-sub-value inside the root dictionary
sub_value[sub_sub_key] = sub_sub_value
# Update the sub-value inside the root dictionary
value[sub_key] = sub_value
# Update the value inside the root dictionary
items_copy[key] = value
# If the items parameter is a list
if type(items_copy) == list:
# Iterate through the items in the list
i = 0
for item in items_copy:
# If the item is not a datetime object, convert it into a date string
if self.Is_Datetime(item) == True:
item = self.Date_To_String(item)
# If not, convert it into a string
else:
item = str(item)
# Update the item in the root list
items_copy[i] = item
# Add one to the "i" number
i += 1
# If the items parameter is a string
if type(items_copy) == str:
# Convert it into a Python object
items_copy = self.To_Python(items_copy)
# Dump the items
items_copy = self.Dumps(items_copy)
# Return the items dictionary
return items_copy
def Is_Datetime(self, item):
# Return the boolean saying if the item is a datetime or time object or not
return isinstance(item, (datetime.datetime, datetime.time))
def Check_Datetime(self, item):
# If the "_PytzShimTimezone" string is present in the item, convert it into a string
if "_PytzShimTimezone" in str(item):
item = str(item)
# If the value is not a string, number, list, dictionary, boolean, or None
if type(item) not in [str, int, list, dict, bool, None]:
# If the item is not a datetime object, convert it into a string
if self.Is_Datetime(item) == False:
item = str(item)
# If it is, convert it into a date string
if self.Is_Datetime(item) == True:
item = self.Date_To_String(item)
# Return the item
return item
def Date_To_String(self, date, format = ""):
# If the item is not a datetime object, get the datetime object from the "Object" key
if self.Is_Datetime(date) == False:
date = date["Object"]
# If the date format is empty
if format == "":
# Get the default date format
format = self.date_texts["default_format"]
# If the timezone is "UTC"
if date.strftime("%Z") == "UTC":
# Add the "Z" to the format
format += "Z"
# If not, add the timezone character
else:
format += "%z"
# Convert the datetime object into a string using the defined format and return it
return date.strftime(format)
def Convert_Objects(self, value):
# Iterate through its sub-keys and sub-values
for sub_key, sub_value in value.items():
# Get the type name of the sub-value
type_name = type(sub_value).__name__
# If the sub-value is a module, function, class, or method
if type_name in ["module", "function", "type", "method"]:
# Convert it into a string
sub_value = str(sub_value)
# Update the sub-value inside the root dictionary
value[sub_key] = sub_value
# If the sub-value is a dictionary
if type(sub_value) == dict:
# Iterate through its sub-sub-keys and sub-sub-values
for sub_sub_key, sub_sub_value in sub_value.items():
# Get the type name of the sub-sub-value
type_name = type(sub_sub_value).__name__
# If it is a module
if type_name == "module":
# Get the root module
root_module = sub_sub_value.__name__.split(".")[0]
# Get the module
module = sub_sub_value.__name__.split(".")[1]
# Define the sub-sub-value as the root module plus the module
sub_sub_value = str(root_module) + "." + str(module)
# If it is a type (class)
if type_name == "type":
# Get the module of the class
module = str(sub_sub_value.__module__).split(".")[0]
# Get the name of the class
class_name = str(sub_sub_value.__module__).split(".")[-1]
# Define the sub-module as the class name
sub_module = class_name
# Define the sub-sub-value as the three variables above added together
sub_sub_value = str(module) + "." + str(sub_module) + "." + str(class_name) + "()"
# If the sub-sub-value is a dictionary
if type(sub_sub_value) == dict:
for sub_sub_sub_key, sub_sub_sub_value in sub_sub_value.items():
# Make a copy of the original sub-sub-value
sub_sub_value = sub_sub_value.copy()
# Get the type name of the sub-sub-sub-value
type_name = type(sub_sub_sub_value).__name__
# If the sub-sub-sub-value is a module, function, class, or method
if type_name in ["module", "function", "type", "method"]:
# If it is a module
if type_name == "module":
# Get the root module
root_module = sub_sub_sub_value.__name__.split(".")[0]
# Get the module
module = sub_sub_sub_value.__name__.split(".")[1]
# Define the sub-sub-value as the root module plus the module
sub_sub_sub_value = str(root_module) + "." + str(module)
# If it is a method
if type_name == "method":
# Get its class
method_class = sub_sub_sub_value.__self__.__class__
# Get the module of the class
module = method_class.__module__.split(".")[0]
# Get the name of the class
method_class = method_class.__name__
# Get the method name
method_name = sub_sub_sub_value.__name__
# Define the sub-sub-sub-value as the two variables above added together
sub_sub_sub_value = str(module) + "." + str(method_class) + "." + str(method_name) + "()"
# Convert it into a string
sub_sub_sub_value = str(sub_sub_sub_value)
# Update the sub-sub-sub-value inside the root dictionary
sub_sub_value[sub_sub_sub_key] = sub_sub_sub_value
# Update the sub-sub-value inside the root dictionary
sub_value[sub_sub_key] = sub_sub_value
# Update the sub-value inside the root dictionary
value[sub_key] = sub_value
# Return the value
return value
def To_Python(self, item):
# If the item is a file
if self.File_Exists(item) == True:
# Sanitize the file path
item = self.Sanitize(item)
# Convert the file text into a Python dictionary
dictionary = json.load(open(item, encoding = "utf8"))
# If the item is not a file
if self.File_Exists(item) == False:
# Convert the JSON dictionary into a Python dictionary
dictionary = json.loads(item)
# Return the Python dictionary
return dictionary
def Show(self, json, return_text = False, testing = False):
# Convert the JSON from Python to JSON text
json = self.From_Python(json, testing = testing)
# If the "return text" parameter is False, show the text
if return_text == False:
print(json)
# If it is True, return the text
if return_text == True:
return json
def Copy(self, json):
# Convert the JSON from Python to JSON text
text = self.From_Python(json)
# Import the "pyperclip" module
import pyperclip
# Copy the JSON
pyperclip.copy(text)
# Show the verbose text about the copied text
# (Never show it because the JSON dictionaries are frequently extensive)
self.Verbose(self.Language.language_texts["copied_text"], "[" + text + "]", verbose = False)
def Add_Key_After_Key(self, dictionary, key_value, after_key = None, number_to_add = 1, add_to_end = False, remove_after_key = False):
# List the keys and values of the parameter dictionary
keys = list(dictionary.keys())
values = list(dictionary.values())
# If the key-value is a string
if type(key_value) == str:
# Define the key as the key-value and the value as the dictionary value in the "after key" key
key_value = {
"key": key_value,
"value": dictionary[after_key]
}
# If the "key" key is not inside the key-value dictionary
if "key" not in key_value:
# Define the key as the first key in the key-value dictionary
key_value["key"] = list(key_value.keys())[0]
# Define the value as the first value in the key-value dictionary
key_value["value"] = list(key_value.values())[0]
# Define a local key number
key_number = 0
# Iterate through the list of keys
for key in keys.copy():
# If the key-value key is not inside the list of keys
# And the current key is the after key
# Or the "add to end" parameter is True
if (
key_value["key"] not in keys and
key == after_key or
add_to_end == True
):
# If the "add to end" parameter is True
if add_to_end == True:
# Define the local number as the number of keys
number = len(keys)
# Else, define it as the key number plus the number to add
else:
number = key_number + number_to_add
# Add the key-value key to the list of keys in the number index
keys.insert(number, key_value["key"])
# Add the key-value value to the list of values in the number index
values.insert(number, key_value["value"])
# If the key-value key is inside the list of keys
# And the current key is the key-value key
if (
key_value["key"] in keys and
key == key_value["key"]
):
# Add the key-value value to the list of values in the key number index
values[key_number] = key_value["value"]
# Add one to the key number
key_number += 1
# Re-create the local dictionary with the lists of keys and values
dictionary = dict(zip(keys, values))
# If the "remove after key" parameter is True
if remove_after_key == True:
# Remove the after key
dictionary.pop(after_key)
# Return the dictionary with the keys and values changed
return dictionary
def Find_Key(self, dictionary, value_to_find):
# Iterate through the keys and values of the dictionary
for key, value in dictionary:
# If the value is equal to the value to find
if value == value_to_find:
# Define the found key as the current key
found_key = key
# Break the loop when the key is found
break
# Return the found key
return found_key
def List_Has_Only_Numbers(self, items):
return all(isinstance(item, int) for item in items)
def Add_To_End_Of_Dictionary(self, dictionary, to_add):
# List the keys of the items dictionary
keys = list(dictionary.keys())
# Create a copy of the list
keys_copy = keys.copy()
# Remove the keys
for key in to_add:
# If the key exists inside the copy of the list
if key in keys_copy:
# Remove it
keys.remove(key)
# Add them to the end
for key in to_add:
# If the key exists inside the copy of the list
if key in keys_copy:
# Add it
keys.append(key)
# Sort the dictionary keys using the updated order
dictionary = self.Sort_Item_List(dictionary, order = keys)
# Return the dictionary
return dictionary
def Sort_Item_List(self, items, order):
# Define the new items as an empty dictionary
new_items = {}
# If the items is a list
if type(items) == list:
# Update it to be an empty list
new_items = []
# If the items is a dictionary
if type(items) == dict:
# List the keys and values
keys = list(items.keys())
values = list(items.values())
# If the order is a list of only numbers
if self.List_Has_Only_Numbers(order) == True:
# Iterate through the orders
i = 0
for item in order.copy():
# Remove one from the order number to make it access the list correcly (starting from zero)
item -= 1
# Update the order in the list
order[i] = item
# Add one to the "i" number
i += 1
# Iterate through the items in the order list
i = 0
for item in order:
# If the items is a dictionary
if type(items) == dict:
# If the item is a string
if type(item) == str:
# Get the value from the dictionary of items
value = items[item]
# Add the key and value to the new dictionary of items
new_items[item] = value
# If the item is a number
if type(item) == int:
# Get the key and value from their respective lists
key = keys[item]
value = values[item]
# Add the key and value to the new dictionary of items
new_items[key] = value
# If the items is a list
if type(items) == list:
# Get the value from the items list
value = items[i]
# If the order is a list of only numbers
if self.List_Has_Only_Numbers(order) == True:
# Get the value from the items list using the order
value = items[item]
# Add the key and value to the new list of items
new_items.append(value)
# Add it to the "i" number
i += 1
# Return the new items list
return new_items
def Remove_Duplicates_From_List(self, items):
# Define the new items list
new_items = []
# Iterate through the items inside the original list
for item in items:
# If the item is not present in the new items list
if item not in new_items:
new_items.append(item)
# Return the new items list
return new_items