Module sdu.paths
This module contains many useful utilities for dealing with system paths such as:
- A pre and post processing pipeline for system paths
- Ability to add paths to the PATH variable
Functions
preprocess_paths -> list: Preprocesses paths to normalize them as standard unix-style paths
postprocess_paths -> list: Postprocesses existing paths (assuming they've been preprocessed) for use in environment
process_paths -> list: Takes a list or tuple of paths and normalizes and globs them. See notes for details
add_to_path : Takes in a path to a program and adds it to the sytem PATH variable
Notes
Preprocessing steps include
- Converting \ seperators to /
- Converting %USERPROFILE% values on windows to ~
Postprocessing steps include
- expanding wildcards (For directories, file paths are excluded)
- processing correct path seperators
- Regex selection expansion (For directories, file paths are excluded)
Examples
Preprocessing to postprocessing pipeline
# Because of the wildcard and OS results will vary
from sdu.paths import preprocess_paths, postprocess_paths
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\Users\Kieran\Desktop\Development\*', '~\Desktop\Development\Personal\noter', '.']
print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.']
print(postprocess_paths(paths)) # Prints: ['C:\Users\Kieran\Desktop\Development\Canadian Coding\SSB', 'C:\Users\Kieran\Desktop\Development\Canadian Coding', 'C:\Users\Kieran\Desktop\Development\Personal', 'C:\Users\Kieran\Desktop\Development\pystall', 'C:\Users\Kieran\Desktop\Development\python-package-template', 'C:\Users\Kieran\Desktop\Development\Work', 'C:\Users\Kieran\Desktop\Development\Personal\noter', 'C:\Users\Kieran\Desktop\sdu']
Add a folder in the downloads folder called /micro editor/micro-1.4.1
from sdu.paths import add_to_path, process_paths
program_path = f"C:\Users\Kieran\Downloads\micro editor\micro-1.4.1" # Path that contains the executeable
add_to_path(program_path) # Adds the program_path to the path variable
See Also
Glob module information - <https://docs.python.org/3/library/glob.html>
Expand source code
"""This module contains many useful utilities for dealing with system paths such as:
- A pre and post processing pipeline for system paths
- Ability to add paths to the PATH variable
Functions
---------
preprocess_paths -> list:
Preprocesses paths to normalize them as standard unix-style paths
postprocess_paths -> list:
Postprocesses existing paths (assuming they've been preprocessed) for use in environment
process_paths -> list:
Takes a list or tuple of paths and normalizes and globs them. See notes for details
add_to_path :
Takes in a path to a program and adds it to the sytem PATH variable
Notes
-----
### Preprocessing steps include
- Converting \\ seperators to /
- Converting %USERPROFILE% values on windows to ~
### Postprocessing steps include
- expanding wildcards (For directories, file paths are excluded)
- processing correct path seperators
- Regex selection expansion (For directories, file paths are excluded)
Examples
--------
### Preprocessing to postprocessing pipeline
```
# Because of the wildcard and OS results will vary
from sdu.paths import preprocess_paths, postprocess_paths
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.']
print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.']
print(postprocess_paths(paths)) # Prints: ['C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding\\SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal', 'C:\\Users\\Kieran\\Desktop\\Development\\pystall', 'C:\\Users\\Kieran\\Desktop\\Development\\python-package-template', 'C:\\Users\\Kieran\\Desktop\\Development\\Work', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal\\noter', 'C:\\Users\\Kieran\\Desktop\\sdu']
```
### Add a folder in the downloads folder called /micro editor/micro-1.4.1
```
from sdu.paths import add_to_path, process_paths
program_path = f"C:\\Users\\Kieran\\Downloads\\micro editor\\micro-1.4.1" # Path that contains the executeable
add_to_path(program_path) # Adds the program_path to the path variable
```
See Also
--------
Glob module information - https://docs.python.org/3/library/glob.html
"""
# Standard lib dependencies
import re # Used to pattern match with RegEx
import os # Used to validate system paths
import glob # Used to glob (expand) paths
import copy # Used to copy objects safely so no data is lost
import logging # Used to log information when debugging
from typing import Union
def preprocess_paths(paths:Union[list, tuple]) -> list:
"""Preprocesses paths to normalize them as standard unix-style paths
This means:
- Converting \\ seperators to /
- Converting %USERPROFILE% values on windows to ~
Parameters
----------
paths : (list or tuple)
A list or tuple of paths, can be relative or absolute. See Notes for details.
Example
-------
An example of the preprocessing function on a windows machine.
```
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.']
print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.']
```
Notes
-----
- This function does not change '.' paths unless they include a relative path to a separate folder. i.e. a plain '.' is untouched but './folder-name' is converted to an absolute path.
- This function leaves in *'s, and brackets since the postprocessing function globs paths and uses those characters for processing.
- This function will take the HOME(*nix) or USERPROFILE(windows) environment variables and convert them to a ~
Returns
-------
list:
The normalized & preprocessed paths
"""
logging.info(f"Beginning path preprocessing on {paths}")
result = list(copy.deepcopy(paths))
for index, directory in enumerate(result):
directory = directory.strip()
logging.debug(f"Directory: {directory}")
# Convert relative directories to absolute directories
if directory.startswith(".") and (len(directory) > 1):
directory = os.path.abspath(directory)
# Replace HOME values
if not directory.startswith("~"):
if not os.name == "nt": # Not windows
directory = directory.replace(os.getenv('HOME'),"~")
# Replace backslashes (windows) with slashes (*nix)
directory = directory.replace("\\", "/")
# Replace old path with preprocessed form
result[index] = directory
# Remove the %USERPROFILE% from windows paths
regex = r"([A-Z]:/Users/.*)"
matches = re.finditer(regex, "\n".join(result), re.MULTILINE | re.IGNORECASE)
matches = [match.group() for match in matches]
for path in matches:
path_index = result.index(path)
path = path.split("/")[2::] # Remove drive letter and username
path[0] = "~"
result[path_index] = "/".join(path)
logging.debug(f"Result: {result}")
return result
def postprocess_paths(paths:Union[list, tuple], include_files = False, silent = True) -> list:
"""Postprocesses existing paths (assuming they've been preprocessed) for use in environment
This postprocessing means:
- expanding wildcards
- processing correct path seperators
- Regex selection expansion
Parameters
----------
paths : (list or tuple)
A list or tuple of paths, can be relative or absolute. See Notes for details.
include_files : (bool)
Whether to include file results into resulting list
silent : (bool)
Whether to throw an error if one of the paths is invalid
Example
-------
An example of the preprocessing to postprocessing pipeline on a windows machine (because of the wildcard and OS results will vary)
```
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.']
print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.']
print(postprocess_paths(paths)) # Prints: ['C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding\\SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal', 'C:\\Users\\Kieran\\Desktop\\Development\\pystall', 'C:\\Users\\Kieran\\Desktop\\Development\\python-package-template', 'C:\\Users\\Kieran\\Desktop\\Development\\Work', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal\\noter', 'C:\\Users\\Kieran\\Desktop\\sdu']
```
Notes
-----
- In most cases you don't explicitly need to preprocess paths if they are unix paths,
but I would recommend it since the function is designed to work on preprocessed paths.
- Entering in raw windows paths as arguments will likely result in partially, or fully garbled paths.
Although in some cases python will interpret the data properly and work, it is better to always use the preprocessor.
Returns
-------
list:
The list of useable paths (post-normalization & globing)
See Also
--------
Glob module information: https://docs.python.org/3/library/glob.html
"""
logging.info(f"Beginning path postprocessing on {paths}")
result = []
for directory in paths:
directory = directory.strip()
if os.name == "nt":
directory = directory.replace("/", "\\")
if directory.startswith("."):
try:
if directory[1] == "/" or directory[1] == "\\":
directory = f"{os.curdir}{directory[1::]}"
except IndexError:
directory = os.path.abspath(".")
if "~" in directory:
if os.name == "nt":
directory = directory.replace("~",f"{os.getenv('USERPROFILE')}")
else:
directory = directory.replace("~", f"{os.getenv('HOME')}")
if "*" in directory or "[" in directory:
wildcard_paths = glob.glob(directory.strip())
for wildcard_directory in wildcard_paths:
if os.path.isdir(wildcard_directory):
result.append(wildcard_directory)
else: # Does not contain a tilde or glob character
if not silent:
if os.path.isdir(directory):
raise NotADirectoryError(f"Directory was not found on system: {directory}")
if os.path.isdir(directory):
result.append(directory)
logging.debug(f"Result: {result}")
return result
def process_paths(paths:Union[list, tuple]) -> list:
"""Takes a list or tuple of paths and normalizes and globs them. See notes for details
Parameters
----------
paths : (list or tuple)
A list or tuple of paths, can be relative or absolute. See Notes for details.
Example
-------
An example of path processing on a windows machine (because of the wildcard and OS results will vary)
```
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.']
print(process_paths(paths)) # Prints: ['C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding\\SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal', 'C:\\Users\\Kieran\\Desktop\\Development\\pystall', 'C:\\Users\\Kieran\\Desktop\\Development\\python-package-template', 'C:\\Users\\Kieran\\Desktop\\Development\\Work', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal\\noter', 'C:\\Users\\Kieran\\Desktop\\sdu']
```
Notes
-----
Since this function runs the preprocess_paths() & postprocess_paths() functions all implications are carried through to this function including:
- This function does not change '.' paths unless they include a relative path to a separate folder. i.e. a plain '.' is untouched but './folder-name' is converted to an absolute path.
- This function leaves in *'s, and brackets and globs paths using those characters for processing.
- This function will take the HOME(*nix) or USERPROFILE(windows) environment variables and interpret them appropriately per OS.
See Also
--------
Glob module information: https://docs.python.org/3/library/glob.html
"""
if not type(paths) == list and not type(paths) == tuple:
raise ValueError("Paths must be specified as a list or tuple")
result = copy.deepcopy(paths)
result = preprocess_paths(result)
result = postprocess_paths(result)
return result
def add_to_path(program_path:str):
"""Takes in a path to a program and adds it to the sytem PATH variable
Parameters
----------
program_path : str
The path to the installation folder of the application
Notes
-----
* The path must be an absolute path
* The linux version of the command assumes you're using ~/.bashrc
* Because there are so many possible ways this can fail, there are no catches in place
Raises
------
ValueError:
If path provided is not a valid path to a directory
Examples
--------
Add a folder in the downloads folder called /micro editor/micro-1.4.1
```
from sdu.paths import add_to_path, process_paths
program_path = f"C:\\Users\\Kieran\\Downloads\\micro editor\\micro-1.4.1" # Path that contains the executeable
add_to_path(program_path) # Adds the program_path to the path variable
```
"""
program_path = os.path.abspath(program_path)
if not os.path.isdir(program_path):
raise ValueError(f"Path provided is not a valid path: {program_path}")
if os.name == "nt": # Windows systems
import winreg # Allows access to the windows registry
import ctypes # Allows interface with low-level C API's
with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as root: # Get the current user registry
with winreg.OpenKey(root, "Environment", 0, winreg.KEY_ALL_ACCESS) as key: # Go to the environment key
existing_path_value = winreg.EnumValue(key, 3)[1] # Grab the current path value
new_path_value = existing_path_value + program_path + ";" # Takes the current path value and appends the new program path
winreg.SetValueEx(key, "PATH", 0, winreg.REG_EXPAND_SZ, new_path_value) # Updated the path with the updated path
# Tell other processes to update their environment
HWND_BROADCAST = 0xFFFF
WM_SETTINGCHANGE = 0x1A
SMTO_ABORTIFHUNG = 0x0002
result = ctypes.c_long()
SendMessageTimeoutW = ctypes.windll.user32.SendMessageTimeoutW
SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u"Environment", SMTO_ABORTIFHUNG, 5000, ctypes.byref(result),)
else: # If system is *nix
with open(f"{os.getenv('HOME')}/.bashrc", "a") as bash_file: # Open bashrc file
bash_file.write(f'\nexport PATH="{program_path}:$PATH"\n') # Add program path to Path variable
os.system(f". {os.getenv('HOME')}/.bashrc") # Update bash source
print(f"Added {program_path} to path, please restart shell for changes to take effect")
Functions
def add_to_path(program_path: str)
-
Takes in a path to a program and adds it to the sytem PATH variable
Parameters
program_path
:str
- The path to the installation folder of the application
Notes
- The path must be an absolute path
- The linux version of the command assumes you're using ~/.bashrc
- Because there are so many possible ways this can fail, there are no catches in place
Raises
Valueerror
If path provided is not a valid path to a directory
Examples
Add a folder in the downloads folder called /micro editor/micro-1.4.1
from sdu.paths import add_to_path, process_paths program_path = f"C:\Users\Kieran\Downloads\micro editor\micro-1.4.1" # Path that contains the executeable add_to_path(program_path) # Adds the program_path to the path variable
Expand source code
def add_to_path(program_path:str): """Takes in a path to a program and adds it to the sytem PATH variable Parameters ---------- program_path : str The path to the installation folder of the application Notes ----- * The path must be an absolute path * The linux version of the command assumes you're using ~/.bashrc * Because there are so many possible ways this can fail, there are no catches in place Raises ------ ValueError: If path provided is not a valid path to a directory Examples -------- Add a folder in the downloads folder called /micro editor/micro-1.4.1 ``` from sdu.paths import add_to_path, process_paths program_path = f"C:\\Users\\Kieran\\Downloads\\micro editor\\micro-1.4.1" # Path that contains the executeable add_to_path(program_path) # Adds the program_path to the path variable ``` """ program_path = os.path.abspath(program_path) if not os.path.isdir(program_path): raise ValueError(f"Path provided is not a valid path: {program_path}") if os.name == "nt": # Windows systems import winreg # Allows access to the windows registry import ctypes # Allows interface with low-level C API's with winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) as root: # Get the current user registry with winreg.OpenKey(root, "Environment", 0, winreg.KEY_ALL_ACCESS) as key: # Go to the environment key existing_path_value = winreg.EnumValue(key, 3)[1] # Grab the current path value new_path_value = existing_path_value + program_path + ";" # Takes the current path value and appends the new program path winreg.SetValueEx(key, "PATH", 0, winreg.REG_EXPAND_SZ, new_path_value) # Updated the path with the updated path # Tell other processes to update their environment HWND_BROADCAST = 0xFFFF WM_SETTINGCHANGE = 0x1A SMTO_ABORTIFHUNG = 0x0002 result = ctypes.c_long() SendMessageTimeoutW = ctypes.windll.user32.SendMessageTimeoutW SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u"Environment", SMTO_ABORTIFHUNG, 5000, ctypes.byref(result),) else: # If system is *nix with open(f"{os.getenv('HOME')}/.bashrc", "a") as bash_file: # Open bashrc file bash_file.write(f'\nexport PATH="{program_path}:$PATH"\n') # Add program path to Path variable os.system(f". {os.getenv('HOME')}/.bashrc") # Update bash source print(f"Added {program_path} to path, please restart shell for changes to take effect")
def postprocess_paths(paths: Union[list, tuple], include_files=False, silent=True) ‑> list
-
Postprocesses existing paths (assuming they've been preprocessed) for use in environment
This postprocessing means: - expanding wildcards - processing correct path seperators - Regex selection expansion
Parameters
paths
:(list
ortuple)
- A list or tuple of paths, can be relative or absolute. See Notes for details.
include_files
:(bool)
- Whether to include file results into resulting list
silent
:(bool)
- Whether to throw an error if one of the paths is invalid
Example
An example of the preprocessing to postprocessing pipeline on a windows machine (because of the wildcard and OS results will vary)
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\Users\Kieran\Desktop\Development\*', '~\Desktop\Development\Personal\noter', '.'] print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.'] print(postprocess_paths(paths)) # Prints: ['C:\Users\Kieran\Desktop\Development\Canadian Coding\SSB', 'C:\Users\Kieran\Desktop\Development\Canadian Coding', 'C:\Users\Kieran\Desktop\Development\Personal', 'C:\Users\Kieran\Desktop\Development\pystall', 'C:\Users\Kieran\Desktop\Development\python-package-template', 'C:\Users\Kieran\Desktop\Development\Work', 'C:\Users\Kieran\Desktop\Development\Personal\noter', 'C:\Users\Kieran\Desktop\sdu']
Notes
- In most cases you don't explicitly need to preprocess paths if they are unix paths, but I would recommend it since the function is designed to work on preprocessed paths.
- Entering in raw windows paths as arguments will likely result in partially, or fully garbled paths. Although in some cases python will interpret the data properly and work, it is better to always use the preprocessor.
Returns
list:
- The list of useable paths (post-normalization & globing)
See Also
Glob module information: <https://docs.python.org/3/library/glob.html>
Expand source code
def postprocess_paths(paths:Union[list, tuple], include_files = False, silent = True) -> list: """Postprocesses existing paths (assuming they've been preprocessed) for use in environment This postprocessing means: - expanding wildcards - processing correct path seperators - Regex selection expansion Parameters ---------- paths : (list or tuple) A list or tuple of paths, can be relative or absolute. See Notes for details. include_files : (bool) Whether to include file results into resulting list silent : (bool) Whether to throw an error if one of the paths is invalid Example ------- An example of the preprocessing to postprocessing pipeline on a windows machine (because of the wildcard and OS results will vary) ``` paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.'] print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.'] print(postprocess_paths(paths)) # Prints: ['C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding\\SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal', 'C:\\Users\\Kieran\\Desktop\\Development\\pystall', 'C:\\Users\\Kieran\\Desktop\\Development\\python-package-template', 'C:\\Users\\Kieran\\Desktop\\Development\\Work', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal\\noter', 'C:\\Users\\Kieran\\Desktop\\sdu'] ``` Notes ----- - In most cases you don't explicitly need to preprocess paths if they are unix paths, but I would recommend it since the function is designed to work on preprocessed paths. - Entering in raw windows paths as arguments will likely result in partially, or fully garbled paths. Although in some cases python will interpret the data properly and work, it is better to always use the preprocessor. Returns ------- list: The list of useable paths (post-normalization & globing) See Also -------- Glob module information: https://docs.python.org/3/library/glob.html """ logging.info(f"Beginning path postprocessing on {paths}") result = [] for directory in paths: directory = directory.strip() if os.name == "nt": directory = directory.replace("/", "\\") if directory.startswith("."): try: if directory[1] == "/" or directory[1] == "\\": directory = f"{os.curdir}{directory[1::]}" except IndexError: directory = os.path.abspath(".") if "~" in directory: if os.name == "nt": directory = directory.replace("~",f"{os.getenv('USERPROFILE')}") else: directory = directory.replace("~", f"{os.getenv('HOME')}") if "*" in directory or "[" in directory: wildcard_paths = glob.glob(directory.strip()) for wildcard_directory in wildcard_paths: if os.path.isdir(wildcard_directory): result.append(wildcard_directory) else: # Does not contain a tilde or glob character if not silent: if os.path.isdir(directory): raise NotADirectoryError(f"Directory was not found on system: {directory}") if os.path.isdir(directory): result.append(directory) logging.debug(f"Result: {result}") return result
def preprocess_paths(paths: Union[list, tuple]) ‑> list
-
Preprocesses paths to normalize them as standard unix-style paths
This means: - Converting \ seperators to / - Converting %USERPROFILE% values on windows to ~
Parameters
paths
:(list
ortuple)
- A list or tuple of paths, can be relative or absolute. See Notes for details.
Example
An example of the preprocessing function on a windows machine.
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\Users\Kieran\Desktop\Development\*', '~\Desktop\Development\Personal\noter', '.'] print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.']
Notes
- This function does not change '.' paths unless they include a relative path to a separate folder. i.e. a plain '.' is untouched but './folder-name' is converted to an absolute path.
- This function leaves in *'s, and brackets since the postprocessing function globs paths and uses those characters for processing.
- This function will take the HOME(*nix) or USERPROFILE(windows) environment variables and convert them to a ~
Returns
list:
- The normalized & preprocessed paths
Expand source code
def preprocess_paths(paths:Union[list, tuple]) -> list: """Preprocesses paths to normalize them as standard unix-style paths This means: - Converting \\ seperators to / - Converting %USERPROFILE% values on windows to ~ Parameters ---------- paths : (list or tuple) A list or tuple of paths, can be relative or absolute. See Notes for details. Example ------- An example of the preprocessing function on a windows machine. ``` paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.'] print(preprocess_paths(paths)) # Prints: ['~/Desktop/Development/Canadian Coding/SSB', '~/Desktop/Development/*' , '~/Desktop/Development/Personal/noter', '.'] ``` Notes ----- - This function does not change '.' paths unless they include a relative path to a separate folder. i.e. a plain '.' is untouched but './folder-name' is converted to an absolute path. - This function leaves in *'s, and brackets since the postprocessing function globs paths and uses those characters for processing. - This function will take the HOME(*nix) or USERPROFILE(windows) environment variables and convert them to a ~ Returns ------- list: The normalized & preprocessed paths """ logging.info(f"Beginning path preprocessing on {paths}") result = list(copy.deepcopy(paths)) for index, directory in enumerate(result): directory = directory.strip() logging.debug(f"Directory: {directory}") # Convert relative directories to absolute directories if directory.startswith(".") and (len(directory) > 1): directory = os.path.abspath(directory) # Replace HOME values if not directory.startswith("~"): if not os.name == "nt": # Not windows directory = directory.replace(os.getenv('HOME'),"~") # Replace backslashes (windows) with slashes (*nix) directory = directory.replace("\\", "/") # Replace old path with preprocessed form result[index] = directory # Remove the %USERPROFILE% from windows paths regex = r"([A-Z]:/Users/.*)" matches = re.finditer(regex, "\n".join(result), re.MULTILINE | re.IGNORECASE) matches = [match.group() for match in matches] for path in matches: path_index = result.index(path) path = path.split("/")[2::] # Remove drive letter and username path[0] = "~" result[path_index] = "/".join(path) logging.debug(f"Result: {result}") return result
def process_paths(paths: Union[list, tuple]) ‑> list
-
Takes a list or tuple of paths and normalizes and globs them. See notes for details
Parameters
paths
:(list
ortuple)
- A list or tuple of paths, can be relative or absolute. See Notes for details.
Example
An example of path processing on a windows machine (because of the wildcard and OS results will vary)
paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\Users\Kieran\Desktop\Development\*', '~\Desktop\Development\Personal\noter', '.'] print(process_paths(paths)) # Prints: ['C:\Users\Kieran\Desktop\Development\Canadian Coding\SSB', 'C:\Users\Kieran\Desktop\Development\Canadian Coding', 'C:\Users\Kieran\Desktop\Development\Personal', 'C:\Users\Kieran\Desktop\Development\pystall', 'C:\Users\Kieran\Desktop\Development\python-package-template', 'C:\Users\Kieran\Desktop\Development\Work', 'C:\Users\Kieran\Desktop\Development\Personal\noter', 'C:\Users\Kieran\Desktop\sdu']
Notes
Since this function runs the preprocess_paths() & postprocess_paths() functions all implications are carried through to this function including:
- This function does not change '.' paths unless they include a relative path to a separate folder. i.e. a plain '.' is untouched but './folder-name' is converted to an absolute path.
- This function leaves in *'s, and brackets and globs paths using those characters for processing.
- This function will take the HOME(*nix) or USERPROFILE(windows) environment variables and interpret them appropriately per OS.
See Also
Glob module information: <https://docs.python.org/3/library/glob.html>
Expand source code
def process_paths(paths:Union[list, tuple]) -> list: """Takes a list or tuple of paths and normalizes and globs them. See notes for details Parameters ---------- paths : (list or tuple) A list or tuple of paths, can be relative or absolute. See Notes for details. Example ------- An example of path processing on a windows machine (because of the wildcard and OS results will vary) ``` paths = ['~/Desktop/Development/Canadian Coding/SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\*', '~\\Desktop\\Development\\Personal\\noter', '.'] print(process_paths(paths)) # Prints: ['C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding\\SSB', 'C:\\Users\\Kieran\\Desktop\\Development\\Canadian Coding', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal', 'C:\\Users\\Kieran\\Desktop\\Development\\pystall', 'C:\\Users\\Kieran\\Desktop\\Development\\python-package-template', 'C:\\Users\\Kieran\\Desktop\\Development\\Work', 'C:\\Users\\Kieran\\Desktop\\Development\\Personal\\noter', 'C:\\Users\\Kieran\\Desktop\\sdu'] ``` Notes ----- Since this function runs the preprocess_paths() & postprocess_paths() functions all implications are carried through to this function including: - This function does not change '.' paths unless they include a relative path to a separate folder. i.e. a plain '.' is untouched but './folder-name' is converted to an absolute path. - This function leaves in *'s, and brackets and globs paths using those characters for processing. - This function will take the HOME(*nix) or USERPROFILE(windows) environment variables and interpret them appropriately per OS. See Also -------- Glob module information: https://docs.python.org/3/library/glob.html """ if not type(paths) == list and not type(paths) == tuple: raise ValueError("Paths must be specified as a list or tuple") result = copy.deepcopy(paths) result = preprocess_paths(result) result = postprocess_paths(result) return result