More OS support for dynamic environment column width

This commit is contained in:
Casper da Costa-Luis 2015-10-27 16:09:24 +00:00 committed by Casper da Costa-Luis
parent 1392025c49
commit 7be2fdcf92
2 changed files with 78 additions and 9 deletions

View File

@ -11,7 +11,7 @@ Usage:
# a result precise floating numbers (instead of truncated int)
from __future__ import division, absolute_import
# import compatibility functions and utilities
from ._utils import _supports_unicode, _environ_cols, _range, _unich
from ._utils import _supports_unicode, _environ_cols_wrapper, _range, _unich
import sys
from time import time
@ -263,7 +263,11 @@ class tqdm(object):
if ((ncols is None) and (file in (sys.stderr, sys.stdout))) or \
dynamic_ncols:
ncols = _environ_cols(file)
if dynamic_ncols:
dynamic_ncols = _environ_cols_wrapper()
ncols = dynamic_ncols(file)
else:
ncols = _environ_cols_wrapper()(file)
if miniters is None:
miniters = 0
@ -359,8 +363,9 @@ class tqdm(object):
# Initialize the screen printer
self.sp = StatusPrinter(self.file)
if not disable:
self.sp(format_meter(
0, total, 0, ncols, self.desc, ascii, unit, unit_scale))
self.sp(format_meter(0, total, 0,
(dynamic_ncols(file) if dynamic_ncols else ncols),
self.desc, ascii, unit, unit_scale))
# Init the time/iterations counters
self.start_t = self.last_print_t = time()
@ -474,7 +479,7 @@ class tqdm(object):
else:
sp(format_meter(
n, self.total, elapsed,
(_environ_cols(self.file) if dynamic_ncols
(dynamic_ncols(self.file) if dynamic_ncols
else ncols),
self.desc, ascii, unit, unit_scale))
@ -584,7 +589,7 @@ class tqdm(object):
else:
self.sp(format_meter(
self.n, self.total, elapsed,
(_environ_cols(self.file) if self.dynamic_ncols
(self.dynamic_ncols(self.file) if self.dynamic_ncols
else self.ncols),
self.desc, self.ascii, self.unit, self.unit_scale))
@ -621,7 +626,7 @@ class tqdm(object):
cur_t = time()
self.sp(format_meter(
self.n, self.total, cur_t-self.start_t,
(_environ_cols(self.file) if self.dynamic_ncols
(self.dynamic_ncols(self.file) if self.dynamic_ncols
else self.ncols),
self.desc, self.ascii, self.unit, self.unit_scale))
self.file.write('\n')

View File

@ -20,7 +20,71 @@ def _supports_unicode(file):
return _is_utf(file.encoding)
def _environ_cols(file): # pragma: no cover
def _environ_cols_wrapper(): # pragma: no cover
"""
Return a function which gets width and height of console
(linux,osx,windows,cygwin).
"""
import platform
current_os = platform.system()
_environ_cols = None
if current_os == 'Windows':
_environ_cols = _environ_cols_windows
if _environ_cols is None:
_environ_cols = _environ_cols_tput
if current_os in ['Linux', 'Darwin'] or current_os.startswith('CYGWIN'):
_environ_cols = _environ_cols_linux
return _environ_cols
def _environ_cols_windows(fp): # pragma: no cover
try:
from ctypes import windll, create_string_buffer
import struct
from sys import stdin, stdout
io_handle = None
if fp == stdin:
io_handle = -10
elif fp == stdout:
io_handle = -11
else: # assume stderr
io_handle = -12
h = windll.kernel32.GetStdHandle(io_handle)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
if res:
(bufx, bufy, curx, cury, wattr, left, top, right, bottom,
maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
# nlines = bottom - top + 1
return right - left + 1
except:
pass
return None
def _environ_cols_tput(*args): # pragma: no cover
""" cygwin xterm (windows) """
try:
import subprocess
import shlex
cols = int(subprocess.check_call(shlex.split('tput cols')))
# rows = int(subprocess.check_call(shlex.split('tput lines')))
return cols
except:
pass
return None
def _environ_cols_linux(fp): # pragma: no cover
# import os
# if fp is None:
# try:
# fp = os.open(os.ctermid(), os.O_RDONLY)
# except:
# pass
try:
from termios import TIOCGWINSZ
from fcntl import ioctl
@ -29,7 +93,7 @@ def _environ_cols(file): # pragma: no cover
return None
else:
try:
return array('h', ioctl(file, TIOCGWINSZ, '\0' * 8))[1]
return array('h', ioctl(fp, TIOCGWINSZ, '\0' * 8))[1]
except:
try:
from os.environ import get