Comments (2)
Created tasks.py for demo:
# pylint: disable-next=E0401:import-error
from invoke import task # type: ignore
@task(default=True)
def demo_qol_shellpathspaces(ctx):
"""Config run shell should handle paths with spaces."""
# pylint: disable=C0415:import-outside-toplevel
import shutil
# pylint: disable-next=E0401:import-error
from invoke.exceptions import UnexpectedExit # type: ignore
class Kernel32DllExt:
"""Namespace for `kernel32.dll` extensions."""
# Disable pylint error message when importing from namespaces.
# pylint: disable=C0415:import-outside-toplevel
# Useful for any `invoke` tasks that set `config.run.shell` value
# on Windows platform because `invoke` does not handle shell
# executable files with paths containing spaces. Note the default
# shell for `invoke` is `cmd`, which has been superceded by `pwsh`.
# It would be nice to have this handled by `invoke` automatically.
@staticmethod
def get_short_path_name(long_path):
"""Get short path form for long path.
This API converts path strings from the posix format used by
`pathlib.Path` to the 8.3 format used by earlier tools on the
Windows platform.
"""
import ctypes
from ctypes import wintypes
# Access `GetShortPathNameW()` function from `kernel32.dll`.
kernel32_func = ctypes.windll.kernel32.GetShortPathNameW
kernel32_func.argtypes = [
wintypes.LPCWSTR,
wintypes.LPWSTR,
wintypes.DWORD,
]
kernel32_func.restype = wintypes.DWORD
# Call function to get short path form.
buffer_size = 0
while True:
buffer_array = ctypes.create_unicode_buffer(buffer_size)
required_size = kernel32_func(long_path, buffer_array, buffer_size)
if required_size > buffer_size:
buffer_size = required_size
else:
return buffer_array.value
def _demo(ctx_, index_, shell_path_, command_):
ctx.config.run.shell = shell_path_
print(f"** Demo #{index_}: with {shell_path_=} run {command_=}")
try:
res_ = ctx_.run(command)
except (OSError, FileNotFoundError, TypeError, UnexpectedExit) as _exc:
print(f"** Demo Error: {_exc=}\n")
else:
print(f"** Demo Success!: {res_=}\n")
ctx.config.run.echo = True
command = "git status --porcelain"
for index, shell_name in enumerate([
"cmd.exe",
"pwsh.exe",
], start=1):
shell_which = shutil.which(shell_name)
print(f"** Setup Start: {shell_name=}, {shell_which=}")
try:
_demo(ctx, f"{index}-whichformat", shell_which, command)
_demo(ctx, f"{index}-83format", Kernel32DllExt.get_short_path_name(shell_which), command)
except TypeError as exc:
print(f"** Setup Error: {exc=}")
finally:
print("==========================================")
Results with invoke main:
** Setup Start: shell_name='cmd.exe', shell_which='C:\\WINDOWS\\system32\\cmd.exe'
** Demo #1-whichformat: with shell_path_='C:\\WINDOWS\\system32\\cmd.exe' run command_='git status --porcelain'
�[1;37mgit status --porcelain�[0m
M projects/bce-patch-builder/tasks.py
** Demo Success!: res_=<Result cmd='git status --porcelain' exited=0>
** Demo #1-83format: with shell_path_='C:\\WINDOWS\\system32\\cmd.exe' run command_='git status --porcelain'
�[1;37mgit status --porcelain�[0m
M projects/bce-patch-builder/tasks.py
The argument 'Files\PowerShell\7\pwsh.exe' is not recognized as the name of a script file. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
** Demo Success!: res_=<Result cmd='git status --porcelain' exited=0>
==========================================
** Setup Start: shell_name='pwsh.exe', shell_which='C:\\Program Files\\PowerShell\\7\\pwsh.exe'
** Demo #2-whichformat: with shell_path_='C:\\Program Files\\PowerShell\\7\\pwsh.exe' run command_='git status --porcelain'
�[1;37mgit status --porcelain�[0m
Usage: pwsh[.exe] [-Login] [[-File] <filePath> [args]]
[-Command { - | <script-block> [-args <arg-array>]
| <string> [<CommandParameters>] } ]
[-CommandWithArgs <string> [<CommandParameters>]
[-ConfigurationName <string>] [-ConfigurationFile <filePath>]
[-CustomPipeName <string>] [-EncodedCommand <Base64EncodedCommand>]
[-ExecutionPolicy <ExecutionPolicy>] [-InputFormat {Text | XML}]
[-Interactive] [-MTA] [-NoExit] [-NoLogo] [-NonInteractive] [-NoProfile]
[-NoProfileLoadTime] [-OutputFormat {Text | XML}]
[-SettingsFile <filePath>] [-SSHServerMode] [-STA]
[-Version] [-WindowStyle <style>]
[-WorkingDirectory <directoryPath>]
pwsh[.exe] -h | -Help | -? | /?
PowerShell Online Help https://aka.ms/powershell-docs
All parameters are case-insensitive.
** Demo Error: _exc=<UnexpectedExit: cmd='git status --porcelain' exited=64>
** Demo #2-83format: with shell_path_='C:\\PROGRA~1\\POWERS~1\\7\\pwsh.exe' run command_='git status --porcelain'
�[1;37mgit status --porcelain�[0m
M projects/bce-patch-builder/tasks.py
** Demo Success!: res_=<Result cmd='git status --porcelain' exited=0>
==========================================
from invoke.
Added this qol change here
from invoke.
Related Issues (20)
- Possible third option
- Autocomplete after `inv --help` doesn't work as expected
- Support for arm64 architecture? HOT 2
- clint issues and project seems abandoned HOT 2
- getargspec deprecated in Python 3.0 - now gone HOT 2
- loader.py: Wrong directory inserted into sys.path for modules HOT 1
- Change default shell without a config file or Context? HOT 3
- Task decorator removes docstring HOT 1
- Run tasks relative to `tasks.py` HOT 2
- How to manually set short flags? HOT 1
- context.run(): Expose API to pass command and separate args instead of a single string HOT 2
- Specify a config file per Collection... possible?
- Collection mix-up when cross importing invoke tasks
- Running post tasks even if the main task fail
- `--help` after the command treats `--help` as positional argument HOT 2
- Is there support for making invoke.yaml context settings cli flags?
- EncodeWarning's when running on python >= 3.11
- @task(pre=[call(setup, 'qwe')]) fails with "NameError: name 'call' is not defined" HOT 1
- Is it possible to only mock one command and run the rest with MockContext?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from invoke.