Last active
September 26, 2025 19:38
-
-
Save dlenski/234e2fcf5eaa16687b7ce2c04ed01ad4 to your computer and use it in GitHub Desktop.
Revisions
-
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 3 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -126,15 +126,14 @@ def _convert_paths(winenv: Mapping, paths: Union[Container, bool] = True) -> Map if args.associative: print(f'declare -A {args.associative}') for var, val in winenv.items(): print(f'{args.associative}[{shlex.quote(var)}]={shlex.quote(val)}') elif args.format == 'json': json.dump(winenv, sys.stdout) else: kw = 'setenv' if args.format == 'csh' else 'export' for var, val in winenv.items(): if not var.isidentifier(): warn(f'Windows environment variable {var!r} is not a valid POSIX shell identifier, skipping.') else: print(f'{kw} {args.prefix}{var}={shlex.quote(val)}') -
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 1 addition and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,7 +23,6 @@ import subprocess as sp import json from typing import Union, Container, Mapping from pathlib import PureWindowsPath, PurePosixPath import shlex @@ -35,7 +34,6 @@ BACKSLASH = '\\' DOUBLE_BACKSLASH = '\\\\' POWERSHELL_EXE = '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe' @@ -139,4 +137,4 @@ def _convert_paths(winenv: Mapping, paths: Union[Container, bool] = True) -> Map warn(f'Windows environment variable {var!r} is not a valid POSIX shell identifier, skipping.') else: print(f'{delim}{kw} {args.prefix}{var}={shlex.quote(val)}', end='') delim='; ' -
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 8 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,6 +23,7 @@ import subprocess as sp import json import os from typing import Union, Container, Mapping from pathlib import PureWindowsPath, PurePosixPath import shlex @@ -34,6 +35,7 @@ BACKSLASH = '\\' DOUBLE_BACKSLASH = '\\\\' DETECT_WSL_PATH = '/proc/sys/fs/binfmt_misc/WSLInterop' POWERSHELL_EXE = '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe' @@ -126,13 +128,15 @@ def _convert_paths(winenv: Mapping, paths: Union[Container, bool] = True) -> Map if args.associative: print(f'declare -A {args.associative}') print('; '.join(f'{args.associative}[{shlex.quote(var)}]={shlex.quote(val)}')) elif args.format == 'json': json.dump(winenv, sys.stdout) else: kw = 'setenv' if args.format == 'csh' else 'export' delim = '' for var, val in winenv.items(): if not var.isidentifier(): warn(f'Windows environment variable {var!r} is not a valid POSIX shell identifier, skipping.') else: print(f'{delim}{kw} {args.prefix}{var}={shlex.quote(val)}', end='') delim='; ' -
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,7 +23,6 @@ import subprocess as sp import json from typing import Union, Container, Mapping from pathlib import PureWindowsPath, PurePosixPath import shlex @@ -35,7 +34,6 @@ BACKSLASH = '\\' DOUBLE_BACKSLASH = '\\\\' POWERSHELL_EXE = '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe' -
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 4 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,6 +23,7 @@ import subprocess as sp import json import os from typing import Union, Container, Mapping from pathlib import PureWindowsPath, PurePosixPath import shlex @@ -34,14 +35,16 @@ BACKSLASH = '\\' DOUBLE_BACKSLASH = '\\\\' DETECT_WSL_PATH = '/proc/sys/fs/binfmt_misc/WSLInterop' POWERSHELL_EXE = '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe' def _load_winenv() -> dict: env2json = '[System.Environment]::GetEnvironmentVariables() | ConvertTo-Json' # Robustness fixes based on https://github.com/wslutilities/wslu/blob/1bb1b53c0532394a1433b2eaa041b1c1e6ce0b69/src/wslu-header#L290, # with the addition of ErrorActionPreference from https://stackoverflow.com/a/9949909/20789. cli = [ POWERSHELL_EXE, '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', '$ErrorActionPreference = "Stop"; [Console]::OutputEncoding = [System.Text.Encoding]::UTF8; ' + env2json ] -
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,7 +4,7 @@ Access Windows environment variables from Python under WSL The :py:data:`winenv` and py:data:`winenv_wslpath` objects are immutable mappings, loaded at module import time. py:data:`winenv` contains the unmodified Windows environment variables, while py:data:`winenv_wslpath` attempts to convert all ``PATH``-like -
dlenski revised this gist
Sep 26, 2025 . 1 changed file with 16 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ #!/usr/bin/env python3 r''' Access Windows environment variables from Python under WSL @@ -25,10 +27,14 @@ from pathlib import PureWindowsPath, PurePosixPath import shlex import sys from warnings import warn __all__ = ['winenv', 'winenv_wslpath'] BACKSLASH = '\\' DOUBLE_BACKSLASH = '\\\\' def _load_winenv() -> dict: env2json = '[System.Environment]::GetEnvironmentVariables() | ConvertTo-Json' @@ -52,21 +58,21 @@ def _convert_paths(winenv: Mapping, paths: Union[Container, bool] = True) -> Map return winenv j = {} for var, vals in winenv.items(): convert = vals.startswith(BACKSLASH) or (vals[0:1].isalpha() and vals[1:2] == ':') if paths == True else var in paths if convert: winvals = map(PureWindowsPath, vals.split(';')) outvals = [] for val in winvals: if val.anchor.startswith(DOUBLE_BACKSLASH): warn(f'Windows environment variable {var!r} contains UNC path {shlex.quote(str(val))}, not converting') elif val.anchor == BACKSLASH: anchor = winenv.get('SystemDrive', 'C:') warn(f'Windows environment variable {var!r} contains driveless path {shlex.quote(str(val))}, assuming {anchor!r}') val = PurePosixPath(f'/mnt/{anchor.rstrip(BACKSLASH).removesuffix(":").lower()}') / val.relative_to(val.anchor) elif not val.is_absolute(): warn(f'Windows environment variable {var!r} contains relative path {shlex.quote(str(val))}, not converting') else: val = PurePosixPath(f'/mnt/{val.anchor.rstrip(BACKSLASH).removesuffix(":").lower()}') / val.relative_to(val.anchor) outvals.append(str(val)) else: j[var] = ':'.join(outvals) @@ -81,6 +87,11 @@ def _convert_paths(winenv: Mapping, paths: Union[Container, bool] = True) -> Map winenv_wslpath = MappingProxyType(_convert_paths(winenv)) else: # Monkey-patch reduced warning verbosity (see https://stackoverflow.com/a/2187390) import warnings _fw = warnings.formatwarning warnings.formatwarning = lambda *args, **kwargs: _fw(*args, **kwargs).splitlines(keepends=True)[0] import argparse p = argparse.ArgumentParser( description='''Capture Windows environment variables in a format that can be used under Windows Subsystem for Linux. -
dlenski created this gist
Jun 14, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,126 @@ r''' Access Windows environment variables from Python under WSL The :py:data:`winenv` and py:data:`winenv_wslpath` objects are immutable mappings, lazy-loaded upon initial usage. py:data:`winenv` contains the unmodified Windows environment variables, while py:data:`winenv_wslpath` attempts to convert all ``PATH``-like variables to WSL paths. Example: from wslenv import winenv, winenv_wslpath print("Windows username is", winenv['USERNAME']) print("WSL-ified Windows PATH is", winenv_wslpath['PATH']) This requires WSL and PowerShell 3.0 installed in the standard location of ``C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe``. It grew out of https://stackoverflow.com/a/79662726 ''' import subprocess as sp import json from typing import Union, Container, Mapping from pathlib import PureWindowsPath, PurePosixPath import shlex import sys from warnings import warn __all__ = ['winenv', 'winenv_wslpath'] def _load_winenv() -> dict: env2json = '[System.Environment]::GetEnvironmentVariables() | ConvertTo-Json' # Robustness fixes based on https://github.com/wslutilities/wslu/blob/1bb1b53c0532394a1433b2eaa041b1c1e6ce0b69/src/wslu-header#L290, # with the addition of ErrorActionPreference from https://stackoverflow.com/a/9949909/20789. cli = [ '/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', '$ErrorActionPreference = "Stop"; [Console]::OutputEncoding = [System.Text.Encoding]::UTF8; ' + env2json ] try: return json.loads(sp.check_output(cli, stdin=sp.DEVNULL)) except sp.CalledProcessError as exc: raise NotImplementedError("Could not get environment variables from PowerShell in JSON format; PowerShell 3.0+ is required") from exc except FileNotFoundError as exc: raise NotImplementedError(f"Could not invoke {cli[0]}; may not be running under WSL") from exc def _convert_paths(winenv: Mapping, paths: Union[Container, bool] = True) -> Mapping: if not paths: return winenv j = {} for var, vals in winenv.items(): convert = vals.startswith('\\') or vals[1:2] == ':' if paths == True else var in paths if convert: winvals = map(PureWindowsPath, vals.split(';')) outvals = [] for val in winvals: if val.anchor.startswith('\\\\'): warn(f'Windows environment variable {var!r} contains UNC path {shlex.quote(str(val))}, not converting') elif val.anchor == '\\': anchor = winenv.get('SystemDrive', 'C:') warn(f'Windows environment variable {var!r} contains driveless path {shlex.quote(str(val))}, assuming {anchor!r}') val = PurePosixPath(f'/mnt/{anchor.rstrip("\\").removesuffix(":").lower()}') / val.relative_to(val.anchor) elif not val.is_absolute(): warn(f'Windows environment variable {var!r} contains relative path {shlex.quote(str(val))}, not converting') else: val = PurePosixPath(f'/mnt/{val.anchor.rstrip("\\").removesuffix(":").lower()}') / val.relative_to(val.anchor) outvals.append(str(val)) else: j[var] = ':'.join(outvals) else: j[var] = vals return j if __name__ != '__main__': from types import MappingProxyType winenv = MappingProxyType(_load_winenv()) winenv_wslpath = MappingProxyType(_convert_paths(winenv)) else: import argparse p = argparse.ArgumentParser( description='''Capture Windows environment variables in a format that can be used under Windows Subsystem for Linux. Requires PowerShell 3.0+ (Windows 8+). Under bash or other POSIX Bourne shells, use: eval "$(%(prog)s)"''') g = p.add_argument_group('Path conversion') x = g.add_mutually_exclusive_group() x.add_argument('-w', '--wslpath', metavar='COMMA_SEPARATED_LIST', default=True, help="Only try to convert these specific Windows environment variables to WSL paths (default is to try to convert all)") x.add_argument('-W', '--no-wslpath', dest='wslpath', action='store_false', help='Do not try to convert any Windows environment variables containing paths to WSL paths (default is to try to convert all)') g = p.add_argument_group('Output format') x = g.add_mutually_exclusive_group() x.add_argument('-A', '--associative', metavar='ARRAY_NAME', help='Output environment variables in named associative array (Bash extension)') x.add_argument('-b', '--sh', '--bash', dest='format', action='store_const', const='sh', default='sh', help='Output environment variables as POSIX Bourne shell "export" commands (the default)') x.add_argument('-c', '--csh', dest='format', action='store_const', const='csh', help='Output environment variables as C Shell "setenv" commands') x.add_argument('-j', '--json', dest='format', action='store_const', const='json', help='Output environment variables as JSON') p.add_argument('-p', '--prefix', default='WIN_', help='Prefix for variable names in sh/csh output (default %(default)r)') args = p.parse_args() try: winenv = _load_winenv() except Exception as exc: p.error(f'Error loading Windows environment variables: {exc.args}') winenv = _convert_paths(winenv, paths=args.wslpath) if args.associative: print(f'declare -A {args.associative}') for var, val in winenv.items(): print(f'{args.associative}[{shlex.quote(var)}]={shlex.quote(val)}') elif args.format == 'json': json.dump(winenv, sys.stdout) else: kw = 'setenv' if args.format == 'csh' else 'export' for var, val in winenv.items(): if not var.isidentifier(): warn(f'Windows environment variable {var!r} is not a valid POSIX shell identifier, commenting out.') print(("" if var.isidentifier() else "# ") + f'{kw} {args.prefix}{var}={shlex.quote(val)}')