Giter Club home page Giter Club logo

Comments (2)

achekery avatar achekery commented on August 19, 2024

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.

achekery avatar achekery commented on August 19, 2024

Added this qol change here

#989

from invoke.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.