shellutils: System calls with STDOUT capture, SFTP, and more

This module mainly provides two types of tools:

  • convenience functions that wrap subprocess.Popen that simplify common use cases and

  • classes like Shell and SSH that create persistent processes, usually logged into a remote host.

The convenience functions include

Essentially each of these functions create an instance of subprocess.Popen and then call subprocess.Popen.communicate(). They are all calls to _call() but with different defaults and outputs for each case. The o stands for “output,” as in STDOUT will be captured. The e is for “error,” referring to STDERR capture, and q is for “quiet,” meaning that by default both STDOUT and STDERR will be suppressed.

Finally, check_o() is very similar to subprocess.check_output(); it will capture STDOUT by default, but it will also raise an exception if tne command’s return code is nonzero. All of these functions can also be used to execute a command on a remote host using the host keyword argument.

The second category is collection of persistent-process classes:

The first works by logging into a remote host and creating a process so that you can run a sequence of commands there. It starts with a

ssh -q {host} {shell}

command, for example

ssh -q pfe bash

It then sets STDIN, STDOUT, and STDERR of this process to be non-blocking so that you can run multiple commands and query STDOUT and the others more than one time.

The second class, Shell, works in a similar way but on the local host. It can be convenient because a Shell instance has its own current working directory. It also enables writing code for which remote hosts and local hosts can share the vast majority of their code.

SFTP is a similar class that starts an SFTP session to a remote host and behaves much like the system sftp itself. However, users will generally prefer the fourth class to using this one directly.

The SSHPortal is simply a combination of SSH and SFTP. More specifically, it’s a new class that have an instance of both SSH and SFTP as attributes. Although this requires two logins, it is usually preferable because it allows the SSH instance to do detailed checks and can create folders with complex file permissions, while the SFTP is used for the actual transfer of data.

You can instantiate any of these classes (except Shell, which usually takes no arguments) by just giving it the name of the remote host as a single positional parameter.

proc = SSH("pfe")

These classes provide several common functions, such as SSH.listdir(), SSH.chdir(), SFTP.cd_local(), and SSHPortal.get() and SSHPortal.put(). But they (except for SFTP) also have generic run() commands that allow for running arbitrary code by writing the command to STDIN.

class lfc._vendor.gitutils._vendor.shellutils.SFTP(host: str, **kw)

Interface to an SFTP process

Call:
>>> sftp = SFTP(host, **kw)
Inputs:
host: str

Name of remote host to log into

encoding: {"utf-8"} | str

Text encoding choice

Outputs:
sftp: SFTP

SFTP file transfer instance

Attributes:
cd_local(path: str)

Change working directory on local side

Call:
>>> sftp.cd_local(path)
Inputs:
sftp: SFTP

SFTP file transfer instance

path: str

Folder (absolute or relative) to change to

cd_remote(path: str)

Change working directory on remote side

Call:
>>> sftp.cd_remote(path)
Inputs:
sftp: SFTP

SFTP file transfer instance

path: str

Folder (absolute or relative) to change to

encoding

str – Text encoding for this instance

get(fremote: str, flocal=None)

Transfer a file from remote host to local

Call:
>>> sftp.get(fremote, flocal=None)
Inputs:
sftp: SFTP

SFTP file transfer instance

fremote: str

Name of file on remote host

flocal: {None} | str

Name of destination file on local host, default is os.path.basename(fremote)

getcwd_local() str

Get current working directory for local side

Call:
>>> cwd = sftp.getcwd_local()
Inputs:
sftp: SFTP

SFTP file transfer instance

Outputs:
cwd: str

Absolute path to current working directory

getcwd_remote() str

Get current working directory for remote side

Call:
>>> cwd = sftp.getcwd_remote()
Inputs:
sftp: SFTP

SFTP file transfer instance

Outputs:
cwd: str

Absolute path to current working directory

host

str – Name of remote host for this instance

log

list[str] – Log messages

proc

subprocess.Popen – Subprocess used to interface sftp executable

put(flocal: str, fremote=None)

Transfer a file from local host to remote

Call:
>>> sftp.put(flocal, fremote=None)
Inputs:
sftp: SFTP

SFTP file transfer instance

flocal: str

Name of file on local host

fremote: {None} | str

Name of destination file on remote host, default is os.path.basename(flocal)

wait()

Wait for any current commands to exit

Call:
>>> sftp.wait()
Inputs:
sftp: SFTP

SFTP file transfer instance

wait_stdout()

Read current STDOUT, or wait until some appears

Call:
>>> txt = sftp.wait_stdout()
Inputs:
sftp: SFTP

SFTP file transfer instance

Outputs:
txt: str | None

Text read from STDOUT, if any

class lfc._vendor.gitutils._vendor.shellutils.SSH(host=None, **kw)

Class for persistent SSH subprocess

This class opens subprocess.Popen instance that logs into a remote host of your choosing and then waits for you to issue commands. It can also collect and return STDOUT and STDERR.

Call:
>>> ssh = SSH(host, **kw)
Inputs:
host: None | str

Name of server to login to using SSH (use local if None)

executable: {"bash"} | str

Executable to use on the remote host

encoding: {"utf-8"} | str

Encoding for STDOUT, etc. bytes

Outputs:
ssh: SSH

Persistent SSH subprocess

Attributes:
assert_isdir(fdir: str)

Assert that a folder exists on remote host

Call:
>>> ssh.assert_isdir(fdir)
Inputs:
ssh: SSH

Persistent SSH subprocess

fdir: str

Name of prospective folder to test

Raises:

ShellutilsFileNotFoundError if fdir is not a dir

Versions:
  • 2022-12-19 @ddalle: v1.0

assert_isfile(fname: str)

Assert that a file exists on remote host

Call:
>>> ssh.assert_isfile(fdir)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of prospective file to test

Raises:

ShellutilsFileNotFoundError if fname is not file

Versions:
  • 2022-12-19 @ddalle: v1.0

call(cmdstr: str)

Run a command and collect return code

Call:
>>> ierr = ssh.call(cmd_str)
Inputs:
ssh: SSH

Persistent SSH subprocess

cmdstr: str

Command to run on remote host

Outputs:
ierr: int

Return code

Versions:
  • 2022-12-19 @ddalle: v1.0

chdir(wd: str)

Change the current working directory on the remote host

Call:
>>> ssh.chdir(wd)
Inputs:
ssh: SSH

Persistent SSH subprocess

Versions:
  • 2022-12-19 @ddalle: v1.0

communicate(cmd_str: str)

Run a command and collect return code, STDOUT, and STDERR

Call:
>>> ierr, stdout, stderr = ssh.communicate(cmd_str)
Inputs:
ssh: SSH

Persistent SSH subprocess

cmd_str: str

Command to run on remote host

Outputs:
ierr: int

Return code

stdout: None | str

STDOUT from command, if any

stderr: None | str

STDERR from command, if any

Versions:
  • 2022-12-19 @ddalle: v1.0

echo(msg: str)

Echo text to STDOUT on remote host

Call:
>>> ssh.echo(msg)
Inputs:
ssh: SSH

Persistent SSH subprocess

msg: str

Text to echo

Versions:
  • 2022-12-19 @ddalle: v1.0

encoding

str – Encoding for this method

executable

str – Executable for remote process

getcwd() str

Get current working directory

Call:
>>> cwd = ssh.getcwd()
Inputs:
ssh: SSH

Persistent SSH subprocess

Outputs:
cwd: str

Working directory on remote host

Versions:
  • 2022-12-19 @ddalle: v1.0

getmtime(fname: str) int

Get modification time of remote file

Call:
>>> mtime = ssh.getmtime(fname)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of file on remote host

Outputs:
fsize: int

Size of file in bytes

Versions:
  • 2024-04-23 @ddalle: v1.0

getsize(fname: str) int

Get size of remote file

Call:
>>> fsize = ssh.getsize(fname)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of file on remote host

Outputs:
fsize: int

Size of file in bytes

Versions:
  • 2022-12-19 @ddalle: v1.0

host

str | None – Name of remote host for this process; if None then local process

isdir(fdir: str) bool

Test if remote folder fdir exists

Call:
>>> q = ssh.isdir(fdir)
Inputs:
ssh: SSH

Persistent SSH subprocess

fdir: str

Name of prospective folder to test

Outputs:
q: True | False

Whether or not fdir is a folder on remote host

Versions:
  • 2022-12-19 @ddalle: v1.0

isfile(fname: str) bool

Test if remote file fname exists and is a file

Call:
>>> q = ssh.isfile(fname)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of prospective folder to test

Outputs:
q: True | False

Whether or not fname is a file on remote host

Versions:
  • 2022-12-19 @ddalle: v1.0

listdir(fdir='.') list

List contents of a folder

Call:
>>> fnames = ssh.listdir(fdir=".")
Inputs:
ssh: SSH

Persistent SSH subprocess

fdir: {"."} | str

Name of prospective folder to test

Outputs:
fnames: list[str]

List of files, folders, and links in fdir

Versions:
  • 2022-12-19 @ddalle: v1.0

log

list[str] – Log messages

mkdir(fdir: str)

Create new folder

Call:
>>> ssh.mkdir(fdir)
Inputs:
ssh: SSH

Persistent SSH subprocess

fdir: {"."} | str

Name of prospective folder to test

Versions:
  • 2022-12-19 @ddalle: v1.0

newfile(fname: str)

Create an empty file w/ correct ACLs based on parent folder

The purpose of this command is to create an empty file with the correct name but obeying the default ACLs of the parent folder. SFTP does not upload files with the correct access control lists, so this file creates a new file using touch. When the empty file already exists, SFTP does not change the ACLs, so the result is a file with the expected permissions. If the file already exists, this function deletes it.

Call:
>>> ssh.newfile(fname)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of prospective folder to test

Versions:
  • 2022-12-19 @ddalle: v1.0

proc

subprocess.Popen – Subprocess interface for ssh for this instance

read_stdout()

Read remote process’s current STDOUT buffer

Call:
>>> stdout = ssh.read_stdout()
Inputs:
ssh: SSH

Persistent SSH subprocess

Outputs:
stdout: None | str

STDOUT buffer, if any

Versions:
  • 2022-12-19 @ddalle: v1.0

  • 2023-08-11 @ddalle: v2.0; os.read() to support Windows

remove(fname: str)

Remove a file or link

Call:
>>> ssh.remove(fname)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of prospective folder to test

Versions:
  • 2022-12-19 @ddalle: v1.0

touch(fname: str)

Create empty file or update modification time

Call:
>>> ssh.touch(fname)
Inputs:
ssh: SSH

Persistent SSH subprocess

fname: str

Name of prospective folder to test

Versions:
  • 2022-12-19 @ddalle: v1.0

wait(timeout=None, dt=0.02)

Wait for any running commands to terminate

The method for this is to echo a random string and wait for it to show up in STDOUT. The random string is then removed from the STDOUT buffer so that other methods can access the intended STDOUT text.

Call:
>>> ierr = ssh.wait()
Inputs:
ssh: SSH

Persistent SSH subprocess

timeout: {None} | float | int

Maximum seconds to wait, unlimited if None

dt: {0.02} | float

Seconds to wait between polls

Outputs:
ierr: 0 | 1 | 2

Status indicator:

  • 0: success

  • 1: wait() call timed out

  • 2: keyboard interrupt

Versions:
  • 2022-12-19 @ddalle: v1.0

wait_stdout(timeout=None, dt=0.02)

Capture STDOUT, but wait for any running process to finish

Call:
>>> stdout = ssh.wait_stdout(timeout=None, dt=0.02)
Inputs:
ssh: SSH

Persistent SSH subprocess

timeout: {None} | float | int

Maximum seconds to wait, unlimited if None

dt: {0.02} | float

Seconds to wait between polls

Outputs:
stdout: str

STDOUT but waiting until it’s nonempty

Versions:
  • 2022-12-19 @ddalle: v1.0

class lfc._vendor.gitutils._vendor.shellutils.SSHBase

Base class for both SSH and SFTP

This class does not have an __init__() method

close()

Close SSH process

Call:
>>> ssh.close()
Inputs:
ssh: SSH

Persistent SSH subprocess

Versions:
  • 2022-12-19 @ddalle: v1.0

read_stderr()

Read remote process’s current STDERR buffer

Call:
>>> stderr = ssh.read_stderr()
Inputs:
ssh: SSHBase

Persistent SSH subprocess

Outputs:
stderr: None | str

STDERR buffer, if any

Versions:
  • 2022-12-19 @ddalle: v1.0

  • 2023-08-11 @ddalle: v2.0; os.read() to support Windows

read_stdout()

Read remote process’s current STDOUT buffer

Call:
>>> stdout = ssh.read_stdout()
Inputs:
ssh: SSHBase

Persistent SSH subprocess

Outputs:
stderr: None | str

STDERR buffer, if any

Versions:
  • 2022-12-19 @ddalle: v1.0

  • 2023-08-11 @ddalle: v2.0; os.read() to support Windows

run(cmdstr: str)

Run a command on remote host

The command does not need to end with a newline (\\n).

Call:
>>> ssh.run(cmdstr)
Inputs:
ssh: SSHBase

Persistent SSH subprocess

cmdstr: str

Command to run

Versions:
  • 2022-12-19 @ddalle: v1.0

class lfc._vendor.gitutils._vendor.shellutils.SSHPortal(host: str, cwd=None, encoding='utf-8')

Combined SSH and SFTP interface

This class works by logging into a remote host twice, once for a shell (SSH) and another for SFTP.

Call:
>>> portal = SSHPortal(host, cwd=None, encoding="utf-8")
Inputs:
host: str

Name of remote host to log into

cwd: {None} | str

Optional initial absolute path of shell on host

encoding: {"utf-8"} | str

Text encoding choice

Outputs:
portal: SSHPortal

Combined SSH and SFTP interface

Attributes:
abspath_local(fname: str) str

Return absolute path to local file/folder

Call:
>>> fabs = portal.abspath_local(fname)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fname: str

Local path to file/folder

Outputs:
fabs: str

Local absolute path to fname

assert_isfile_local(fname: str)

Assert that a file exists locally

Call:
>>> portal.assert_isfile_local(fname)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fname: str

Path to local file

Raises:

ShellutilsFileNotFoundError if fname does not exist relative to portal.cwd

chdir_local(fdir: str)

Change the local working directory

Call:
>>> portal.chdir_remote(fdir)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fdir: str

Name of remote path, relative or absolute

Versions:
  • 2022-12-19 @ddalle: v1.0

  • 2023-08-12 @ddalle: v1.1; one less line for testing

chdir_remote(fdir: str)

Change the remote working directory

Call:
>>> portal.chdir_remote(fdir)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fdir: str

Name of remote path, relative or absolute

Versions:
  • 2022-12-19 @ddalle: v1.0

close()

Close both SSH and SFTP shells, waiting for running commands

Call:
>>> portal.close()
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

Versions:
  • 2022-12-19 @ddalle: v1.0

cwd

str – Initial local working directory

get(fremote: str, flocal=None, wait=True, **kw)

Transfer a file from remote to local host

Call:
>>> portal.get(fremote, flocal=None, wait=True, **kw)
Inputs:
portal: SSHPortal

Combined SSH and SFTP interface

fremote: str

Name of remote file to send

flocal: {None} | str

Name of destination file on local host; if None, then os.path.basename(fremote)

wait: {True} | False

Option to block (wait) until transfer completes

progress: {wait} | True | False

Option to display transfer progress percentage

fprog: {None} | str

File name to show during transfer; default is fremote truncated to fit in current terminal width

getsize_local(fname: str) int

Get size of local file

Call:
>>> st_size = portal.getsize_local(fname)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fname: str

Name of local file

Outputs:
st_size: int

Size of file in bytes

getsize_remote(fname: str) int

Get size of remote file

Call:
>>> st_size = portal.getsize_local(fname)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fname: str

Name of remote file

Outputs:
st_size: int

Size of file in bytes

isfile_local(fname: str) bool

Check if local file exists

Call:
>>> is_file = portal.isfile_local(fname)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fname: str

Name of local file

Outputs:
is_file: True | False

Whether fname exists

put(flocal: str, fremote=None, wait=True, **kw)

Transfer a file from local to remote host

Call:
>>> portal.put(flocal, fremote=None, wait=True, **kw)
Inputs:
portal: SSHPortal

Combined SSH and SFTP interface

flocal: str

Name of local file to send

fremote: {None} | str

Name of destination file on remote host; if None, then os.path.basename(flocal)

wait: {True} | False

Option to block (wait) until transfer completes

progress: {wait} | True | False

Option to display transfer progress percentage

fprog: {None} | str

File name to show during transfer; default is flocal truncated to fit in current terminal width

remove_local(fname: str)

Delete a local file, if it exists

Call:
>>> portal.remove_local(fname)
Inputs:
portal: SSHPortal

Combined remote shell and file transfer portal

fname: str

Name of local file

sftp

SFTP – File transfer interface for this instance

ssh

SSH – Remote shell interface for this instance

class lfc._vendor.gitutils._vendor.shellutils.Shell(**kw)

Class for persistent local subprocess

This class opens subprocess.Popen instance that starts a shell process (usually BASH) on your local host and then waits for you to issue commands. It can also collect and return STDOUT and STDERR.

Call:
>>> shell = Shell(**kw)
Inputs:
host: str

Name of server to login to using SSH

executable: {"bash"} | str

Executable to use on the remote host

encoding: {"utf-8"} | str

Encoding for STDOUT, etc. bytes

Outputs:
shell: Shell

Persistent local subprocess

Attributes:
encoding

str – Encoding for this method

executable

str – Executable for remote process

host

str | None – Name of remote host for this process; if None then local process

log

list[str] – Log messages

proc

subprocess.Popen – Subprocess interface for ssh for this instance

exception lfc._vendor.gitutils._vendor.shellutils.ShellutilsError
exception lfc._vendor.gitutils._vendor.shellutils.ShellutilsFileExistsError

Error class for already existing file

exception lfc._vendor.gitutils._vendor.shellutils.ShellutilsFileNotFoundError

Error class for file/folder not found

exception lfc._vendor.gitutils._vendor.shellutils.ShellutilsFilenameError

Error class for invalid file names

exception lfc._vendor.gitutils._vendor.shellutils.ShellutilsIsADirectoryError

Error class for attempting to access folder as if a file

lfc._vendor.gitutils._vendor.shellutils._call(cmd, **kw)

Generic system interface

This command can either capture STDOUT [and/or STDERR], print it to the terminal, or pipe it to a file. It more or less encapsulates the capabilities of

  • subprocess.call() and

  • subprocess.check_output()

although it works by using subprocess.Popen directly.

Call:
>>> out, err, ierr = _call(cmd, **kw)
Inputs:
cmd: list[str]

System command to run, broken into parts as for subprocess.call()

stdout: {None} | PIPE | file

Destination for standard output

stderr: {None} | PIPE | file

Destination for standard error messages

encoding: {"utf-8"} | str

Name of encoding to use for converting strings to bytes

host: {None} | str

Name of remote host (if not None) on which to run

cwd: {None} | str

Folder in which to run command

executable: {"sh"} | str

Name of shell to use if on remote host

Outputs:
out: None | str

Captured STDOUT if stdout is subprocess.PIPE

err: None | str

Captured STDERR if stdout is subprocess.PIPE

ierr: int

Return code from executing command

Versions:
  • 2020-12-24 @ddalle: v1.0

  • 2021-01-27 @ddalle: v1.1; fix default cwd w/ host

lfc._vendor.gitutils._vendor.shellutils.call(cmd, **kw)

Run a system command and ignore STDOUT and STDERR

Setting stdout and/or stderr to PIPE will suppress them. Setting them to None (the default) will cause them to display normally and not be captured.

Call:
>>> ierr = call(cmd, **kw)
Inputs:
cmd: list[str]

System command to run, broken into parts as for subprocess.call()

stdout: {None} | PIPE | file

Destination for standard output

stderr: {None} | PIPE | file

Destination for standard error messages

encoding: {"utf-8"} | str

Name of encoding to use for converting strings to bytes

host: {None} | str

Name of remote host (if not None) on which to run

cwd: {os.getcwd()} | str

Folder in which to run command

executable: {"sh"} | str

Name of shell to use if on remote host

Outputs:
ierr: int

Return code from executing command

Versions:
  • 2020-12-24 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.call_o(cmd, **kw)

Run a system command and capture STDOUT

Call:
>>> out, err, ierr = call_o(cmd, **kw)
Inputs:
cmd: list[str]

System command to run, broken into parts as for subprocess.call()

stdout: None | {PIPE} | file

Destination for standard output

stderr: {None} | PIPE | file

Destination for standard error messages

encoding: {"utf-8"} | str

Name of encoding to use for converting strings to bytes

host: {None} | str

Name of remote host (if not None) on which to run

cwd: {os.getcwd()} | str

Folder in which to run command

executable: {"sh"} | str

Name of shell to use if on remote host

Outputs:
out: str

Captured STDOUT decoded as a str

err: None | str

Captured STDERR if stdout is subprocess.PIPE

ierr: int

Return code from executing command

Versions:
  • 2020-12-24 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.call_oe(cmd, **kw)

Run a system command and capture STDOUT

Call:
>>> out, err, ierr = call_oe(cmd, **kw)
Inputs:
cmd: list[str]

System command to run, broken into parts as for subprocess.call()

stdout: None | {PIPE} | file

Destination for standard output

stderr: None | {PIPE} | file

Destination for standard error messages

encoding: {"utf-8"} | str

Name of encoding to use for converting strings to bytes

host: {None} | str

Name of remote host (if not None) on which to run

cwd: {os.getcwd()} | str

Folder in which to run command

executable: {"sh"} | str

Name of shell to use if on remote host

Outputs:
out: str

Captured STDOUT decoded as a str

err: None | str

Captured STDERR if stdout is subprocess.PIPE

ierr: int

Return code from executing command

Versions:
  • 2021-07-19 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.call_q(cmd, **kw)

Run a system command, suppressing STDOUT and STDERR

Call:
>>> ierr = call_q(cmd, **kw)
Inputs:
cmd: list[str]

System command to run, broken into parts as for subprocess.call()

stdout: None | {PIPE} | file

Destination for standard output

stderr: None | {PIPE} | file

Destination for standard error messages

encoding: {"utf-8"} | str

Name of encoding to use for converting strings to bytes

host: {None} | str

Name of remote host (if not None) on which to run

cwd: {os.getcwd()} | str

Folder in which to run command

executable: {"sh"} | str

Name of shell to use if on remote host

Outputs:
ierr: int

Return code from executing command

Versions:
  • 2020-12-24 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.check_o(cmd, **kw)

Run a system command and capture STDOUT

Call:
>>> out, err = check_o(cmd, **kw)
Inputs:
cmd: list[str]

System command to run, broken into parts as for subprocess.call()

stdout: None | {PIPE} | file

Destination for standard output

stderr: {None} | PIPE | file

Destination for standard error messages

encoding: {"utf-8"} | str

Name of encoding to use for converting strings to bytes

host: {None} | str

Name of remote host (if not None) on which to run

cwd: {os.getcwd()} | str

Folder in which to run command

executable: {"sh"} | str

Name of shell to use if on remote host

Outputs:
out: str

Captured STDOUT decoded as a str

err: None | str

Captured STDERR if stdout is subprocess.PIPE

Versions:
  • 2020-12-24 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.identify_host(where=None)

Identify possible remote host/local path breakdown

Call:
>>> host, path = identify_host(where)
Inputs:
where: {None} | str

Local path like "/home/user" or remote path like "pfe://home"

Outputs:
host: None | str

Remote host nae preceding : if any

path: str

Path on host; matches where if no host

Versions:
  • 2022-03-06 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.validate_absfilename(fname: str, sep='/')

Check if a file name is valid, allowing for folder names

This version only disallows punctuation characters that cause problems on at least one common file system. Single quotes and foreign language characters are allowed.

It also restricts the file name length to 255 characters, even though this is not strictly speaking a hard limit on Windows systems.

Call:
>>> validate_absfilename(fname, sep='/')
Inputs:
fname: str

Name of file

sep: {'/'} | "\"

Path separator

Versions:
  • 2022-12-19 @ddalle: v1.0

  • 2023-10-25 @ddalle: v1.1; add sep

lfc._vendor.gitutils._vendor.shellutils.validate_dirname(fdir: str, sep='/')

Check if a folder name is valid

This version only disallows punctuation characters that cause problems on at least one common file system. Single quotes and foreign language characters are allowed.

It also restricts the file name length to 255 characters, even though this is not strictly speaking a hard limit on Windows systems.

Call:
>>> validate_dirname(fdir, sep='/')
Inputs:
fdir: str

Name of file

Versions:
  • 2022-12-19 @ddalle: v1.0

  • 2023-10-25 @ddalle: v1.1; add sep

lfc._vendor.gitutils._vendor.shellutils.validate_filename(fname: str)

Check if a file name is valid

This version only disallows punctuation characters that cause problems on at least one common file system. Single quotes and foreign language characters are allowed.

It also restricts the file name length to 255 characters, even though this is not strictly speaking a hard limit on Windows systems.

Call:
>>> validate_filename(fname)
Inputs:
fname: str

Name of file

Versions:
  • 2022-12-19 @ddalle: v1.0

lfc._vendor.gitutils._vendor.shellutils.validate_globname(pattern: str)

Check if a glob pattern is valid

This version only disallows punctuation characters that cause problems on at least one common file system. Single quotes and foreign language characters are allowed.

It also restricts the file name length to 255 characters, even though this is not strictly speaking a hard limit on Windows systems.

Call:
>>> validate_globname(pattern)
Inputs:
fname: str

Name of file

Versions:
  • 2022-12-19 @ddalle: v1.0