Source code for unitils.util

"""Various utility functions for use with command line programs.
"""
import os
import functools
import subprocess

clear = functools.partial(os.system, 'cls' if os.name == 'nt' else 'clear')
clear.__doc__ = """Clear the terminal. uses "cls" on Windows and "clear
on *nix systems."""

[docs]def system_call( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False): """Helper function to shell out commands. This should be platform agnostic. Arguments are the same as to subprocess.Popen. Returns (stdout, stderr, returncode) """ stderr = subprocess.STDOUT pipe = subprocess.Popen( command, stdin=stdin, stdout=stdout, stderr=stderr, shell=shell) stdout, stderr = pipe.communicate() return stdout, stderr, pipe.returncode
import os import sys import struct if sys.platform == 'win32': def get_terminal_size(defaultx=80, defaulty=25): """Return size of current terminal console. This function try to determine actual size of current working console window and return tuple (sizex, sizey) if success, or default size (defaultx, defaulty) otherwise. Dependencies: ctypes should be installed. Author: Alexander Belchenko (e-mail: bialix AT ukr.net) """ try: import ctypes except ImportError: return defaultx, defaulty h = ctypes.windll.kernel32.GetStdHandle(-11) csbi = ctypes.create_string_buffer(22) res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) if res: (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy) = struct.unpack( "hhhhHhhhhhh", csbi.raw) sizex = right - left + 1 sizey = bottom - top + 1 return (sizex, sizey) else: return (defaultx, defaulty) def get_keypress(): """Wait for a keypress and return key pressed. This is the Windows version of this command""" import msvcrt return msvcrt.getch() else: def get_terminal_size(fd=1, defaultx=80, defaulty=25): """Returns height and width of current terminal. First tries to get size via termios.TIOCGWINSZ, then from environment. Defaults to 25 lines x 80 columns if both methods fail. :param fd: file descriptor (default: 1=stdout) :defaultx: The value to return for x if unable to determine (default: 80) :param fd: The value to return for y if unable to determine (default: 80) """ try: import fcntl, termios, struct hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) wh = (hw[1], hw[0]) except: try: wh = (os.environ['COLUMNS'], os.environ['LINES']) except: wh = (80, 25) return wh def get_keypress(): """Wait for a keypress and return key pressed. This is the *nix version of this command""" import termios, fcntl, sys, os fd = sys.stdin.fileno() oldterm = termios.tcgetattr(fd) newattr = termios.tcgetattr(fd) newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO termios.tcsetattr(fd, termios.TCSANOW, newattr) oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) try: while 1: try: c = sys.stdin.read(1) break except IOError: pass finally: termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm) fcntl.fcntl(fd, fcntl.F_SETFL, oldflags) return c def page(text): """Page through text on a terminal. Similar to more. :param text: The text to page through :type text: str :returns: None """ if not sys.stdout.isatty(): sys.stdout.write(text) sys.stdout.flush() return height = get_terminal_size()[1] current_line = 0 for line in text.splitlines(): if current_line >= height - 2: sys.stdout.write(" \r{}".format(line)) sys.stdout.flush() sys.stdout.write("\n--more--\r") sys.stdout.flush() key = get_keypress() if key == " ": sys.stdout.write(" \r") sys.stdout.flush() current_line = 0 elif key == "q": sys.stdout.write(" ") sys.stdout.flush() break elif key == '\x03': sys.stdout.write(" \r") sys.stdout.flush() break else: print(line) current_line += 1