Miscellaneous operating system functions

sage.misc.sage_ostools.have_program(program, path=None)

Return True if a program executable is found in the path given by path.

INPUT:

  • program - a string, the name of the program to check.

  • path - string or None. Paths to search for program, separated by os.pathsep. If None, use the PATH environment variable.

OUTPUT: bool

EXAMPLES:

sage: from sage.misc.sage_ostools import have_program
sage: have_program('ls')
True
sage: have_program('there_is_not_a_program_with_this_name')
False
sage: from sage.env import SAGE_VENV
sage: have_program('sage', os.path.join(SAGE_VENV, 'bin'))
True
sage: have_program('sage', '/there_is_not_a_path_with_this_name')
False
sage: have_program('there_is_not_a_program_with_this_name', os.path.join(SAGE_LOCAL, 'bin'))
False
class sage.misc.sage_ostools.redirection

Bases: object

Context to implement redirection of files, analogous to the >file or 1>&2 syntax in POSIX shells.

Unlike the redirect_stdout and redirect_stderr contexts in the Python 3.4 standard library, this acts on the OS level, not on the Python level. This implies that it only works for true files, not duck-type file objects such as StringIO.

INPUT:

  • source – the file to be redirected

  • dest – where the source file should be redirected to

  • close – (boolean, default: True) whether to close the destination file upon exiting the context. This is only supported if dest is a Python file.

The source and dest arguments can be either Python files or file descriptors.

EXAMPLES:

sage: from sage.misc.sage_ostools import redirection
sage: fn = tmp_filename()
sage: with redirection(sys.stdout, open(fn, 'w')):
....:     print("hello world!")
sage: with open(fn) as f:
....:     _ = sys.stdout.write(f.read())
hello world!

We can do the same using a file descriptor as source:

sage: fd = sys.stdout.fileno()
sage: with redirection(fd, open(fn, 'wb')):
....:     _ = os.write(fd, b"hello world!\n")
sage: with open(fn) as f:
....:     _ = sys.stdout.write(f.read())
hello world!

The converse also works:

sage: with open(fn, 'w') as f:
....:     _ = f.write("This goes to the file\n")
....:     with redirection(f, sys.stdout, close=False):
....:         _ = f.write("This goes to stdout\n")
....:     _ = f.write("This goes to the file again\n")
This goes to stdout
sage: with open(fn) as f:
....:     _ = sys.stdout.write(f.read())
This goes to the file
This goes to the file again

The same redirection instance can be reused multiple times, provided that close=False:

sage: f = open(fn, 'w+')
sage: r = redirection(sys.stdout, f, close=False)
sage: with r:
....:     print("Line 1")
sage: with r:
....:     print("Line 2")
sage: with f:
....:     _ = f.seek(0)
....:     _ = sys.stdout.write(f.read())
Line 1
Line 2

The redirection also works for subprocesses:

sage: import subprocess
sage: with redirection(sys.stdout, open(fn, 'w')):
....:     _ = subprocess.call(["echo", "hello world"])
sage: with open(fn) as f:
....:     _ = sys.stdout.write(f.read())
hello world
dest_fd
dest_file
dup_source_fd
source_fd
source_file
sage.misc.sage_ostools.restore_cwd(chdir=None)

Context manager that restores the original working directory upon exiting.

INPUT:

  • chdir – optionally change directories to the given directory upon entering the context manager

EXAMPLES:

sage: import os
sage: from sage.misc.sage_ostools import restore_cwd
sage: from sage.misc.misc import SAGE_TMP
sage: cwd = os.getcwd()
sage: with restore_cwd(str(SAGE_TMP)):
....:     print(os.getcwd() == os.path.realpath(SAGE_TMP))
True
sage: cwd == os.getcwd()
True