osbot-utils 1.7.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.
- osbot_utils/__init__.py +1 -0
- osbot_utils/base_classes/Cache_Pickle.py +129 -0
- osbot_utils/base_classes/Kwargs_To_Disk.py +27 -0
- osbot_utils/base_classes/Kwargs_To_Self.py +308 -0
- osbot_utils/base_classes/Type_Safe__List.py +14 -0
- osbot_utils/base_classes/__init__.py +0 -0
- osbot_utils/context_managers/__init__.py +0 -0
- osbot_utils/context_managers/capture_duration.py +33 -0
- osbot_utils/decorators/__init__.py +0 -0
- osbot_utils/decorators/classes/__init__.py +0 -0
- osbot_utils/decorators/classes/singleton.py +9 -0
- osbot_utils/decorators/lists/__init__.py +0 -0
- osbot_utils/decorators/lists/filter_list.py +12 -0
- osbot_utils/decorators/lists/group_by.py +21 -0
- osbot_utils/decorators/lists/index_by.py +27 -0
- osbot_utils/decorators/methods/__init__.py +0 -0
- osbot_utils/decorators/methods/cache.py +19 -0
- osbot_utils/decorators/methods/cache_on_function.py +56 -0
- osbot_utils/decorators/methods/cache_on_self.py +78 -0
- osbot_utils/decorators/methods/cache_on_tmp.py +71 -0
- osbot_utils/decorators/methods/capture_exception.py +37 -0
- osbot_utils/decorators/methods/capture_status.py +20 -0
- osbot_utils/decorators/methods/catch.py +13 -0
- osbot_utils/decorators/methods/context.py +11 -0
- osbot_utils/decorators/methods/depreciated.py +79 -0
- osbot_utils/decorators/methods/function_type_check.py +62 -0
- osbot_utils/decorators/methods/obj_as_context.py +6 -0
- osbot_utils/decorators/methods/remove_return_value.py +22 -0
- osbot_utils/decorators/methods/required_fields.py +19 -0
- osbot_utils/fluent/Fluent_Dict.py +19 -0
- osbot_utils/fluent/Fluent_List.py +44 -0
- osbot_utils/fluent/__init__.py +1 -0
- osbot_utils/graphs/__init__.py +0 -0
- osbot_utils/graphs/mermaid/Mermaid.py +75 -0
- osbot_utils/graphs/mermaid/Mermaid__Edge.py +49 -0
- osbot_utils/graphs/mermaid/Mermaid__Graph.py +93 -0
- osbot_utils/graphs/mermaid/Mermaid__Node.py +69 -0
- osbot_utils/graphs/mermaid/Mermaid__Renderer.py +54 -0
- osbot_utils/graphs/mermaid/configs/Mermaid__Edge__Config.py +7 -0
- osbot_utils/graphs/mermaid/configs/Mermaid__Node__Config.py +9 -0
- osbot_utils/graphs/mermaid/configs/Mermaid__Render__Config.py +7 -0
- osbot_utils/graphs/mermaid/examples/Mermaid_Examples__FlowChart.py +98 -0
- osbot_utils/graphs/mermaid/models/Mermaid__Diagram_Direction.py +9 -0
- osbot_utils/graphs/mermaid/models/Mermaid__Diagram__Type.py +17 -0
- osbot_utils/graphs/mermaid/models/Mermaid__Node__Shape.py +30 -0
- osbot_utils/graphs/mgraph/MGraph.py +53 -0
- osbot_utils/graphs/mgraph/MGraph__Config.py +7 -0
- osbot_utils/graphs/mgraph/MGraph__Data.py +139 -0
- osbot_utils/graphs/mgraph/MGraph__Edge.py +27 -0
- osbot_utils/graphs/mgraph/MGraph__Node.py +33 -0
- osbot_utils/graphs/mgraph/MGraph__Random_Graphs.py +27 -0
- osbot_utils/graphs/mgraph/MGraph__Serializer.py +43 -0
- osbot_utils/graphs/mgraph/MGraphs.py +17 -0
- osbot_utils/graphs/mgraph/__init__.py +0 -0
- osbot_utils/helpers/CPrint.py +98 -0
- osbot_utils/helpers/Dict_To_Attr.py +7 -0
- osbot_utils/helpers/Local_Cache.py +111 -0
- osbot_utils/helpers/Local_Caches.py +54 -0
- osbot_utils/helpers/Print_Table.py +369 -0
- osbot_utils/helpers/Python_Audit.py +45 -0
- osbot_utils/helpers/Random_Seed.py +27 -0
- osbot_utils/helpers/SCP.py +58 -0
- osbot_utils/helpers/SSH.py +151 -0
- osbot_utils/helpers/Type_Registry.py +16 -0
- osbot_utils/helpers/__init__.py +0 -0
- osbot_utils/helpers/ast/Ast.py +35 -0
- osbot_utils/helpers/ast/Ast_Base.py +124 -0
- osbot_utils/helpers/ast/Ast_Data.py +28 -0
- osbot_utils/helpers/ast/Ast_Load.py +62 -0
- osbot_utils/helpers/ast/Ast_Merge.py +26 -0
- osbot_utils/helpers/ast/Ast_Node.py +117 -0
- osbot_utils/helpers/ast/Ast_Visit.py +85 -0
- osbot_utils/helpers/ast/Call_Tree.py +38 -0
- osbot_utils/helpers/ast/__init__.py +145 -0
- osbot_utils/helpers/ast/nodes/Ast_Add.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Alias.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_And.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Argument.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Arguments.py +10 -0
- osbot_utils/helpers/ast/nodes/Ast_Assert.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Assign.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Attribute.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Aug_Assign.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Bin_Op.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Bool_Op.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Break.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Call.py +17 -0
- osbot_utils/helpers/ast/nodes/Ast_Class_Def.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Compare.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Comprehension.py +10 -0
- osbot_utils/helpers/ast/nodes/Ast_Constant.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Continue.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Dict.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Eq.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Except_Handler.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Expr.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_For.py +10 -0
- osbot_utils/helpers/ast/nodes/Ast_Function_Def.py +17 -0
- osbot_utils/helpers/ast/nodes/Ast_Generator_Exp.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Gt.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_GtE.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_If.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_If_Exp.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Import.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Import_From.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_In.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Is.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Is_Not.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Keyword.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Lambda.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_List.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_List_Comp.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Load.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Lt.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_LtE.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Mod.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Module.py +20 -0
- osbot_utils/helpers/ast/nodes/Ast_Mult.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Name.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Not.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Not_Eq.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Not_In.py +6 -0
- osbot_utils/helpers/ast/nodes/Ast_Or.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Pass.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Pow.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Raise.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Return.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Set.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Slice.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Starred.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Store.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Sub.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Subscript.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_Try.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Tuple.py +9 -0
- osbot_utils/helpers/ast/nodes/Ast_Unary_Op.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_While.py +8 -0
- osbot_utils/helpers/ast/nodes/Ast_With.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_With_Item.py +7 -0
- osbot_utils/helpers/ast/nodes/Ast_Yield.py +7 -0
- osbot_utils/helpers/ast/nodes/__init__.py +0 -0
- osbot_utils/helpers/html/Dict_To_Css.py +20 -0
- osbot_utils/helpers/html/Dict_To_Html.py +59 -0
- osbot_utils/helpers/html/Dict_To_Tags.py +88 -0
- osbot_utils/helpers/html/Html_To_Dict.py +75 -0
- osbot_utils/helpers/html/Html_To_Tag.py +20 -0
- osbot_utils/helpers/html/Tag__Base.py +91 -0
- osbot_utils/helpers/html/Tag__Body.py +5 -0
- osbot_utils/helpers/html/Tag__Div.py +5 -0
- osbot_utils/helpers/html/Tag__H.py +9 -0
- osbot_utils/helpers/html/Tag__HR.py +5 -0
- osbot_utils/helpers/html/Tag__Head.py +32 -0
- osbot_utils/helpers/html/Tag__Html.py +42 -0
- osbot_utils/helpers/html/Tag__Link.py +17 -0
- osbot_utils/helpers/html/Tag__Style.py +25 -0
- osbot_utils/helpers/html/__init__.py +0 -0
- osbot_utils/helpers/pubsub/Event__Queue.py +95 -0
- osbot_utils/helpers/pubsub/PubSub__Client.py +53 -0
- osbot_utils/helpers/pubsub/PubSub__Room.py +13 -0
- osbot_utils/helpers/pubsub/PubSub__Server.py +94 -0
- osbot_utils/helpers/pubsub/PubSub__Sqlite.py +24 -0
- osbot_utils/helpers/pubsub/__init__.py +0 -0
- osbot_utils/helpers/pubsub/schemas/Schema__Event.py +15 -0
- osbot_utils/helpers/pubsub/schemas/Schema__Event__Connect.py +7 -0
- osbot_utils/helpers/pubsub/schemas/Schema__Event__Disconnect.py +7 -0
- osbot_utils/helpers/pubsub/schemas/Schema__Event__Join_Room.py +8 -0
- osbot_utils/helpers/pubsub/schemas/Schema__Event__Leave_Room.py +8 -0
- osbot_utils/helpers/pubsub/schemas/Schema__Event__Message.py +7 -0
- osbot_utils/helpers/pubsub/schemas/Schema__PubSub__Client.py +8 -0
- osbot_utils/helpers/pubsub/schemas/__init__.py +0 -0
- osbot_utils/helpers/sqlite/Capture_Sqlite_Error.py +51 -0
- osbot_utils/helpers/sqlite/Sqlite__Cursor.py +87 -0
- osbot_utils/helpers/sqlite/Sqlite__Database.py +137 -0
- osbot_utils/helpers/sqlite/Sqlite__Field.py +70 -0
- osbot_utils/helpers/sqlite/Sqlite__Globals.py +5 -0
- osbot_utils/helpers/sqlite/Sqlite__Table.py +293 -0
- osbot_utils/helpers/sqlite/Sqlite__Table__Create.py +96 -0
- osbot_utils/helpers/sqlite/Temp_Sqlite__Database__Disk.py +17 -0
- osbot_utils/helpers/sqlite/Temp_Sqlite__Table.py +23 -0
- osbot_utils/helpers/sqlite/__init__.py +0 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests.py +214 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests__Patch.py +63 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py +23 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Graph.py +47 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Json.py +83 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py +20 -0
- osbot_utils/helpers/sqlite/domains/Sqlite__DB__Requests.py +39 -0
- osbot_utils/helpers/sqlite/domains/__init__.py +0 -0
- osbot_utils/helpers/sqlite/domains/schemas/Schema__Table__Requests.py +12 -0
- osbot_utils/helpers/sqlite/domains/schemas/__init__.py +0 -0
- osbot_utils/helpers/sqlite/models/Sqlite__Field__Type.py +37 -0
- osbot_utils/helpers/sqlite/models/__init__.py +0 -0
- osbot_utils/helpers/sqlite/sample_data/Sqlite__Sample_Data__Chinook.py +116 -0
- osbot_utils/helpers/sqlite/sample_data/__init__.py +0 -0
- osbot_utils/helpers/sqlite/sql_builder/SQL_Builder.py +159 -0
- osbot_utils/helpers/sqlite/sql_builder/SQL_Builder__Select.py +12 -0
- osbot_utils/helpers/sqlite/sql_builder/__init__.py +0 -0
- osbot_utils/helpers/sqlite/tables/Sqlite__Table__Config.py +63 -0
- osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py +46 -0
- osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py +45 -0
- osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py +52 -0
- osbot_utils/helpers/sqlite/tables/__init__.py +0 -0
- osbot_utils/helpers/trace/Trace_Call.py +120 -0
- osbot_utils/helpers/trace/Trace_Call__Config.py +94 -0
- osbot_utils/helpers/trace/Trace_Call__Graph.py +26 -0
- osbot_utils/helpers/trace/Trace_Call__Handler.py +215 -0
- osbot_utils/helpers/trace/Trace_Call__Print_Lines.py +85 -0
- osbot_utils/helpers/trace/Trace_Call__Print_Traces.py +170 -0
- osbot_utils/helpers/trace/Trace_Call__Stack.py +166 -0
- osbot_utils/helpers/trace/Trace_Call__Stack_Node.py +59 -0
- osbot_utils/helpers/trace/Trace_Call__Stats.py +71 -0
- osbot_utils/helpers/trace/Trace_Call__View_Model.py +75 -0
- osbot_utils/helpers/trace/Trace_Files.py +33 -0
- osbot_utils/helpers/trace/__init__.py +0 -0
- osbot_utils/testing/Catch.py +54 -0
- osbot_utils/testing/Duration.py +69 -0
- osbot_utils/testing/Hook_Method.py +118 -0
- osbot_utils/testing/Log_To_Queue.py +46 -0
- osbot_utils/testing/Log_To_String.py +37 -0
- osbot_utils/testing/Logging.py +81 -0
- osbot_utils/testing/Patch_Print.py +52 -0
- osbot_utils/testing/Profiler.py +89 -0
- osbot_utils/testing/Stderr.py +19 -0
- osbot_utils/testing/Stdout.py +19 -0
- osbot_utils/testing/Temp_File.py +46 -0
- osbot_utils/testing/Temp_Folder.py +114 -0
- osbot_utils/testing/Temp_Sys_Path.py +13 -0
- osbot_utils/testing/Temp_Web_Server.py +83 -0
- osbot_utils/testing/Temp_Zip.py +45 -0
- osbot_utils/testing/Temp_Zip_In_Memory.py +90 -0
- osbot_utils/testing/Unit_Test.py +34 -0
- osbot_utils/testing/Unzip_File.py +30 -0
- osbot_utils/testing/__init__.py +0 -0
- osbot_utils/utils/Assert.py +52 -0
- osbot_utils/utils/Call_Stack.py +187 -0
- osbot_utils/utils/Csv.py +32 -0
- osbot_utils/utils/Dev.py +47 -0
- osbot_utils/utils/Exceptions.py +7 -0
- osbot_utils/utils/Files.py +528 -0
- osbot_utils/utils/Functions.py +113 -0
- osbot_utils/utils/Http.py +136 -0
- osbot_utils/utils/Int.py +6 -0
- osbot_utils/utils/Json.py +171 -0
- osbot_utils/utils/Json_Cache.py +59 -0
- osbot_utils/utils/Lists.py +198 -0
- osbot_utils/utils/Misc.py +496 -0
- osbot_utils/utils/Objects.py +341 -0
- osbot_utils/utils/Png.py +29 -0
- osbot_utils/utils/Process.py +73 -0
- osbot_utils/utils/Python_Logger.py +301 -0
- osbot_utils/utils/Status.py +79 -0
- osbot_utils/utils/Str.py +63 -0
- osbot_utils/utils/Version.py +16 -0
- osbot_utils/utils/Zip.py +97 -0
- osbot_utils/utils/__init__.py +16 -0
- osbot_utils/version +1 -0
- osbot_utils-1.7.7.dist-info/LICENSE +201 -0
- osbot_utils-1.7.7.dist-info/METADATA +46 -0
- osbot_utils-1.7.7.dist-info/RECORD +260 -0
- osbot_utils-1.7.7.dist-info/WHEEL +4 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
import json
|
2
|
+
import socket
|
3
|
+
import ssl
|
4
|
+
from time import sleep
|
5
|
+
from urllib.request import Request, urlopen
|
6
|
+
|
7
|
+
from osbot_utils.utils.Files import save_bytes_as_file, file_size, file_bytes, file_open_bytes, file_create
|
8
|
+
from osbot_utils.utils.Python_Logger import Python_Logger
|
9
|
+
|
10
|
+
URL_CHECK_HOST_ONLINE = 'https://www.google.com'
|
11
|
+
|
12
|
+
def current_host_offline(url_to_use=URL_CHECK_HOST_ONLINE):
|
13
|
+
return current_host_online(url_to_use=url_to_use) is False
|
14
|
+
|
15
|
+
def current_host_online(url_to_use=URL_CHECK_HOST_ONLINE):
|
16
|
+
try:
|
17
|
+
http_request(url_to_use, method='HEAD')
|
18
|
+
return True
|
19
|
+
except:
|
20
|
+
return False
|
21
|
+
|
22
|
+
def dns_ip_address(host):
|
23
|
+
return socket.gethostbyname(host)
|
24
|
+
|
25
|
+
def is_port_open(host, port, timeout=0.5):
|
26
|
+
return port_is_open(host=host, port=port, timeout=timeout)
|
27
|
+
|
28
|
+
def port_is_open(port : int , host='0.0.0.0', timeout=1.0):
|
29
|
+
try:
|
30
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
31
|
+
sock.settimeout(timeout)
|
32
|
+
result = sock.connect_ex((host, port))
|
33
|
+
return result == 0
|
34
|
+
except:
|
35
|
+
return False
|
36
|
+
|
37
|
+
|
38
|
+
def http_request(url, data=None, headers=None, method='GET', encoding ='utf-8', return_response_object=False):
|
39
|
+
ssl_request = url.startswith('https://')
|
40
|
+
headers = headers or {}
|
41
|
+
if data:
|
42
|
+
print()
|
43
|
+
if type(data) is not str: # if the data object is not a string
|
44
|
+
if headers.get('Content-Type') == "application/json": # and a json payload is expected
|
45
|
+
data = json.dumps(data) # convert it to json
|
46
|
+
if type(data) is str: # only convert to bytes if current data is a string
|
47
|
+
data = data.encode()
|
48
|
+
request = Request(url, data=data, headers=headers)
|
49
|
+
request.get_method = lambda: method
|
50
|
+
|
51
|
+
if ssl_request:
|
52
|
+
gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
|
53
|
+
response = urlopen(request, context=gcontext)
|
54
|
+
else:
|
55
|
+
response = urlopen(request)
|
56
|
+
|
57
|
+
if return_response_object:
|
58
|
+
return response
|
59
|
+
else:
|
60
|
+
result = response.read()
|
61
|
+
if encoding:
|
62
|
+
return result.decode(encoding)
|
63
|
+
return result
|
64
|
+
|
65
|
+
def port_is_not_open(port, host='0.0.0.0', timeout=1.0):
|
66
|
+
return port_is_open(port, host,timeout) is False
|
67
|
+
|
68
|
+
def wait_for_http(url, max_attempts=20, wait_for=0.1):
|
69
|
+
for i in range(max_attempts):
|
70
|
+
try:
|
71
|
+
if GET(url):
|
72
|
+
return True
|
73
|
+
except:
|
74
|
+
pass
|
75
|
+
sleep(wait_for)
|
76
|
+
return False
|
77
|
+
|
78
|
+
def wait_for_ssh(host, max_attempts=120, wait_for=0.5):
|
79
|
+
return wait_for_port(host=host, port=22, max_attempts=max_attempts, wait_for=wait_for)
|
80
|
+
|
81
|
+
def wait_for_port(host, port, max_attempts=20, wait_for=0.1):
|
82
|
+
for i in range(max_attempts):
|
83
|
+
if is_port_open(host=host,port=port,timeout=wait_for):
|
84
|
+
return True
|
85
|
+
sleep(wait_for)
|
86
|
+
return False
|
87
|
+
|
88
|
+
def wait_for_port_closed(host, port, max_attempts=20, wait_for=0.1):
|
89
|
+
for i in range(max_attempts):
|
90
|
+
if is_port_open(host=host,port=port,timeout=wait_for) is False:
|
91
|
+
return True
|
92
|
+
sleep(wait_for)
|
93
|
+
return False
|
94
|
+
|
95
|
+
def DELETE(url, data=None, headers=None):
|
96
|
+
return http_request(url, data, headers, 'DELETE')
|
97
|
+
|
98
|
+
def DELETE_json(*args, **kwargs):
|
99
|
+
return json.loads(DELETE(*args, **kwargs))
|
100
|
+
|
101
|
+
def GET(url,headers = None, encoding='utf-8'):
|
102
|
+
return http_request(url, headers=headers, method='GET', encoding=encoding)
|
103
|
+
|
104
|
+
def GET_to_file(url,path=None, headers = None, extension=None):
|
105
|
+
contents = GET(url, headers)
|
106
|
+
return file_create(path=path, contents=contents,extension=extension)
|
107
|
+
|
108
|
+
def GET_bytes(url, headers=None):
|
109
|
+
return GET(url, headers=headers, encoding=None)
|
110
|
+
|
111
|
+
def GET_bytes_to_file(url,path=None, headers = None):
|
112
|
+
file_bytes = GET_bytes(url, headers)
|
113
|
+
return save_bytes_as_file(file_bytes, path)
|
114
|
+
|
115
|
+
def GET_json(*args, **kwargs):
|
116
|
+
return json.loads(GET(*args, **kwargs))
|
117
|
+
|
118
|
+
def OPTIONS(url,headers = None):
|
119
|
+
response = http_request(url, headers=headers, method='OPTIONS', return_response_object=True)
|
120
|
+
response_headers = {}
|
121
|
+
for response_header in response.getheaders():
|
122
|
+
(name,value) = response_header
|
123
|
+
response_headers[name] = value
|
124
|
+
return response_headers
|
125
|
+
|
126
|
+
def POST(url, data='', headers=None):
|
127
|
+
return http_request(url, data, headers, 'POST')
|
128
|
+
|
129
|
+
def POST_json(*args, **kwargs):
|
130
|
+
return json.loads(POST(*args, **kwargs))
|
131
|
+
|
132
|
+
def PUT(url, data='', headers=None):
|
133
|
+
return http_request(url, data, headers, 'PUT')
|
134
|
+
|
135
|
+
def PUT_json(*args, **kwargs):
|
136
|
+
return json.loads(PUT(*args, **kwargs))
|
osbot_utils/utils/Int.py
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
import json
|
2
|
+
import gzip
|
3
|
+
import logging
|
4
|
+
import os
|
5
|
+
|
6
|
+
from osbot_utils.utils.Misc import str_lines, str_md5, str_sha256
|
7
|
+
from osbot_utils.utils.Status import log_exception
|
8
|
+
|
9
|
+
logger_json = logging.getLogger() # todo: start using this API for capturing error messages from methods bellow
|
10
|
+
|
11
|
+
from osbot_utils.utils.Files import file_create_gz, file_create, load_file_gz, file_contents, file_lines, file_lines_gz
|
12
|
+
|
13
|
+
|
14
|
+
def json_dumps(python_object, indent=4, pretty=True, sort_keys=False, default=str, raise_exception=False):
|
15
|
+
if python_object:
|
16
|
+
try:
|
17
|
+
if pretty:
|
18
|
+
return json.dumps(python_object, indent=indent, sort_keys=sort_keys, default=default)
|
19
|
+
return json.dumps(python_object, default=default)
|
20
|
+
except Exception as error:
|
21
|
+
error_message = f'Error in load_json: {error}'
|
22
|
+
log_exception(message=error_message, error=error)
|
23
|
+
if raise_exception:
|
24
|
+
raise error
|
25
|
+
|
26
|
+
|
27
|
+
def json_dumps_to_bytes(*args, **kwargs):
|
28
|
+
return json_dumps(*args, **kwargs).encode()
|
29
|
+
|
30
|
+
def json_lines_file_load(target_path):
|
31
|
+
raw_json = '[' # start the json array
|
32
|
+
lines = file_lines(target_path) # get all lines from the file provided in target_path
|
33
|
+
raw_json += ','.join(lines) # add lines to raw_json split by json array separator
|
34
|
+
raw_json += ']' # close the json array
|
35
|
+
return json_parse(raw_json) # convert json data into a python object
|
36
|
+
|
37
|
+
def json_lines_file_load_gz(target_path):
|
38
|
+
raw_json = '[' # start the json array
|
39
|
+
lines = file_lines_gz(target_path) # get all lines from the file provided in target_path
|
40
|
+
raw_json += ','.join(lines) # add lines to raw_json split by json array separator
|
41
|
+
raw_json += ']' # close the json array
|
42
|
+
return json_parse(raw_json) # convert json data into a python object
|
43
|
+
|
44
|
+
|
45
|
+
def json_sha_256(target):
|
46
|
+
return str_sha256(json_dumps(target))
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
class Json:
|
51
|
+
|
52
|
+
@staticmethod
|
53
|
+
def load_file(path):
|
54
|
+
"""
|
55
|
+
Loads json data from file
|
56
|
+
Note: will not throw errors and will return {} as default
|
57
|
+
errors are logged to Json.log
|
58
|
+
"""
|
59
|
+
json_data = file_contents(path)
|
60
|
+
return json_loads(json_data)
|
61
|
+
|
62
|
+
@staticmethod
|
63
|
+
def load_file_and_delete(path):
|
64
|
+
data = json_load_file(path)
|
65
|
+
if data:
|
66
|
+
os.remove(path)
|
67
|
+
return data
|
68
|
+
|
69
|
+
@staticmethod
|
70
|
+
def load_file_gz(path):
|
71
|
+
data = load_file_gz(path)
|
72
|
+
return json_loads(data)
|
73
|
+
|
74
|
+
@staticmethod
|
75
|
+
def load_file_gz_and_delete(path):
|
76
|
+
data = json_load_file_gz(path)
|
77
|
+
if data:
|
78
|
+
os.remove(path)
|
79
|
+
return data
|
80
|
+
|
81
|
+
@staticmethod
|
82
|
+
def loads(json_data, raise_exception=False):
|
83
|
+
"""
|
84
|
+
Loads json data from string
|
85
|
+
Note: will not throw errors and will return {} as default
|
86
|
+
errors are logged to Json.log
|
87
|
+
"""
|
88
|
+
if json_data:
|
89
|
+
try:
|
90
|
+
return json.loads(json_data)
|
91
|
+
except Exception as error:
|
92
|
+
log_exception(message='Error in load_json', error=error)
|
93
|
+
if raise_exception:
|
94
|
+
raise error
|
95
|
+
|
96
|
+
return {}
|
97
|
+
|
98
|
+
@staticmethod
|
99
|
+
def loads_json_lines(json_lines):
|
100
|
+
json_data = '[' + ','.join(str_lines(json_lines.strip())) + ']'
|
101
|
+
return json_loads(json_data)
|
102
|
+
|
103
|
+
@staticmethod
|
104
|
+
def md5(data):
|
105
|
+
return str_md5(json_dump(data))
|
106
|
+
|
107
|
+
@staticmethod
|
108
|
+
def round_trip(data):
|
109
|
+
return json_loads(json_dumps(data))
|
110
|
+
|
111
|
+
@staticmethod
|
112
|
+
def save_file(python_object, path=None, pretty=False, sort_keys=False):
|
113
|
+
json_data = json_dumps(python_object=python_object, indent=2, pretty=pretty, sort_keys=sort_keys)
|
114
|
+
return file_create(path=path, contents=json_data)
|
115
|
+
|
116
|
+
@staticmethod
|
117
|
+
def save_file_pretty(python_object, path=None):
|
118
|
+
return json_save_file(python_object=python_object, path=path, pretty=True)
|
119
|
+
|
120
|
+
@staticmethod
|
121
|
+
def save_file_gz(python_object, path=None, pretty=False):
|
122
|
+
json_data = json_dumps(python_object,indent=2, pretty=pretty)
|
123
|
+
return file_create_gz(path=path, contents=json_data)
|
124
|
+
|
125
|
+
@staticmethod
|
126
|
+
def save_file_pretty_gz(python_object, path=None):
|
127
|
+
return json_save_file_gz(python_object=python_object, path=path, pretty=True)
|
128
|
+
|
129
|
+
|
130
|
+
@staticmethod
|
131
|
+
def json_save_tmp_file(python_object, pretty=True):
|
132
|
+
return Json.save_file(python_object=python_object, pretty=pretty, path=None)
|
133
|
+
|
134
|
+
file_create_json = Json.save_file_pretty
|
135
|
+
file_contents_json = Json.load_file
|
136
|
+
|
137
|
+
json_dump = json_dumps
|
138
|
+
json_format = json_dumps
|
139
|
+
json_file_create = Json.save_file
|
140
|
+
json_file_create_gz = Json.save_file_gz
|
141
|
+
json_file_contents = Json.load_file
|
142
|
+
json_file_contents_gz = Json.load_file_gz
|
143
|
+
json_file_load = Json.load_file
|
144
|
+
json_file_safe = Json.save_file
|
145
|
+
json_from_file = Json.load_file
|
146
|
+
json_load_file = Json.load_file
|
147
|
+
json_load_file_and_delete = Json.load_file_and_delete
|
148
|
+
json_load_file_gz = Json.load_file_gz
|
149
|
+
json_load_file_gz_and_delete = Json.load_file_gz_and_delete
|
150
|
+
json_from_string = Json.loads
|
151
|
+
json_load = Json.loads
|
152
|
+
json_loads = Json.loads
|
153
|
+
json_md5 = Json.md5
|
154
|
+
json_lines_loads = Json.loads_json_lines
|
155
|
+
json_parse = Json.loads
|
156
|
+
json_lines_parse = Json.loads_json_lines
|
157
|
+
json_to_str = json_dumps
|
158
|
+
json_round_trip = Json.round_trip
|
159
|
+
json_save = Json.save_file
|
160
|
+
json_save_file = Json.save_file
|
161
|
+
json_save_file_pretty = Json.save_file_pretty
|
162
|
+
json_save_file_gz = Json.save_file_gz
|
163
|
+
json_save_file_pretty_gz = Json.save_file_pretty_gz
|
164
|
+
json_save_tmp_file = Json.json_save_tmp_file
|
165
|
+
str_to_json = Json.loads
|
166
|
+
|
167
|
+
load_file_json = json_load_file
|
168
|
+
load_file_json_gz = json_load_file_gz
|
169
|
+
|
170
|
+
to_json_str = json_dumps
|
171
|
+
from_json_str = json_loads
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from osbot_utils.utils.Files import path_combine, folder_create, file_delete, file_exists
|
2
|
+
from osbot_utils.utils.Json import json_save_file_gz, json_save_file, json_load_file_gz, json_load_file
|
3
|
+
from osbot_utils.utils.Str import str_safe
|
4
|
+
|
5
|
+
PATH_TEMP_FOLDER = '/tmp/json_cache'
|
6
|
+
|
7
|
+
class Json_Cache:
|
8
|
+
|
9
|
+
def __init__(self, cache_type=None, cache_keys=None):
|
10
|
+
self.cache_type = cache_type or '__cache'
|
11
|
+
self.cache_keys = cache_keys or [self.cache_type]
|
12
|
+
self.path_tmp_folder = PATH_TEMP_FOLDER
|
13
|
+
self.save_as_gz = True
|
14
|
+
if type(self.cache_keys) is not list and type(self.cache_keys) is not tuple:
|
15
|
+
self.cache_keys = [self.cache_keys]
|
16
|
+
#self.data = None
|
17
|
+
|
18
|
+
def __enter__(self):
|
19
|
+
return self
|
20
|
+
|
21
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
22
|
+
pass
|
23
|
+
|
24
|
+
def data(self):
|
25
|
+
file_path = self.path_cache_file()
|
26
|
+
if self.exists():
|
27
|
+
if self.save_as_gz:
|
28
|
+
return json_load_file_gz(file_path)
|
29
|
+
else:
|
30
|
+
return json_load_file(file_path)
|
31
|
+
return None
|
32
|
+
|
33
|
+
def delete(self):
|
34
|
+
return file_delete(self.path_cache_file())
|
35
|
+
|
36
|
+
def exists(self):
|
37
|
+
return file_exists(self.path_cache_file())
|
38
|
+
|
39
|
+
def save(self, data):
|
40
|
+
file_path = self.path_cache_file()
|
41
|
+
if self.save_as_gz:
|
42
|
+
return json_save_file_gz(data, file_path)
|
43
|
+
else:
|
44
|
+
return json_save_file(data, file_path)
|
45
|
+
|
46
|
+
def path_cache_folder(self):
|
47
|
+
path_cache = path_combine(self.path_tmp_folder, self.cache_type)
|
48
|
+
folder_create(path_cache)
|
49
|
+
return path_cache
|
50
|
+
|
51
|
+
def path_cache_file(self):
|
52
|
+
tmp_file_name = ""#str_safe(str(self.cache_type))
|
53
|
+
for cache_key in self.cache_keys:
|
54
|
+
tmp_file_name += f"--{str_safe(str(cache_key))}"
|
55
|
+
tmp_file_name += ".json"
|
56
|
+
if self.save_as_gz:
|
57
|
+
tmp_file_name += ".gz"
|
58
|
+
file_path = path_combine(self.path_cache_folder(), tmp_file_name)
|
59
|
+
return file_path
|
@@ -0,0 +1,198 @@
|
|
1
|
+
import sys
|
2
|
+
from typing import List
|
3
|
+
|
4
|
+
from osbot_utils.utils.Misc import list_set
|
5
|
+
|
6
|
+
from osbot_utils.utils.Str import trim
|
7
|
+
|
8
|
+
def len_list(target):
|
9
|
+
if type(target) is list:
|
10
|
+
return len(list(target))
|
11
|
+
return 0
|
12
|
+
|
13
|
+
def list_add(array : list, value):
|
14
|
+
if value is not None:
|
15
|
+
array.append(value)
|
16
|
+
return value
|
17
|
+
|
18
|
+
def list_chunks(items:list, split: int):
|
19
|
+
if items and split and split > 0:
|
20
|
+
for i in range(0, len(items), split):
|
21
|
+
yield items[i:i + split]
|
22
|
+
|
23
|
+
def list_contains_list(array : list, values):
|
24
|
+
if array is not None:
|
25
|
+
if type(values) is list:
|
26
|
+
for item in values:
|
27
|
+
if (item in array) is False:
|
28
|
+
return False
|
29
|
+
return True
|
30
|
+
return False
|
31
|
+
|
32
|
+
def list_delete(target, item):
|
33
|
+
if item in target:
|
34
|
+
target.remove(item)
|
35
|
+
return target
|
36
|
+
|
37
|
+
def list_empty(list):
|
38
|
+
return not list_not_empty(list)
|
39
|
+
|
40
|
+
def list_filter(target_list, filter_function):
|
41
|
+
return list(filter(filter_function, target_list))
|
42
|
+
|
43
|
+
def list_filter_starts_with(target_list, prefix):
|
44
|
+
return list_filter(target_list, lambda x: x.startswith(prefix))
|
45
|
+
|
46
|
+
def list_filter_contains(target_list, value):
|
47
|
+
return list_filter(target_list, lambda x: x.find(value) > -1)
|
48
|
+
|
49
|
+
def list_find(array:list, item):
|
50
|
+
if item in array:
|
51
|
+
return array.index(item)
|
52
|
+
return -1
|
53
|
+
|
54
|
+
def list_first(list, strip=False):
|
55
|
+
if list_not_empty(list):
|
56
|
+
value = list[0]
|
57
|
+
if strip:
|
58
|
+
value = value.strip()
|
59
|
+
return value
|
60
|
+
|
61
|
+
def list_in_list(source : list, target: list):
|
62
|
+
return set(source).issubset(set(target))
|
63
|
+
|
64
|
+
def list_get(array, position=None, default=None):
|
65
|
+
if type(array) is list:
|
66
|
+
if type(position) is int and position >=0 :
|
67
|
+
if len(array) > position:
|
68
|
+
return array[position]
|
69
|
+
return default
|
70
|
+
|
71
|
+
def list_get_field(values, field):
|
72
|
+
if type(values) is list:
|
73
|
+
return [item.get(field) for item in values]
|
74
|
+
return []
|
75
|
+
|
76
|
+
def list_group_by(values, group_by):
|
77
|
+
results = {}
|
78
|
+
if type(values) is list:
|
79
|
+
for item in values:
|
80
|
+
value = str(item.get(group_by))
|
81
|
+
if results.get(value) is None: results[value] = []
|
82
|
+
results[value].append(item)
|
83
|
+
return results
|
84
|
+
|
85
|
+
def list_index_by(values, index_by):
|
86
|
+
from osbot_utils.fluent.Fluent_Dict import Fluent_Dict
|
87
|
+
results = {}
|
88
|
+
if values and index_by:
|
89
|
+
for item in values:
|
90
|
+
results[item.get(index_by)] = item
|
91
|
+
return Fluent_Dict(results)
|
92
|
+
|
93
|
+
def list_lower(input_list):
|
94
|
+
return [item.lower() for item in input_list]
|
95
|
+
|
96
|
+
def list_not_empty(list):
|
97
|
+
if list and type(list).__name__ == 'list' and len(list) >0:
|
98
|
+
return True
|
99
|
+
return False
|
100
|
+
|
101
|
+
def list_order_by(target: List[dict], key: str, reverse: bool=False) -> List[dict]:
|
102
|
+
if target and key:
|
103
|
+
return sorted(target, key=lambda x: x[key], reverse=reverse)
|
104
|
+
return []
|
105
|
+
|
106
|
+
def list_pop(array:list, position=None, default=None):
|
107
|
+
if array:
|
108
|
+
if len(array) >0:
|
109
|
+
if type(position) is int:
|
110
|
+
if len(array) > position:
|
111
|
+
return array.pop(position)
|
112
|
+
else:
|
113
|
+
return array.pop()
|
114
|
+
return default
|
115
|
+
|
116
|
+
def list_pop_and_trim(array, position=None):
|
117
|
+
value = array_pop(array,position)
|
118
|
+
if type(value) is str:
|
119
|
+
return trim(value)
|
120
|
+
return value
|
121
|
+
|
122
|
+
def list_remove(array, item):
|
123
|
+
if type(array) is list:
|
124
|
+
if type(item) is list:
|
125
|
+
result = []
|
126
|
+
for element in array:
|
127
|
+
if element not in item:
|
128
|
+
result.append(element)
|
129
|
+
return result
|
130
|
+
|
131
|
+
return [element for element in array if element != item]
|
132
|
+
return array
|
133
|
+
|
134
|
+
def list_remove_list(source: list, target: list):
|
135
|
+
if type(source) is list and type(target) is list:
|
136
|
+
for item in target:
|
137
|
+
if item in source:
|
138
|
+
source.remove(item)
|
139
|
+
return source
|
140
|
+
|
141
|
+
def list_remove_empty(array):
|
142
|
+
if type(array) is list:
|
143
|
+
return [element for element in array if element]
|
144
|
+
return array
|
145
|
+
|
146
|
+
def list_set_dict(target):
|
147
|
+
if hasattr(target, '__dict__'):
|
148
|
+
return sorted(list(set(target.__dict__)))
|
149
|
+
return []
|
150
|
+
|
151
|
+
def list_sorted(target_list, key, descending=False):
|
152
|
+
return list(sorted(target_list, key= lambda x:x.get(key,None) ,reverse=descending))
|
153
|
+
|
154
|
+
def list_stats(target):
|
155
|
+
stats = {}
|
156
|
+
if type(target) is list:
|
157
|
+
for item in target:
|
158
|
+
if stats.get(item) is None:
|
159
|
+
stats[item] = 0
|
160
|
+
stats[item] += 1
|
161
|
+
return stats
|
162
|
+
|
163
|
+
def list_to_tuple(target: list):
|
164
|
+
if type(target) is list:
|
165
|
+
return tuple(target)
|
166
|
+
|
167
|
+
def list_zip(*args):
|
168
|
+
if args:
|
169
|
+
return list(zip(*args))
|
170
|
+
|
171
|
+
def sys_path_python(python_folder='lib/python'):
|
172
|
+
return list_contains(sys.path, python_folder)
|
173
|
+
|
174
|
+
def tuple_to_list(target:tuple):
|
175
|
+
if type(target) is tuple:
|
176
|
+
return list(target)
|
177
|
+
|
178
|
+
def tuple_replace_position(target:tuple, position,value):
|
179
|
+
tuple_as_list = tuple_to_list(target)
|
180
|
+
if len(tuple_as_list) > position:
|
181
|
+
tuple_as_list[position] = value
|
182
|
+
list_as_tuple = list_to_tuple(tuple_as_list)
|
183
|
+
return list_as_tuple
|
184
|
+
|
185
|
+
def unique(target):
|
186
|
+
return list_set(target)
|
187
|
+
|
188
|
+
array_find = list_find
|
189
|
+
array_get = list_get
|
190
|
+
array_pop = list_pop
|
191
|
+
array_pop_and_trim = list_pop_and_trim
|
192
|
+
array_add = list_add
|
193
|
+
|
194
|
+
list_contains = list_filter_contains
|
195
|
+
list_del = list_delete
|
196
|
+
list_sort_by = list_sorted
|
197
|
+
|
198
|
+
chunks = list_chunks
|