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: have_program('sh', '/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', "/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: from sage.misc.sage_ostools import restore_cwd
sage: import tempfile
sage: orig_cwd = os.getcwd()
sage: with tempfile.TemporaryDirectory() as d:
....:     with restore_cwd(d):
....:         print(os.getcwd() == orig_cwd)
False
sage: os.getcwd() == orig_cwd
True