Miscellaneous operating system functions#

sage.misc.sage_ostools.have_program(program, path=None)[source]#

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
>>> from sage.all import *
>>> from sage.misc.sage_ostools import have_program
>>> have_program('ls')
True
>>> have_program('there_is_not_a_program_with_this_name')
False
>>> have_program('sh', '/bin')
True
>>> have_program('sage', '/there_is_not_a_path_with_this_name')
False
>>> have_program('there_is_not_a_program_with_this_name', "/bin")
False
class sage.misc.sage_ostools.redirection[source]#

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()
>>> from sage.all import *
>>> from sage.misc.sage_ostools import redirection
>>> 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!
>>> from sage.all import *
>>> with redirection(sys.stdout, open(fn, 'w')):
...     print("hello world!")
>>> 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!
>>> from sage.all import *
>>> fd = sys.stdout.fileno()
>>> with redirection(fd, open(fn, 'wb')):
...     _ = os.write(fd, b"hello world!\n")
>>> 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
>>> from sage.all import *
>>> 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
>>> 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
>>> from sage.all import *
>>> f = open(fn, 'w+')
>>> r = redirection(sys.stdout, f, close=False)
>>> with r:
...     print("Line 1")
>>> with r:
...     print("Line 2")
>>> with f:
...     _ = f.seek(Integer(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
>>> from sage.all import *
>>> import subprocess
>>> with redirection(sys.stdout, open(fn, 'w')):
...     _ = subprocess.call(["echo", "hello world"])
>>> with open(fn) as f:
...     _ = sys.stdout.write(f.read())
hello world
dest_fd[source]#
dest_file[source]#
dup_source_fd[source]#
source_fd[source]#
source_file[source]#
sage.misc.sage_ostools.restore_cwd(chdir=None)[source]#

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
>>> from sage.all import *
>>> from sage.misc.sage_ostools import restore_cwd
>>> import tempfile
>>> orig_cwd = os.getcwd()
>>> with tempfile.TemporaryDirectory() as d:
...     with restore_cwd(d):
...         print(os.getcwd() == orig_cwd)
False
>>> os.getcwd() == orig_cwd
True