Return a Windows argv-escaped version of the string *s* Windows has potentially bizarre rules depending on where you look. When spawning a process via the Windows C runtime the rules are as follows: https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments To sum
(s)
| 290 | |
| 291 | |
| 292 | def _windows_argv_quote(s): |
| 293 | """Return a Windows argv-escaped version of the string *s* |
| 294 | |
| 295 | Windows has potentially bizarre rules depending on where you look. When |
| 296 | spawning a process via the Windows C runtime the rules are as follows: |
| 297 | |
| 298 | https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments |
| 299 | |
| 300 | To summarize the relevant bits: |
| 301 | |
| 302 | * Only space and tab are valid delimiters |
| 303 | * Double quotes are the only valid quotes |
| 304 | * Backslash is interpreted literally unless it is part of a chain that |
| 305 | leads up to a double quote. Then the backslashes escape the backslashes, |
| 306 | and if there is an odd number the final backslash escapes the quote. |
| 307 | |
| 308 | :param s: A string to escape |
| 309 | :return: An escaped string |
| 310 | """ |
| 311 | if not s: |
| 312 | return '""' |
| 313 | |
| 314 | buff = [] |
| 315 | num_backslashes = 0 |
| 316 | for character in s: |
| 317 | if character == '\\': |
| 318 | # We can't simply append backslashes because we don't know if |
| 319 | # they will need to be escaped. Instead we separately keep track |
| 320 | # of how many we've seen. |
| 321 | num_backslashes += 1 |
| 322 | elif character == '"': |
| 323 | if num_backslashes > 0: |
| 324 | # The backslashes are part of a chain that lead up to a |
| 325 | # double quote, so they need to be escaped. |
| 326 | buff.append('\\' * (num_backslashes * 2)) |
| 327 | num_backslashes = 0 |
| 328 | |
| 329 | # The double quote also needs to be escaped. The fact that we're |
| 330 | # seeing it at all means that it must have been escaped in the |
| 331 | # original source. |
| 332 | buff.append('\\"') |
| 333 | else: |
| 334 | if num_backslashes > 0: |
| 335 | # The backslashes aren't part of a chain leading up to a |
| 336 | # double quote, so they can be inserted directly without |
| 337 | # being escaped. |
| 338 | buff.append('\\' * num_backslashes) |
| 339 | num_backslashes = 0 |
| 340 | buff.append(character) |
| 341 | |
| 342 | # There may be some leftover backslashes if they were on the trailing |
| 343 | # end, so they're added back in here. |
| 344 | if num_backslashes > 0: |
| 345 | buff.append('\\' * num_backslashes) |
| 346 | |
| 347 | new_s = ''.join(buff) |
| 348 | if ' ' in new_s or '\t' in new_s: |
| 349 | # If there are any spaces or tabs then the string needs to be double |
no outgoing calls
no test coverage detected