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
osbot_utils/utils/Dev.py
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
import json
|
2
|
+
import pprint as original_pprint
|
3
|
+
|
4
|
+
from osbot_utils.utils.Misc import date_time_now
|
5
|
+
|
6
|
+
|
7
|
+
class Dev:
|
8
|
+
@staticmethod
|
9
|
+
def jformat(data):
|
10
|
+
return json.dumps(data, indent=4) # use json.dumps to format
|
11
|
+
|
12
|
+
@staticmethod
|
13
|
+
def jprint(data):
|
14
|
+
print() # add a line before
|
15
|
+
print(json.dumps(data, indent=4)) # use json.dumps to format
|
16
|
+
return data
|
17
|
+
|
18
|
+
@staticmethod
|
19
|
+
def pformat(data):
|
20
|
+
return original_pprint.pformat(data, indent=2) # use a pprint to format
|
21
|
+
|
22
|
+
@staticmethod
|
23
|
+
def pprint(*args):
|
24
|
+
print() # add a line before
|
25
|
+
for arg in args:
|
26
|
+
original_pprint.pprint(arg, indent=2) # use a pprint to format
|
27
|
+
if len(args) == 1:
|
28
|
+
return args[0]
|
29
|
+
return args
|
30
|
+
|
31
|
+
@staticmethod
|
32
|
+
def nprint(data):
|
33
|
+
print() # add a line before
|
34
|
+
print(data)
|
35
|
+
return data
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def print_now():
|
39
|
+
print(date_time_now())
|
40
|
+
|
41
|
+
jformat = Dev.jformat
|
42
|
+
jprint = Dev.jprint
|
43
|
+
pformat = Dev.pformat
|
44
|
+
pprint = Dev.pprint
|
45
|
+
nprint = Dev.nprint
|
46
|
+
|
47
|
+
print_now = Dev.print_now
|
@@ -0,0 +1,7 @@
|
|
1
|
+
def syntax_error(error):
|
2
|
+
if type(error) is SyntaxError:
|
3
|
+
error_message = f"{error.msg} in {error.filename} at line {error.lineno} column {error.offset}\n\n"
|
4
|
+
error_message += f" {error.text}"
|
5
|
+
error_message += f" {' ' * (error.offset - 1)}^"
|
6
|
+
return Exception(f'[SyntaxError] \n\nError parsing code: {error_message}')
|
7
|
+
return Exception(f'{error}')
|
@@ -0,0 +1,528 @@
|
|
1
|
+
import gzip
|
2
|
+
|
3
|
+
import os
|
4
|
+
import glob
|
5
|
+
import pickle
|
6
|
+
import re
|
7
|
+
import shutil
|
8
|
+
import tempfile
|
9
|
+
from os.path import abspath, join
|
10
|
+
from pathlib import Path, PosixPath
|
11
|
+
from osbot_utils.utils.Misc import bytes_to_base64, base64_to_bytes, random_string
|
12
|
+
|
13
|
+
|
14
|
+
class Files:
|
15
|
+
@staticmethod
|
16
|
+
def bytes(path):
|
17
|
+
with open(path, 'rb') as file:
|
18
|
+
return file.read()
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def copy(source:str, destination:str) -> str:
|
22
|
+
if file_exists(source): # make sure source file exists
|
23
|
+
destination_parent_folder = parent_folder(destination) # get target parent folder
|
24
|
+
folder_create(destination_parent_folder) # ensure targer folder exists # todo: check if this is still needed (we should be using a copy method that creates the required fodlers)
|
25
|
+
return shutil.copy(source, destination) # copy file and returns file destination
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
def contains(path, content):
|
29
|
+
text = Files.contents(path)
|
30
|
+
if type(content) is list:
|
31
|
+
for item in content:
|
32
|
+
if item not in text:
|
33
|
+
return False
|
34
|
+
return True
|
35
|
+
return content in text
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def contents(path, mode='rt'):
|
39
|
+
if file_exists(path):
|
40
|
+
with file_open(path, mode) as file:
|
41
|
+
return file.read()
|
42
|
+
|
43
|
+
@staticmethod
|
44
|
+
def contents_gz(path, mode='rt'):
|
45
|
+
if file_exists(path):
|
46
|
+
with file_open_gz(path, mode) as file:
|
47
|
+
return file.read()
|
48
|
+
|
49
|
+
@staticmethod
|
50
|
+
def contents_md5(path):
|
51
|
+
from osbot_utils.utils.Misc import bytes_md5
|
52
|
+
return bytes_md5(file_contents_as_bytes(path))
|
53
|
+
|
54
|
+
@staticmethod
|
55
|
+
def contents_sha256(path):
|
56
|
+
from osbot_utils.utils.Misc import bytes_sha256
|
57
|
+
return bytes_sha256(file_contents_as_bytes(path))
|
58
|
+
|
59
|
+
@staticmethod
|
60
|
+
def current_folder():
|
61
|
+
return Files.path_combine(".","")
|
62
|
+
|
63
|
+
@staticmethod
|
64
|
+
def delete(path):
|
65
|
+
if Files.exists(path):
|
66
|
+
os.remove(path)
|
67
|
+
return Files.exists(path) is False
|
68
|
+
return False
|
69
|
+
|
70
|
+
@staticmethod
|
71
|
+
def exists(path):
|
72
|
+
return is_file(str(path))
|
73
|
+
# if path and is_file(path):
|
74
|
+
# return os.path.exists(path)
|
75
|
+
# return False
|
76
|
+
|
77
|
+
@staticmethod
|
78
|
+
def find(path_pattern, recursive=True):
|
79
|
+
return glob.glob(path_pattern, recursive=recursive)
|
80
|
+
|
81
|
+
@staticmethod
|
82
|
+
def files(path, pattern= '*.*'): # todo: check behaviour and improve ability to detect file (vs folders)
|
83
|
+
result = []
|
84
|
+
for file in Path(path).rglob(pattern):
|
85
|
+
result.append(str(file)) # todo: see if there is a better way to do this conversion to string
|
86
|
+
return sorted(result)
|
87
|
+
|
88
|
+
@staticmethod
|
89
|
+
def files_names(files : list, check_if_exists=True):
|
90
|
+
result = []
|
91
|
+
for file in files:
|
92
|
+
if is_file(file):
|
93
|
+
result.append(file_name(file, check_if_exists=check_if_exists))
|
94
|
+
return result
|
95
|
+
|
96
|
+
@staticmethod
|
97
|
+
def file_create_all_parent_folders(file_path):
|
98
|
+
if file_path:
|
99
|
+
parent_path = parent_folder(file_path)
|
100
|
+
if parent_path:
|
101
|
+
path = Path(parent_path)
|
102
|
+
path.mkdir(parents=True, exist_ok=True)
|
103
|
+
return parent_path
|
104
|
+
|
105
|
+
@staticmethod
|
106
|
+
def file_name(path, check_if_exists=True):
|
107
|
+
if is_file(path) or check_if_exists is False:
|
108
|
+
return os.path.basename(path)
|
109
|
+
|
110
|
+
@staticmethod
|
111
|
+
def file_name_without_extension(path):
|
112
|
+
if path:
|
113
|
+
path_file_name = file_name(path)
|
114
|
+
extension = file_extension(path_file_name)
|
115
|
+
if extension:
|
116
|
+
return path_file_name.replace(extension, '')
|
117
|
+
|
118
|
+
|
119
|
+
@staticmethod
|
120
|
+
def file_extension(path):
|
121
|
+
if path and '.' in path:
|
122
|
+
return os.path.splitext(path)[1]
|
123
|
+
return ''
|
124
|
+
|
125
|
+
@staticmethod
|
126
|
+
def file_extension_fix(extension):
|
127
|
+
if extension is None or len(extension) == 0: # if it None or empty return default .tmp extension
|
128
|
+
return '.tmp'
|
129
|
+
if extension[0] != '.': # make sure that the extension starts with a dot
|
130
|
+
return '.' + extension
|
131
|
+
return extension
|
132
|
+
|
133
|
+
@staticmethod
|
134
|
+
def file_to_base64(path):
|
135
|
+
return bytes_to_base64(file_bytes(path))
|
136
|
+
|
137
|
+
@staticmethod
|
138
|
+
def file_from_base64(bytes_base64, path=None, extension=None):
|
139
|
+
bytes_ = base64_to_bytes(bytes_base64)
|
140
|
+
return file_create_bytes(bytes=bytes_, path=path, extension=None)
|
141
|
+
|
142
|
+
@staticmethod
|
143
|
+
def file_size(path):
|
144
|
+
return file_stats(path).st_size
|
145
|
+
|
146
|
+
@staticmethod
|
147
|
+
def file_stats(path):
|
148
|
+
return os.stat(path)
|
149
|
+
|
150
|
+
@staticmethod
|
151
|
+
def filter_parent_folder(items, folder):
|
152
|
+
all_relative_items = []
|
153
|
+
for item in items:
|
154
|
+
all_relative_items.append(item.replace(folder, '')[1:])
|
155
|
+
return sorted(all_relative_items)
|
156
|
+
|
157
|
+
@staticmethod
|
158
|
+
def files_recursive(parent_dir, include_folders=False):
|
159
|
+
all_files = []
|
160
|
+
if os.path.isdir(parent_dir):
|
161
|
+
for item in os.listdir(parent_dir):
|
162
|
+
item_path = os.path.join(parent_dir, item)
|
163
|
+
if os.path.isfile(item_path):
|
164
|
+
all_files.append(item_path)
|
165
|
+
elif os.path.isdir(item_path):
|
166
|
+
if include_folders:
|
167
|
+
all_files.append(item_path + '/')
|
168
|
+
all_files.extend(files_recursive(item_path,include_folders=include_folders))
|
169
|
+
|
170
|
+
|
171
|
+
return sorted(all_files)
|
172
|
+
|
173
|
+
|
174
|
+
@staticmethod
|
175
|
+
def folder_exists(path):
|
176
|
+
return is_folder(path)
|
177
|
+
|
178
|
+
@staticmethod
|
179
|
+
def folder_copy(source, destination, ignore_pattern=None):
|
180
|
+
if ignore_pattern:
|
181
|
+
if type(ignore_pattern) is str:
|
182
|
+
ignore_pattern = [ignore_pattern]
|
183
|
+
ignore = shutil.ignore_patterns(*ignore_pattern) # for example ignore_pattern = ['*.pyc','.DS_Store']
|
184
|
+
else:
|
185
|
+
ignore = None
|
186
|
+
return shutil.copytree(src=source, dst=destination, ignore=ignore)
|
187
|
+
|
188
|
+
@staticmethod
|
189
|
+
def folder_create(path):
|
190
|
+
if folder_exists(path):
|
191
|
+
return path
|
192
|
+
|
193
|
+
os.makedirs(path)
|
194
|
+
return path
|
195
|
+
|
196
|
+
@staticmethod
|
197
|
+
def folder_create_in_parent(path, name):
|
198
|
+
folder_path = path_combine(path, name)
|
199
|
+
return folder_create(folder_path)
|
200
|
+
|
201
|
+
@staticmethod
|
202
|
+
def folder_delete(target_folder):
|
203
|
+
if folder_exists(target_folder):
|
204
|
+
try:
|
205
|
+
os.rmdir(target_folder)
|
206
|
+
return True
|
207
|
+
except OSError:
|
208
|
+
pass
|
209
|
+
return False
|
210
|
+
|
211
|
+
@staticmethod
|
212
|
+
def folder_delete_all(path): # this will remove recursively
|
213
|
+
if folder_exists(path):
|
214
|
+
shutil.rmtree(path)
|
215
|
+
return folder_exists(path) is False
|
216
|
+
return False
|
217
|
+
|
218
|
+
@staticmethod
|
219
|
+
def folder_name(path):
|
220
|
+
if path:
|
221
|
+
return os.path.basename(path)
|
222
|
+
|
223
|
+
@staticmethod
|
224
|
+
def folder_not_exists(path):
|
225
|
+
return folder_exists(path) is False
|
226
|
+
|
227
|
+
@staticmethod
|
228
|
+
def folder_sub_folders(path):
|
229
|
+
result = []
|
230
|
+
item: os.DirEntry
|
231
|
+
if Files.is_folder(path):
|
232
|
+
for item in os.scandir(path):
|
233
|
+
if item.is_dir():
|
234
|
+
result.append(item.path)
|
235
|
+
return result
|
236
|
+
|
237
|
+
@staticmethod
|
238
|
+
def folders_names(folders : list):
|
239
|
+
result = []
|
240
|
+
for folder in folders:
|
241
|
+
if folder:
|
242
|
+
result.append(folder_name(folder))
|
243
|
+
return sorted(result)
|
244
|
+
|
245
|
+
@staticmethod
|
246
|
+
def folders_sub_folders(folders : list):
|
247
|
+
result = []
|
248
|
+
for folder in folders:
|
249
|
+
result.extend(Files.folder_sub_folders(folder))
|
250
|
+
return result
|
251
|
+
|
252
|
+
@staticmethod
|
253
|
+
def folders_recursive(parent_dir):
|
254
|
+
subdirectories = []
|
255
|
+
for item in os.listdir(parent_dir):
|
256
|
+
item_path = os.path.join(parent_dir, item)
|
257
|
+
if os.path.isdir(item_path):
|
258
|
+
subdirectories.append(item_path)
|
259
|
+
subdirectories.extend(folders_recursive(item_path))
|
260
|
+
|
261
|
+
return sorted(subdirectories)
|
262
|
+
|
263
|
+
|
264
|
+
@staticmethod
|
265
|
+
def is_file(target):
|
266
|
+
if isinstance(target, Path):
|
267
|
+
return target.is_file()
|
268
|
+
if type(target) is str:
|
269
|
+
return os.path.isfile(target)
|
270
|
+
return False
|
271
|
+
|
272
|
+
@staticmethod
|
273
|
+
def is_folder(target):
|
274
|
+
if isinstance(target, Path):
|
275
|
+
return target.is_dir()
|
276
|
+
if type(target) is str:
|
277
|
+
return os.path.isdir(target)
|
278
|
+
return False
|
279
|
+
|
280
|
+
@staticmethod
|
281
|
+
def lines(path):
|
282
|
+
with open(path, "rt") as file:
|
283
|
+
for line in file:
|
284
|
+
yield line
|
285
|
+
|
286
|
+
@staticmethod
|
287
|
+
def lines_gz(path):
|
288
|
+
with gzip.open(path, "rt") as file:
|
289
|
+
for line in file:
|
290
|
+
yield line
|
291
|
+
|
292
|
+
@staticmethod
|
293
|
+
def not_exists(path):
|
294
|
+
return os.path.exists(str(path)) is False
|
295
|
+
|
296
|
+
@staticmethod
|
297
|
+
def open(path, mode='r'):
|
298
|
+
return open(path, mode=mode)
|
299
|
+
|
300
|
+
@staticmethod
|
301
|
+
def open_gz(path, mode='r'):
|
302
|
+
return gzip.open(path, mode=mode)
|
303
|
+
|
304
|
+
@staticmethod
|
305
|
+
def open_bytes(path):
|
306
|
+
return Files.open(path, mode='rb')
|
307
|
+
|
308
|
+
@staticmethod
|
309
|
+
def path_combine(path1, path2):
|
310
|
+
if type(path1) in [str, Path] and type(path2) in [str, Path]:
|
311
|
+
return abspath(join(str(path1), str(path2)))
|
312
|
+
|
313
|
+
@staticmethod
|
314
|
+
def parent_folder(path):
|
315
|
+
if path:
|
316
|
+
return os.path.dirname(path)
|
317
|
+
|
318
|
+
@staticmethod
|
319
|
+
def parent_folder_combine(file, path):
|
320
|
+
return Files.path_combine(os.path.dirname(file),path)
|
321
|
+
|
322
|
+
@staticmethod
|
323
|
+
def pickle_save_to_file(object_to_save, path=None):
|
324
|
+
path = path or temp_file(extension=".pickle")
|
325
|
+
file_to_store = open(path, "wb")
|
326
|
+
pickle.dump(object_to_save, file_to_store)
|
327
|
+
file_to_store.close()
|
328
|
+
return path
|
329
|
+
|
330
|
+
@staticmethod
|
331
|
+
def pickle_load_from_file(path=None):
|
332
|
+
file_to_read = open(path, "rb")
|
333
|
+
loaded_object = pickle.load(file_to_read)
|
334
|
+
file_to_read.close()
|
335
|
+
return loaded_object
|
336
|
+
|
337
|
+
@staticmethod
|
338
|
+
def safe_file_name(file_name):
|
339
|
+
if type(file_name) is not str:
|
340
|
+
file_name = f"{file_name}"
|
341
|
+
return re.sub(r'[^a-zA-Z0-9_.-]', '_',file_name or '')
|
342
|
+
|
343
|
+
@staticmethod
|
344
|
+
def save(contents, path=None, extension=None):
|
345
|
+
path = path or temp_file(extension=extension)
|
346
|
+
file_create(path, contents)
|
347
|
+
return path
|
348
|
+
|
349
|
+
@staticmethod
|
350
|
+
def sub_folders(target):
|
351
|
+
if type(target) is list:
|
352
|
+
return Files.folders_sub_folders(target)
|
353
|
+
if type(target) is str:
|
354
|
+
return Files.folder_sub_folders(target)
|
355
|
+
return []
|
356
|
+
|
357
|
+
@staticmethod
|
358
|
+
def save_bytes_as_file(bytes_to_save, path=None, extension=None):
|
359
|
+
if path is None:
|
360
|
+
path = Files.temp_file(extension)
|
361
|
+
with open(path, 'wb') as fp:
|
362
|
+
fp.write(bytes_to_save)
|
363
|
+
return path
|
364
|
+
|
365
|
+
@staticmethod
|
366
|
+
def temp_file(extension = '.tmp', contents=None, target_folder=None):
|
367
|
+
extension = file_extension_fix(extension)
|
368
|
+
if target_folder is None:
|
369
|
+
(fd, tmp_file) = tempfile.mkstemp(extension)
|
370
|
+
file_delete(tmp_file)
|
371
|
+
else:
|
372
|
+
tmp_file = path_combine(target_folder, temp_filename(extension))
|
373
|
+
|
374
|
+
if contents:
|
375
|
+
file_create(tmp_file, contents)
|
376
|
+
return tmp_file
|
377
|
+
|
378
|
+
@staticmethod
|
379
|
+
def temp_file_in_folder(target_folder, prefix="temp_file_", postfix='.txt'):
|
380
|
+
if is_folder(target_folder):
|
381
|
+
path_to_file = path_combine(target_folder, random_string(prefix=prefix, postfix=postfix))
|
382
|
+
file_create(path_to_file, random_string())
|
383
|
+
return path_to_file
|
384
|
+
|
385
|
+
|
386
|
+
|
387
|
+
@staticmethod
|
388
|
+
def temp_filename(extension='.tmp'):
|
389
|
+
return file_name(temp_file(extension), check_if_exists=False)
|
390
|
+
|
391
|
+
@staticmethod
|
392
|
+
def temp_folder(prefix=None, suffix=None,target_folder=None):
|
393
|
+
return tempfile.mkdtemp(suffix, prefix, target_folder)
|
394
|
+
|
395
|
+
@staticmethod
|
396
|
+
def temp_folder_current():
|
397
|
+
return tempfile.gettempdir()
|
398
|
+
|
399
|
+
@staticmethod
|
400
|
+
def temp_folder_with_temp_file(prefix=None, suffix=None,parent_folder=None, file_name='temp_file.txt', file_contents='temp_file'):
|
401
|
+
folder = temp_folder(prefix,suffix,parent_folder)
|
402
|
+
file_create(path_combine(folder,file_name), file_contents)
|
403
|
+
return folder
|
404
|
+
|
405
|
+
@staticmethod
|
406
|
+
def write(path = None,contents=None, extension=None, mode='w'):
|
407
|
+
path = path or temp_file(extension)
|
408
|
+
contents = contents or ''
|
409
|
+
with open(file=path, mode=mode) as file:
|
410
|
+
file.write(contents)
|
411
|
+
return path
|
412
|
+
|
413
|
+
@staticmethod
|
414
|
+
def write_bytes(path=None, bytes=None, extension=None):
|
415
|
+
return Files.write(path=path, contents=bytes, extension=extension, mode='wb')
|
416
|
+
|
417
|
+
@staticmethod
|
418
|
+
def write_gz(path=None, contents=None):
|
419
|
+
path = path or temp_file(extension='.gz')
|
420
|
+
contents = contents or ''
|
421
|
+
if type(contents) is str:
|
422
|
+
contents = contents.encode()
|
423
|
+
with gzip.open(path, "w") as file:
|
424
|
+
file.write(contents)
|
425
|
+
return path
|
426
|
+
|
427
|
+
# todo: refactor the methods above into static methods
|
428
|
+
|
429
|
+
|
430
|
+
|
431
|
+
# helper methods
|
432
|
+
# todo: all all methods above (including the duplicated mappings at the top)
|
433
|
+
|
434
|
+
create_folder = Files.folder_create
|
435
|
+
create_folder_in_parent = Files.folder_create_in_parent
|
436
|
+
create_temp_file = Files.write
|
437
|
+
current_folder = Files.current_folder
|
438
|
+
current_temp_folder = Files.temp_folder_current
|
439
|
+
|
440
|
+
file_bytes = Files.bytes
|
441
|
+
file_contains = Files.contains
|
442
|
+
file_contents = Files.contents
|
443
|
+
file_contents_gz = Files.contents_gz
|
444
|
+
file_contents_md5 = Files.contents_md5
|
445
|
+
file_contents_sha256 = Files.contents_sha256
|
446
|
+
file_contents_as_bytes = Files.bytes
|
447
|
+
file_create_all_parent_folders = Files.file_create_all_parent_folders
|
448
|
+
file_copy = Files.copy
|
449
|
+
file_delete = Files.delete
|
450
|
+
file_create = Files.write
|
451
|
+
file_create_bytes = Files.write_bytes
|
452
|
+
file_create_from_bytes = Files.write_bytes
|
453
|
+
file_create_gz = Files.write_gz
|
454
|
+
file_exists = Files.exists
|
455
|
+
file_extension = Files.file_extension
|
456
|
+
file_extension_fix = Files.file_extension_fix
|
457
|
+
file_lines = Files.lines
|
458
|
+
file_lines_gz = Files.lines_gz
|
459
|
+
file_md5 = Files.contents_md5
|
460
|
+
file_name = Files.file_name
|
461
|
+
file_name_without_extension = Files.file_name_without_extension
|
462
|
+
file_not_exists = Files.not_exists
|
463
|
+
file_open = Files.open
|
464
|
+
file_open_gz = Files.open_gz
|
465
|
+
file_open_bytes = Files.open_bytes
|
466
|
+
file_to_base64 = Files.file_to_base64
|
467
|
+
file_from_base64 = Files.file_from_base64
|
468
|
+
file_save = Files.save
|
469
|
+
file_sha256 = Files.contents_sha256
|
470
|
+
file_size = Files.file_size
|
471
|
+
file_stats = Files.file_stats
|
472
|
+
file_write = Files.write
|
473
|
+
file_write_bytes = Files.write_bytes
|
474
|
+
file_write_gz = Files.write_gz
|
475
|
+
filter_parent_folder = Files.filter_parent_folder
|
476
|
+
files_find = Files.find
|
477
|
+
files_recursive = Files.files_recursive
|
478
|
+
files_list = Files.files
|
479
|
+
files_names = Files.files_names
|
480
|
+
|
481
|
+
find_files = Files.files
|
482
|
+
|
483
|
+
folder_create = Files.folder_create
|
484
|
+
folder_create_in_parent = Files.folder_create_in_parent
|
485
|
+
folder_create_temp = Files.temp_folder
|
486
|
+
folder_copy = Files.folder_copy
|
487
|
+
folder_copy_except = Files.folder_copy
|
488
|
+
folder_delete = Files.folder_delete
|
489
|
+
folder_delete_all = Files.folder_delete_all
|
490
|
+
folder_delete_recursively = Files.folder_delete_all
|
491
|
+
folder_exists = Files.folder_exists
|
492
|
+
folder_not_exists = Files.folder_not_exists
|
493
|
+
folder_name = Files.folder_name
|
494
|
+
folder_temp = Files.temp_folder
|
495
|
+
folder_files = Files.files
|
496
|
+
folder_sub_folders = Files.folder_sub_folders
|
497
|
+
|
498
|
+
folders_in_folder = Files.folder_sub_folders
|
499
|
+
folders_names = Files.folders_names
|
500
|
+
folders_recursive = Files.folders_recursive
|
501
|
+
folders_sub_folders = Files.folders_sub_folders
|
502
|
+
|
503
|
+
is_file = Files.is_file
|
504
|
+
is_folder = Files.is_folder
|
505
|
+
|
506
|
+
load_file = Files.contents
|
507
|
+
load_file_gz = Files.contents_gz
|
508
|
+
|
509
|
+
path_append = Files.path_combine
|
510
|
+
path_combine = Files.path_combine
|
511
|
+
path_current = Files.current_folder
|
512
|
+
parent_folder = Files.parent_folder
|
513
|
+
parent_folder_combine = Files.parent_folder_combine
|
514
|
+
pickle_load_from_file = Files.pickle_load_from_file
|
515
|
+
pickle_save_to_file = Files.pickle_save_to_file
|
516
|
+
|
517
|
+
safe_file_name = Files.safe_file_name
|
518
|
+
save_bytes_as_file = Files.save_bytes_as_file
|
519
|
+
save_string_as_file = Files.save
|
520
|
+
sub_folders = Files.sub_folders
|
521
|
+
|
522
|
+
temp_file = Files.temp_file
|
523
|
+
temp_file_in_folder = Files.temp_file_in_folder
|
524
|
+
temp_filename = Files.temp_filename
|
525
|
+
temp_folder = Files.temp_folder
|
526
|
+
temp_folder_current = Files.temp_folder_current
|
527
|
+
temp_folder_with_temp_file = Files.temp_folder_with_temp_file
|
528
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import builtins
|
2
|
+
import inspect
|
3
|
+
import textwrap
|
4
|
+
import types
|
5
|
+
|
6
|
+
from osbot_utils.utils.Files import parent_folder
|
7
|
+
|
8
|
+
def function_args(function):
|
9
|
+
if isinstance(function, types.FunctionType):
|
10
|
+
return inspect.getfullargspec(function)
|
11
|
+
|
12
|
+
def function_file(function):
|
13
|
+
if isinstance(function, types.FunctionType):
|
14
|
+
return inspect.getfile(function)
|
15
|
+
|
16
|
+
def function_folder(function):
|
17
|
+
if isinstance(function, types.FunctionType):
|
18
|
+
return parent_folder(inspect.getfile(function))
|
19
|
+
|
20
|
+
def function_module(function):
|
21
|
+
if isinstance(function, types.FunctionType):
|
22
|
+
return inspect.getmodule(function)
|
23
|
+
|
24
|
+
def function_name(function):
|
25
|
+
if isinstance(function, types.FunctionType):
|
26
|
+
return function.__name__
|
27
|
+
|
28
|
+
def function_source_code(function):
|
29
|
+
if isinstance(function, types.FunctionType):
|
30
|
+
source_code = inspect.getsource(function)
|
31
|
+
source_code = textwrap.dedent(source_code).strip()
|
32
|
+
return source_code
|
33
|
+
elif isinstance(function, str):
|
34
|
+
return function
|
35
|
+
return None
|
36
|
+
|
37
|
+
def get_line_number(function):
|
38
|
+
try:
|
39
|
+
code, line = inspect.getsourcelines(function)
|
40
|
+
return line
|
41
|
+
except Exception:
|
42
|
+
return None
|
43
|
+
|
44
|
+
def is_callable(target):
|
45
|
+
return callable(target)
|
46
|
+
|
47
|
+
def method_params(target):
|
48
|
+
params = {}
|
49
|
+
method_signature = signature(target)
|
50
|
+
if method_signature:
|
51
|
+
parameters = method_signature.get('parameters')
|
52
|
+
args = []
|
53
|
+
kwargs = {}
|
54
|
+
for name, data in parameters.items():
|
55
|
+
if 'default' in set(data):
|
56
|
+
kwargs[name] = data['default']
|
57
|
+
else:
|
58
|
+
args.append(name)
|
59
|
+
params['args' ] = args
|
60
|
+
params['kwargs'] = kwargs
|
61
|
+
return params
|
62
|
+
|
63
|
+
|
64
|
+
def module_file(module):
|
65
|
+
if isinstance(module, types.ModuleType):
|
66
|
+
return inspect.getfile(module)
|
67
|
+
|
68
|
+
def module_folder(module):
|
69
|
+
if isinstance(module, types.ModuleType):
|
70
|
+
return parent_folder(inspect.getfile(module))
|
71
|
+
|
72
|
+
def module_full_name(module):
|
73
|
+
if isinstance(module, types.ModuleType):
|
74
|
+
return module.__name__
|
75
|
+
|
76
|
+
def module_name(module):
|
77
|
+
if isinstance(module, types.ModuleType):
|
78
|
+
return module.__name__.split('.')[-1]
|
79
|
+
|
80
|
+
# todo Improve this method to return more usefull set of data (like an signature str,better view of the param.kind, annotations )
|
81
|
+
def signature(callable_obj):
|
82
|
+
if not isinstance(callable_obj, (types.FunctionType, types.MethodType)):
|
83
|
+
return {}
|
84
|
+
|
85
|
+
signature = inspect.signature(callable_obj)
|
86
|
+
parameters = {}
|
87
|
+
sig_dict = { 'name' : callable_obj.__name__,
|
88
|
+
'parameters': parameters }
|
89
|
+
|
90
|
+
for name, param in signature.parameters.items():
|
91
|
+
value = {'kind' : str(param.kind)}
|
92
|
+
if param.default is not inspect.Parameter.empty:
|
93
|
+
value['default'] = param.default
|
94
|
+
|
95
|
+
if param.annotation is not inspect.Parameter.empty:
|
96
|
+
value['annotation'] = str(param.annotation)
|
97
|
+
|
98
|
+
sig_dict['parameters'][name] = value
|
99
|
+
return sig_dict
|
100
|
+
|
101
|
+
def python_file(target):
|
102
|
+
if isinstance(target, type) or type(target) in [types.ModuleType , types.MethodType,
|
103
|
+
types.FunctionType, types.TracebackType,
|
104
|
+
types.FrameType, types.CodeType]:
|
105
|
+
return inspect.getfile(target)
|
106
|
+
|
107
|
+
def type_file(target):
|
108
|
+
if isinstance(target, type):
|
109
|
+
return python_file(target)
|
110
|
+
|
111
|
+
|
112
|
+
function_line_number = get_line_number
|
113
|
+
method_line_number = get_line_number
|