ScriptCollection 4.2.46__py3-none-any.whl → 4.2.47__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.
@@ -3,6 +3,7 @@ import os
3
3
  from os import listdir
4
4
  from os.path import isfile, join, isdir
5
5
  import platform
6
+ import json
6
7
  import inspect
7
8
  import ctypes
8
9
  import hashlib
@@ -1396,3 +1397,38 @@ class GeneralUtilities:
1396
1397
  res = res.joinpath(part)
1397
1398
  result= res.read_bytes()
1398
1399
  return result
1400
+
1401
+ @staticmethod
1402
+ @check_arguments
1403
+ def escape_json_string_value(str_value: str) -> str:
1404
+ """For input 'a"b\\c' this function returns 'a\\"b\\\\c'. This function does not add surrounding quotes. It only escapes the characters inside the string."""
1405
+ json_escaped = json.dumps(str_value)
1406
+ return json_escaped[1:-1]
1407
+
1408
+ @staticmethod
1409
+ @check_arguments
1410
+ def escape_json_property_value(str_value: str) -> str:
1411
+ # remove all characters not in [a-zA-Z0-9_]
1412
+ sanitized = re.sub(r'[^a-zA-Z0-9_]', '', str_value)
1413
+
1414
+ # check if result starts with [a-zA-Z_]
1415
+ if not sanitized or len(sanitized) == 0 or not re.match(r'[a-zA-Z_]', sanitized[0]):
1416
+ raise ValueError(f"Invalid JSON property name after sanitizing: '{sanitized}'. Value must start with [a-zA-Z_].")
1417
+
1418
+ return sanitized
1419
+
1420
+ @staticmethod
1421
+ @check_arguments
1422
+ def escape_yaml_string_value(str_value: str) -> str:
1423
+ """For input 'a"b\\c' this function returns 'a\\"b\\\\c'. This function does not add surrounding quotes. It only escapes the characters inside the string."""
1424
+ result= GeneralUtilities.escape_json_string_value(str_value)
1425
+ #do other adaptions here if desired/required
1426
+ return result
1427
+
1428
+ @staticmethod
1429
+ @check_arguments
1430
+ def escape_yaml_property_value(str_value: str) -> str:
1431
+ result= GeneralUtilities.escape_json_property_value(str_value)
1432
+ #do other adaptions here if desired/required
1433
+ return result
1434
+
@@ -35,10 +35,120 @@ from .ProgramRunnerBase import ProgramRunnerBase
35
35
  from .ProgramRunnerPopen import ProgramRunnerPopen
36
36
  from .SCLog import SCLog, LogLevel
37
37
 
38
- version = "4.2.46"
38
+ version = "4.2.47"
39
39
  __version__ = version
40
40
 
41
+ class VSCodeWorkspaceShellTask:
42
+ label:str
43
+ description:str#nullable
44
+ work_dir:str#nullable
45
+ command:str
46
+ aliases:list[str]
47
+ allow_custom_arguments:bool
48
+
49
+ def __init__(self,label:str,description:str,work_dir:str,command:str,aliases:list[str],allow_custom_arguments:bool):
50
+ GeneralUtilities.assert_not_null(label,"label")
51
+ self.label=label
52
+ self.description=description
53
+ self.work_dir=work_dir
54
+ GeneralUtilities.assert_not_null(command,"command")
55
+ self.command=command
56
+ GeneralUtilities.assert_not_null(aliases,"aliases")
57
+ self.aliases=aliases
58
+ GeneralUtilities.assert_not_null(allow_custom_arguments,"allow_custom_arguments")
59
+ self.allow_custom_arguments=allow_custom_arguments
60
+
61
+
62
+ def serialize_for_vscode(self)->str:
63
+ aliases=",".join([f"\"{GeneralUtilities.escape_json_string_value(alias)}\"" for alias in self.aliases])
64
+
65
+ cwd:str=None
66
+ if self.work_dir is None:
67
+ cwd=GeneralUtilities.empty_string
68
+ else:
69
+ cwd=f"\"cwd\": \"{GeneralUtilities.escape_json_string_value(self.work_dir)}\""
70
+
71
+ desc:str=None
72
+ if self.description is None:
73
+ desc=GeneralUtilities.empty_string
74
+ else:
75
+ desc=f"\"description\": \"{GeneralUtilities.escape_json_string_value(self.description)}\","
76
+
77
+ result=f""" {{
78
+ "label": "{GeneralUtilities.escape_json_string_value(self.label)}",
79
+ "command": "{GeneralUtilities.escape_json_string_value(self.command)}",
80
+ "type": "shell",
81
+ "options": {{
82
+ {cwd}
83
+ }},
84
+ "aliases": [
85
+ {aliases}
86
+ ],
87
+ {desc}
88
+ "allowcustomarguments": {str(self.allow_custom_arguments).lower()}
89
+ }}"""
90
+ return result
91
+
92
+ class VSCodeWorkspaceMariaDBConnection:
93
+ name:str
94
+ previewLimit:int=50
95
+ server:str
96
+ port:int
97
+ database:str
98
+ username:str
99
+ password:str
100
+
101
+ def __init__(self,name:str,server,port,database,username,password):
102
+ GeneralUtilities.assert_not_null(name,"name")
103
+ self.name=name
104
+ GeneralUtilities.assert_not_null(server,"server")
105
+ self.server=server
106
+ GeneralUtilities.assert_not_null(port,"port")
107
+ self.port=port
108
+ GeneralUtilities.assert_not_null(database,"database")
109
+ self.database=database
110
+ GeneralUtilities.assert_not_null(username,"username")
111
+ self.username=username
112
+ GeneralUtilities.assert_not_null(password,"password")
113
+ self.password=password
114
+
115
+ def serialize_for_vscode(self)->str:
116
+ result=f""" {{
117
+ "name": "{GeneralUtilities.escape_json_string_value(self.name)}",
118
+ "mysqlOptions": {{
119
+ "authProtocol": "default",
120
+ "enableSsl": "Disabled"
121
+ }},
122
+ "previewLimit": {self.previewLimit},
123
+ "server": "{GeneralUtilities.escape_json_string_value(self.server)}",
124
+ "port": {self.port},
125
+ "driver": "MySQL",
126
+ "database": "{GeneralUtilities.escape_json_string_value(self.database)}",
127
+ "username": "{GeneralUtilities.escape_json_string_value(self.username)}",
128
+ "password": "{GeneralUtilities.escape_json_string_value(self.password)}"
129
+ }}
130
+ """
131
+ return result
132
+
41
133
 
134
+ class VSCodeWorkspaceMongoDBConnection:
135
+ name:str
136
+ connection_string:str
137
+
138
+ def __init__(self,name:str,connection_string:str):
139
+ GeneralUtilities.assert_not_null(name,"name")
140
+ self.name=name
141
+ GeneralUtilities.assert_not_null(connection_string,"connection_string")
142
+ self.connection_string=connection_string
143
+
144
+ def serialize_for_vscode(self)->str:
145
+ result=f""" {{
146
+ "name": "{GeneralUtilities.escape_json_string_value(self.name)}",
147
+ "connectionString": "{GeneralUtilities.escape_json_string_value(self.connection_string)}"
148
+ }}
149
+ """
150
+ return result
151
+
42
152
  class ScriptCollectionCore:
43
153
 
44
154
  # The purpose of this property is to use it when testing your code which uses scriptcollection for external program-calls.
@@ -2810,3 +2920,63 @@ OCR-content:
2810
2920
 
2811
2921
  languages=list(languages)
2812
2922
  return languages
2923
+
2924
+ @GeneralUtilities.check_arguments
2925
+ def parse_tasks_from_codeworkspace_file(self,code_workspace_file:str)->list[VSCodeWorkspaceShellTask]:
2926
+ result=[]
2927
+ jsoncontent = json.loads(GeneralUtilities.read_text_from_file(code_workspace_file))
2928
+ tasks = jsoncontent["tasks"]["tasks"]
2929
+ for task in tasks:
2930
+ if task["type"] == "shell":
2931
+ label: str = task["label"]
2932
+ name: str = GeneralUtilities.to_pascal_case(label)
2933
+ command:str= task["command"]
2934
+ work_dir:str = None
2935
+
2936
+ if "options" in task:
2937
+ options = task["options"]
2938
+ if "cwd" in options:
2939
+ work_dir = options["cwd"]
2940
+ work_dir = work_dir.replace("${workspaceFolder}", ".")
2941
+
2942
+ command_with_args = command
2943
+ if "args" in task:
2944
+ args = task["args"]
2945
+ if len(args) > 1:
2946
+ command_with_args = f"{command_with_args} {' '.join(args)}"
2947
+
2948
+ description: str =None
2949
+ if "description" in task:
2950
+ description = f'{label} ({task["description"]})'
2951
+ else:
2952
+ description = label
2953
+
2954
+
2955
+ alias_list:list[str]=[]
2956
+ name_lower=name.lower()
2957
+ if name!=name.lower():
2958
+ alias_list.append(name_lower)
2959
+
2960
+ if "aliases" in task:
2961
+ aliases = task["aliases"]
2962
+ for alias in aliases:
2963
+ alias_list.append(alias)
2964
+
2965
+ allow_custom_arguments:bool=False
2966
+ if "allowcustomarguments" in task:
2967
+ allow_custom_arguments = task["allowcustomarguments"]
2968
+
2969
+ result.append(VSCodeWorkspaceShellTask(name, description, work_dir, command_with_args, alias_list, allow_custom_arguments))
2970
+ return result
2971
+
2972
+ @GeneralUtilities.check_arguments
2973
+ def parse_mongodbconnection_from_codeworkspace_file(self,code_workspace_file:str)->list[VSCodeWorkspaceMongoDBConnection]:
2974
+ result=[]
2975
+ #TODO
2976
+ return result
2977
+
2978
+ @GeneralUtilities.check_arguments
2979
+ def parse_sqlconnection_from_codeworkspace_file(self,code_workspace_file:str)->list[VSCodeWorkspaceMariaDBConnection]:
2980
+ result=[]
2981
+ #TODO
2982
+ return result
@@ -17,7 +17,7 @@ from packaging import version
17
17
  import requests
18
18
  from lxml import etree
19
19
  from ..GeneralUtilities import GeneralUtilities
20
- from ..ScriptCollectionCore import ScriptCollectionCore
20
+ from ..ScriptCollectionCore import ScriptCollectionCore,VSCodeWorkspaceShellTask
21
21
  from ..SCLog import LogLevel
22
22
  from ..ImageUpdater import ConcreteImageUpdater, ImageUpdater, VersionEcholon
23
23
  from ..OCIImages.OCIImageManager import OCIImageManager
@@ -609,62 +609,30 @@ class TFCPS_Tools_General:
609
609
  self.__sc.assert_is_git_repository(repository_folder)
610
610
  workspace_file: str = self.__sc.find_file_by_extension(repository_folder, "code-workspace")
611
611
  task_file: str = repository_folder + "/Taskfile.yml"
612
- lines: list[str] = ["version: '3'", GeneralUtilities.empty_string, "tasks:", GeneralUtilities.empty_string]
613
- workspace_file_content: str = self.__sc.get_file_content(workspace_file)
614
- jsoncontent = json.loads(workspace_file_content)
615
- tasks = jsoncontent["tasks"]["tasks"]
616
- tasks.sort(key=lambda x: x["label"].split("/")[-1], reverse=False) # sort by the label of the task
617
- for task in tasks:
618
- if task["type"] == "shell":
619
-
620
- description: str = task["label"]
621
- name: str = GeneralUtilities.to_pascal_case(description)
622
- command = task["command"]
623
- relative_script_file = task["command"]
624
-
625
- relative_script_file = "."
626
- cwd: str = None
627
- if "options" in task:
628
- options = task["options"]
629
- if "cwd" in options:
630
- cwd = options["cwd"]
631
- cwd = cwd.replace("${workspaceFolder}", ".")
632
- cwd = cwd.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
633
- relative_script_file = cwd
634
- if len(relative_script_file) == 0:
635
- relative_script_file = "."
636
-
637
- command_with_args = command
638
- if "args" in task:
639
- args = task["args"]
640
- if len(args) > 1:
641
- command_with_args = f"{command_with_args} {' '.join(args)}"
642
-
643
- if "description" in task:
644
- additional_description = task["description"]
645
- description = f"{description} ({additional_description})"
646
-
647
- if append_cli_args_at_end:
648
- command_with_args = f"{command_with_args} {{{{.CLI_ARGS}}}}"
649
-
650
- description_literal = description.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
651
- command_with_args = command_with_args.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
652
-
653
- lines.append(f" {name}:")
654
- lines.append(f' desc: "{description_literal}"')
655
- lines.append(' silent: true')
656
- if cwd is not None:
657
- lines.append(f' dir: "{cwd}"')
658
- lines.append(" cmds:")
659
- lines.append(f' - "{command_with_args}"')
660
- lines.append(' aliases:')
661
- lines.append(f' - {name.lower()}')
662
- if "aliases" in task:
663
- aliases = task["aliases"]
664
- for alias in aliases:
665
- lines.append(f' - {alias}')
666
- lines.append(GeneralUtilities.empty_string)
667
-
612
+ lines: list[str] = [
613
+ "version: '3'", GeneralUtilities.empty_string,
614
+ "tasks:", GeneralUtilities.empty_string,
615
+ ]
616
+ tasks = self.__sc.parse_tasks_from_codeworkspace_file(workspace_file)
617
+ tasks.sort(key=lambda task: task.label, reverse=False)
618
+ for t in tasks:
619
+ task:VSCodeWorkspaceShellTask = t
620
+ lines.append(f" {GeneralUtilities.escape_yaml_property_value(task.label)}:")
621
+ if task.description is not None:
622
+ lines.append(f' desc: "{GeneralUtilities.escape_yaml_string_value(task.description)}"')
623
+ lines.append(' silent: true')
624
+ if task.work_dir is not None:
625
+ lines.append(f' dir: "{GeneralUtilities.escape_yaml_string_value(task.work_dir)}"')
626
+ lines.append(" cmds:")
627
+ command=GeneralUtilities.escape_yaml_string_value(task.command)
628
+ if task.allow_custom_arguments:
629
+ command=command+" {{.CLI_ARGS}}"
630
+ lines.append(f' - "{command}"')
631
+ if task.aliases!=None and len(task.aliases) > 0:
632
+ lines.append(" aliases:")
633
+ for alias in task.aliases:
634
+ lines.append(f' - {GeneralUtilities.escape_yaml_property_value(alias)}')
635
+ lines.append(GeneralUtilities.empty_string)
668
636
  self.__sc.set_file_content(task_file, "\n".join(lines))
669
637
  else:
670
638
  self.__sc.run_program("scgeneratetasksfilefromworkspacefile", f"--repositoryfolder {repository_folder}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ScriptCollection
3
- Version: 4.2.46
3
+ Version: 4.2.47
4
4
  Summary: The ScriptCollection is the place for reusable scripts.
5
5
  Home-page: https://github.com/anionDev/ScriptCollection
6
6
  Author: Marius Göcke
@@ -1,7 +1,7 @@
1
1
  ScriptCollection/AnionBuildPlatform.py,sha256=Sw35p6gKZ4qjvaDWtrnWW3iCHdUpHSUjtq5tc2iL_AI,11522
2
2
  ScriptCollection/CertificateUpdater.py,sha256=aCBF-bym5renP5joL32ev7WZW8HHh6hNm_mz6_hQKLc,9617
3
3
  ScriptCollection/Executables.py,sha256=18zrelUGO8wlpy6mM1DE-KMX6_m5mS7dzhgdjx-vCIs,44308
4
- ScriptCollection/GeneralUtilities.py,sha256=ouIbf7ivnMztSIFRd-x8ziOFncfoGby-ibdL0be_Q3o,59758
4
+ ScriptCollection/GeneralUtilities.py,sha256=jarMc5sD3ifttHaICzlVsDweL0gWzOJm4W4VtW4CEWc,61313
5
5
  ScriptCollection/HTTPMaintenanceOverheadHelper.py,sha256=TToNtyO1XzsMbBsTBf3o0xgOK0v4Jf03qw2Z0xb2nCk,2007
6
6
  ScriptCollection/ImageUpdater.py,sha256=fxyz3oZkKlqyieYiyj0Yi1dQjOJEuHhu0WvL_JHsB90,38905
7
7
  ScriptCollection/ProcessesRunner.py,sha256=o5raxIt3lknNPoPrjNzJ2bprRPJ3SnL0rrR7crraD7E,1523
@@ -10,7 +10,7 @@ ScriptCollection/ProgramRunnerMock.py,sha256=uTu-aFle1W_oKjeQEmuPsFPQpvo0kRf2FrR
10
10
  ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
11
11
  ScriptCollection/ProgramRunnerSudo.py,sha256=_khC3xuTdrPoLluBJZWfldltmmuKltABJPcbjZSFW-4,4835
12
12
  ScriptCollection/SCLog.py,sha256=8TRy1LeYMsPOIuWUcnUNNbO5pd-cNBS-3cn-kdzP8FU,4768
13
- ScriptCollection/ScriptCollectionCore.py,sha256=KU-wkr5KjUvJ9j4lO4rj0x3uDExoEhST8JmwD776bNE,157835
13
+ ScriptCollection/ScriptCollectionCore.py,sha256=6ebRc8enTzphWybayRwWBor_ak9APz3fqEpnqgwWsmQ,164482
14
14
  ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  ScriptCollection/OCIImages/AbstractImageHandler.py,sha256=Pa72cRybzBroy-OzzxZqKpFB58iY2kcf5yFfIAIPfXk,1627
16
16
  ScriptCollection/OCIImages/OCIImageManager.py,sha256=xTYnj68CRDkTjJiibSov1HSI0djmmcY6mwP6_fD0kCM,7141
@@ -31,7 +31,7 @@ ScriptCollection/TFCPS/TFCPS_Generic.py,sha256=O-0guM_LJCcZmPZJhMgTvXD2RXUJEBWWv
31
31
  ScriptCollection/TFCPS/TFCPS_MergeToMain.py,sha256=-Ev9D3bZDlUk2WFQhcmvzQ3FCS97OdsVUd0koAdmpZc,7474
32
32
  ScriptCollection/TFCPS/TFCPS_MergeToStable.py,sha256=Ajfy2pLajTuU6UpwItHt4C2a-gLF3gPc4z6BktL3Cio,22163
33
33
  ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py,sha256=f0Uq1cA_4LvmL72cal0crrbKF6PcxL13D9wBKuQ1YBw,2328
34
- ScriptCollection/TFCPS/TFCPS_Tools_General.py,sha256=5yyWne5o4TygR4Sby1F-g7uL-QDAGWNxljnfQMe1dzU,94066
34
+ ScriptCollection/TFCPS/TFCPS_Tools_General.py,sha256=D8yTq-CoC8rL8FM-P9qFtfQbir8hHwnsTSniBlP1BBA,92525
35
35
  ScriptCollection/TFCPS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py,sha256=krF-SYvXyG1cAepj-5witV76suBvEumTApn7nY6Zin0,10564
37
37
  ScriptCollection/TFCPS/Docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -48,8 +48,8 @@ ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py,sha256=wKB5t-K7p3
48
48
  ScriptCollection/TFCPS/NodeJS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py,sha256=nLw_eSUd_56jjgfcAvtUyzecSZ14mYmNJl0iu-1YNVk,13496
50
50
  ScriptCollection/TFCPS/Python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- scriptcollection-4.2.46.dist-info/METADATA,sha256=ZDl1gkJuJBya-IgvvDWL3L5gXqAdC3jdz6Zt3p3qW4A,7690
52
- scriptcollection-4.2.46.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
53
- scriptcollection-4.2.46.dist-info/entry_points.txt,sha256=FUA-dAZQISQRwFDJvo-tVVTVE0vrH0f0VR9XckeRvv0,4621
54
- scriptcollection-4.2.46.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
55
- scriptcollection-4.2.46.dist-info/RECORD,,
51
+ scriptcollection-4.2.47.dist-info/METADATA,sha256=ueN3DpRK5RaqhTzr-PpIhlB6BQN0vD_WKCOhESx2JB0,7690
52
+ scriptcollection-4.2.47.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
53
+ scriptcollection-4.2.47.dist-info/entry_points.txt,sha256=FUA-dAZQISQRwFDJvo-tVVTVE0vrH0f0VR9XckeRvv0,4621
54
+ scriptcollection-4.2.47.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
55
+ scriptcollection-4.2.47.dist-info/RECORD,,