Skip to content

Instantly share code, notes, and snippets.

@dsc
Created October 8, 2012 21:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsc/3855195 to your computer and use it in GitHub Desktop.
Save dsc/3855195 to your computer and use it in GitHub Desktop.
Base class for Python CLI scripts, with example using PIL to display image dimensions on the shell.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" Prints image dimensions.
"""
__author__ = 'David Schoonover <dsc@less.ly>'
import sys, re, argparse
from subprocess import Popen, PIPE, STDOUT, check_output
from path import path
from bunch import *
from lessly import *
from script import Script
from PIL import Image
class ImgScript(Script):
def __init__(self, *args, **options):
super(ImgScript, self).__init__(*args, **options)
if self.includePath is None:
self.includePath = self.__options__['includePath'] = len(self.images) > 1
def run(self):
for img_path in map(path, self.images):
if not img_path.isfile(): continue
info = []
if self.includePath: info += [img_path]
img = Image.open(img_path)
img.load()
w, h = img.size
if self.onlyPrint:
info += [w if self.onlyPrint == 'w' else h]
else:
info += [w, h]
print self.sep.join(map(str, info))
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("-p", "--path", dest='includePath', action="store_true", default=None,
help="Print image path along with dimensions. This defaults to True when more than one path is supplied.")
parser.add_argument("-P", "--no-path", dest='includePath', action="store_false", default=None,
help="Do not print image path along with dimensions, even when more than one path is supplied.")
parser.add_argument("-W", "--width", dest='onlyPrint', action='store_const', default=None, const='w',
help="Only print image width.")
parser.add_argument("-H", "--height", dest='onlyPrint', action='store_const', default=None, const='h',
help="Only print image height.")
parser.add_argument("-s", "--sep", default=' ',
help="Separator between dimensions (and path, if included). [default: %(default)r]")
parser.add_argument('images', nargs='+')
if __name__ == '__main__':
sys.exit(ImgScript.main() or 0)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys, argparse, colorama
from colorama import Fore, Back, Style
__all__ = ('Script',)
ERROR = '%sError:%s ' % (Fore.RED, Style.RESET_ALL)
def add_colors(d):
for color in 'BLACK BLUE CYAN GREEN MAGENTA RED WHITE YELLOW RESET'.split():
d.setdefault(color, getattr(Fore, color))
for style in 'BRIGHT DIM NORMAL RESET_ALL'.split():
d.setdefault(style, getattr(Style, style))
return d
class Script(object):
"Scripting base class."
verbose = True
parser = None
def __init__(self, *args, **options):
self.__dict__.update(**options)
self.__args__ = args
self.__options__ = options
def log(self, message, *args, **kwargs):
"Log a message to stderr if verbose."
_end = kwargs.pop('_end', '\n')
_outfile = kwargs.pop('_outfile', sys.stderr)
_is_error = kwargs.pop('_is_error', False)
if self.verbose or _is_error:
kwargs.setdefault('self', self)
msg = (ERROR if _is_error else '') + message.format(*args, **kwargs) + Style.RESET_ALL
print(msg, end=_end, file=_outfile)
return True
def error(self, message, *args, **kwargs):
"Log a non-fatal error to stderr. (For fatal errors, just raise.)"
kwargs.setdefault('_is_error', True)
return self.log(message, *args, **kwargs)
def run(self):
raise Exception('Script.run() is not implemented!')
def __call__(self, *args, **kwargs):
return self.run(*args, **kwargs)
def __repr__(self):
return '{self.__class__.__name__}(options={self.__options__!r})'.format(self=self)
def __str__(self):
return repr(self)
@classmethod
def parse(cls, *args, **overrides):
parsed = cls.parser.parse_args(args or None)
values = dict(**parsed.__dict__)
values.update(overrides)
return values
@classmethod
def create(cls, *args, **overrides):
values = cls.parse(*args, **overrides)
return cls(**values)
@classmethod
def main(cls, *args, **overrides):
return cls.create(*args, **overrides)() or 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment