Skip to content

Instantly share code, notes, and snippets.

@blaylockbk
Last active July 10, 2021 16:47
Show Gist options
  • Save blaylockbk/d19ec2e61438c251d22c8ebd5d4becb9 to your computer and use it in GitHub Desktop.
Save blaylockbk/d19ec2e61438c251d22c8ebd5d4becb9 to your computer and use it in GitHub Desktop.
replace environment variables in Path object
import os
from pathlib import Path
import warnings
# Create a new method for Path objects called `expand`, which fully
# expands the Path object with the given environment variables.
def _expand(self, *, strict=True):
"""
Fully expand and resolve the Path with the given environment variables.
Parameters
----------
strict : bool
If True, must use the operating system syntax to find environment variables.
- On Linux/Mac, environment variables look like ``${NAME}`` or ``$NAME``
- On Windows, environment variables look like ``%NAME%``
If False, just look for the path part in the os.environ dict
(i.e., HOME without symbols)
"""
full_path = Path()
for i in self.parts:
if not strict:
if i in os.environ:
i = os.getenv(i)
if i.startswith('$') or i.startswith('%'):
# This might be an environment variable
envar = i
for ch in '${}%':
if ch in envar:
envar = envar.replace(ch,"")
if envar not in os.environ:
warnings.warn(f'🦨 Sorry, [{i}] is not an environment variable.')
else:
i = os.getenv(envar)
# Note: When you append to a path with a root, that path overwrites
# the old path.
# Example: Path('this/dir/') / Path('/p/home/') ==> Path(/p/home/)
# and not Path(this/dir//p/home/)
full_path = full_path / i
# Resolve path for `~`, `~blaylock`, `..`, `//`, and `.`
full_path = full_path.expanduser().resolve()
return full_path
# Add the method to the Path class
Path.expand = _expand
# Test the new method
Path('~/').expand()
# > Path('/home/blaylock')
Path('$HOME/software').expand()
# > Path('/home/blaylock/software')
Path('HOME').expand()
# > NOT WHAT YOU MIGHT EXPECT >> Path('/home/blaylock/HOME')
Path('HOME').expand(strict=False)
# > Path('/home/blaylock')
@blaylockbk
Copy link
Author

blaylockbk commented Jul 10, 2021

Actually, that method can more simply be done like this

from pathlib import Path
import os

def _expand(self):
    """
    Fully expand and resolve the Path with the given environment variables.
    """
    return Path(os.path.expandvars(self)).expanduser().resolve()

Path.expand = _expand

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment