cengal.os.execute.versions.v_0.execute

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  5# 
  6# Licensed under the Apache License, Version 2.0 (the "License");
  7# you may not use this file except in compliance with the License.
  8# You may obtain a copy of the License at
  9# 
 10#     http://www.apache.org/licenses/LICENSE-2.0
 11# 
 12# Unless required by applicable law or agreed to in writing, software
 13# distributed under the License is distributed on an "AS IS" BASIS,
 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15# See the License for the specific language governing permissions and
 16# limitations under the License.
 17
 18
 19__all__ = [
 20    'escape_text', 
 21    'handle_spaces', 
 22    'escape_param', 
 23    'prepare_params', 
 24    'prepare_py_params', 
 25    'prepare_command', 
 26    'prepare_py_command', 
 27]
 28
 29
 30"""
 31Module Docstring
 32Docstrings: http://www.python.org/dev/peps/pep-0257/
 33"""
 34
 35__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 36__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 37__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 38__license__ = "Apache License, Version 2.0"
 39__version__ = "4.4.1"
 40__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 41__email__ = "gtalk@butenkoms.space"
 42# __status__ = "Prototype"
 43__status__ = "Development"
 44# __status__ = "Production"
 45
 46
 47from cengal.system import OS_TYPE
 48
 49import os
 50import sys
 51from typing import Sequence, Union, List
 52
 53
 54def escape_text(text: str) -> str:
 55    """Resulting text can be used safely inside a brackets:
 56
 57    param = f'--define:MyVar="{escape_text(param)}"'
 58
 59    Args:
 60        text (str): _description_
 61
 62    Returns:
 63        str: _description_
 64    """
 65    if 'Windows' == OS_TYPE:
 66        text = text.replace('"', '""')
 67    else:
 68        text = text.translate(str.maketrans({'\\': '\\\\', '"': '\\"', '$': '\\$', '`': '\\`'}))
 69
 70    return text
 71
 72
 73def handle_spaces(text: str) -> str:
 74    if ' ' in text:
 75        if 'Windows' == OS_TYPE:
 76            # text = '"{}"'.format(text)
 77            need_to_wrap: bool = False
 78            start = 0
 79            while True:
 80                space_pos = text.find(' ', start)
 81                if -1 >= space_pos:
 82                    break
 83
 84                lbracket_pos = text.find('"', start)
 85                rbracket_pos = text.find('"', space_pos + 1)
 86                if (-1 < lbracket_pos) and (-1 < rbracket_pos) and (lbracket_pos < space_pos < rbracket_pos):
 87                    start = rbracket_pos + 1
 88                    continue
 89                else:
 90                    need_to_wrap = True
 91                    break
 92            
 93            if need_to_wrap:
 94                text = text.replace('"', '""')
 95                text = '"{}"'.format(text)
 96        else:
 97            # text = text.replace(' ', '\\ ')
 98            unescaped_spaces: List[int] = list()
 99            probably_unescaped_spaces: List[int] = list()
100            escaped: bool = False
101            lbracket_found: bool = False
102            for index, char in enumerate(text):
103                if escaped:
104                    escaped = False
105                    continue
106
107                if '\\' == char:
108                    escaped = True
109                elif ' ' == char:
110                    if lbracket_found:
111                        probably_unescaped_spaces.append(index)
112                    else:
113                        unescaped_spaces.append(index)
114                elif '"' == char:
115                    if lbracket_found:
116                        probably_unescaped_spaces.clear()
117                        lbracket_found = False
118                    else:
119                        lbracket_found = True
120
121            unescaped_spaces.extend(probably_unescaped_spaces)
122            if unescaped_spaces:
123                characters: List[str] = list(text)
124                for space_pos in reversed(unescaped_spaces):
125                    characters.insert(space_pos, '\\')
126                
127                text = ''.join(characters)
128
129    return text
130
131
132def escape_param(text: str) -> str:
133    return handle_spaces(escape_text(text))
134
135
136def prepare_params(params: Sequence[str]) -> List[str]:
137    result: List[str] = list()
138    for param in params:
139        result.append(handle_spaces(param))
140    
141    return result
142
143
144def prepare_py_params(params: Sequence[str]) -> List[str]:
145    result: List[str] = [handle_spaces(sys.executable)]
146    for param in params:
147        result.append(handle_spaces(param))
148    
149    return result
150
151
152def prepare_command(command: str, params: Union[str, Sequence[str]] = None) -> str:
153    command = handle_spaces(command)
154    params_has_spaces_under_windows: bool = False
155    if (params is not None) and (not isinstance(params, str)):
156        new_params: List[str] = list()
157        for param in params:
158            if ('Windows' == OS_TYPE) and ' ' in param:
159                params_has_spaces_under_windows = True
160                
161            new_params.append(handle_spaces(param))
162
163        params = ' '.join(new_params)
164    
165    if params:
166        command = '{} {}'.format(command, params)
167        if params_has_spaces_under_windows:
168            command = '"{}"'.format(command)
169    
170    return command
171
172
173def prepare_py_command(params: Union[str, Sequence[str]] = None) -> str:
174    return prepare_command(sys.executable, params)
def escape_text(text: str) -> str:
55def escape_text(text: str) -> str:
56    """Resulting text can be used safely inside a brackets:
57
58    param = f'--define:MyVar="{escape_text(param)}"'
59
60    Args:
61        text (str): _description_
62
63    Returns:
64        str: _description_
65    """
66    if 'Windows' == OS_TYPE:
67        text = text.replace('"', '""')
68    else:
69        text = text.translate(str.maketrans({'\\': '\\\\', '"': '\\"', '$': '\\$', '`': '\\`'}))
70
71    return text

Resulting text can be used safely inside a brackets:

param = f'--define:MyVar="{escape_text(param)}"'

Args: text (str): _description_

Returns: str: _description_

def handle_spaces(text: str) -> str:
 74def handle_spaces(text: str) -> str:
 75    if ' ' in text:
 76        if 'Windows' == OS_TYPE:
 77            # text = '"{}"'.format(text)
 78            need_to_wrap: bool = False
 79            start = 0
 80            while True:
 81                space_pos = text.find(' ', start)
 82                if -1 >= space_pos:
 83                    break
 84
 85                lbracket_pos = text.find('"', start)
 86                rbracket_pos = text.find('"', space_pos + 1)
 87                if (-1 < lbracket_pos) and (-1 < rbracket_pos) and (lbracket_pos < space_pos < rbracket_pos):
 88                    start = rbracket_pos + 1
 89                    continue
 90                else:
 91                    need_to_wrap = True
 92                    break
 93            
 94            if need_to_wrap:
 95                text = text.replace('"', '""')
 96                text = '"{}"'.format(text)
 97        else:
 98            # text = text.replace(' ', '\\ ')
 99            unescaped_spaces: List[int] = list()
100            probably_unescaped_spaces: List[int] = list()
101            escaped: bool = False
102            lbracket_found: bool = False
103            for index, char in enumerate(text):
104                if escaped:
105                    escaped = False
106                    continue
107
108                if '\\' == char:
109                    escaped = True
110                elif ' ' == char:
111                    if lbracket_found:
112                        probably_unescaped_spaces.append(index)
113                    else:
114                        unescaped_spaces.append(index)
115                elif '"' == char:
116                    if lbracket_found:
117                        probably_unescaped_spaces.clear()
118                        lbracket_found = False
119                    else:
120                        lbracket_found = True
121
122            unescaped_spaces.extend(probably_unescaped_spaces)
123            if unescaped_spaces:
124                characters: List[str] = list(text)
125                for space_pos in reversed(unescaped_spaces):
126                    characters.insert(space_pos, '\\')
127                
128                text = ''.join(characters)
129
130    return text
def escape_param(text: str) -> str:
133def escape_param(text: str) -> str:
134    return handle_spaces(escape_text(text))
def prepare_params(params: Sequence[str]) -> List[str]:
137def prepare_params(params: Sequence[str]) -> List[str]:
138    result: List[str] = list()
139    for param in params:
140        result.append(handle_spaces(param))
141    
142    return result
def prepare_py_params(params: Sequence[str]) -> List[str]:
145def prepare_py_params(params: Sequence[str]) -> List[str]:
146    result: List[str] = [handle_spaces(sys.executable)]
147    for param in params:
148        result.append(handle_spaces(param))
149    
150    return result
def prepare_command(command: str, params: Union[str, Sequence[str]] = None) -> str:
153def prepare_command(command: str, params: Union[str, Sequence[str]] = None) -> str:
154    command = handle_spaces(command)
155    params_has_spaces_under_windows: bool = False
156    if (params is not None) and (not isinstance(params, str)):
157        new_params: List[str] = list()
158        for param in params:
159            if ('Windows' == OS_TYPE) and ' ' in param:
160                params_has_spaces_under_windows = True
161                
162            new_params.append(handle_spaces(param))
163
164        params = ' '.join(new_params)
165    
166    if params:
167        command = '{} {}'.format(command, params)
168        if params_has_spaces_under_windows:
169            command = '"{}"'.format(command)
170    
171    return command
def prepare_py_command(params: Union[str, Sequence[str]] = None) -> str:
174def prepare_py_command(params: Union[str, Sequence[str]] = None) -> str:
175    return prepare_command(sys.executable, params)