Print usage information if no input file was specified (and no data is available from stdin) (#65)

fixes #34
This commit is contained in:
Eduard Braun 2016-08-23 21:16:14 +02:00 committed by GitHub
parent 57f93efc89
commit 4f23ea7a34
2 changed files with 61 additions and 50 deletions

View file

@ -3263,13 +3263,6 @@ _option_group_compatibility.add_option("--error-on-flowtext",
_options_parser.add_option_group(_option_group_compatibility) _options_parser.add_option_group(_option_group_compatibility)
def maybe_gziped_file(filename, mode="r"):
if os.path.splitext(filename)[1].lower() in (".svgz", ".gz"):
import gzip
return gzip.GzipFile(filename, mode)
return open(filename, mode)
def parse_args(args=None, ignore_additional_args=False): def parse_args(args=None, ignore_additional_args=False):
options, rargs = _options_parser.parse_args(args) options, rargs = _options_parser.parse_args(args)
@ -3290,6 +3283,42 @@ def parse_args(args=None, ignore_additional_args=False):
if options.infilename and options.outfilename and options.infilename == options.outfilename: if options.infilename and options.outfilename and options.infilename == options.outfilename:
_options_parser.error("Input filename is the same as output filename") _options_parser.error("Input filename is the same as output filename")
return options
def generateDefaultOptions():
## FIXME: clean up this mess/hack and refactor arg parsing to argparse
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
d = parse_args(args = [], ignore_additional_args = True).__dict__.copy()
return Struct(**d)
# sanitizes options by updating attributes in a set of defaults options while discarding unknown attributes
def sanitizeOptions(options):
optionsDict = dict((key, getattr(options, key)) for key in dir(options) if not key.startswith('__'))
sanitizedOptions = _options_parser.get_default_values()
sanitizedOptions._update_careful(optionsDict)
return sanitizedOptions
def maybe_gziped_file(filename, mode="r"):
if os.path.splitext(filename)[1].lower() in (".svgz", ".gz"):
import gzip
return gzip.GzipFile(filename, mode)
return open(filename, mode)
def getInOut(options):
if options.infilename: if options.infilename:
infile = maybe_gziped_file(options.infilename, "rb") infile = maybe_gziped_file(options.infilename, "rb")
# GZ: could catch a raised IOError here and report # GZ: could catch a raised IOError here and report
@ -3298,9 +3327,13 @@ def parse_args(args=None, ignore_additional_args=False):
# #
# open the binary buffer of stdin and let XML parser handle decoding # open the binary buffer of stdin and let XML parser handle decoding
try: try:
infile = sys.stdin.buffer infile = sys.stdin.buffer
except AttributeError: except AttributeError:
infile = sys.stdin infile = sys.stdin
# the user probably does not want to manually enter SVG code into the terminal...
if sys.stdin.isatty():
_options_parser.error("No input file specified, see --help for detailed usage information")
if options.outfilename: if options.outfilename:
outfile = maybe_gziped_file(options.outfilename, "wb") outfile = maybe_gziped_file(options.outfilename, "wb")
else: else:
@ -3310,7 +3343,7 @@ def parse_args(args=None, ignore_additional_args=False):
except AttributeError: except AttributeError:
outfile = sys.stdout outfile = sys.stdout
return options, [infile, outfile] return [infile, outfile]
@ -3331,29 +3364,6 @@ def getReport():
def generateDefaultOptions():
## FIXME: clean up this mess/hack and refactor arg parsing to argparse
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
d = parse_args(args = [], ignore_additional_args = True)[0].__dict__.copy()
return Struct(**d)
# sanitizes options by updating attributes in a set of defaults options while discarding unknown attributes
def sanitizeOptions(options):
optionsDict = dict((key, getattr(options, key)) for key in dir(options) if not key.startswith('__'))
sanitizedOptions = _options_parser.get_default_values()
sanitizedOptions._update_careful(optionsDict)
return sanitizedOptions
def start(options, input, output): def start(options, input, output):
start = walltime() start = walltime()
@ -3388,7 +3398,8 @@ def start(options, input, output):
def run(): def run():
options, (input, output) = parse_args() options = parse_args()
(input, output) = getInOut(options)
start(options, input, output) start(options, input, output)

View file

@ -193,7 +193,7 @@ class RemoveUnreferencedDefs(unittest.TestCase):
class KeepUnreferencedDefs(unittest.TestCase): class KeepUnreferencedDefs(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/unreferenced-defs.svg', doc = scour.scourXmlFile('unittests/unreferenced-defs.svg',
scour.parse_args(['--keep-unreferenced-defs'])[0]) scour.parse_args(['--keep-unreferenced-defs']))
self.assertEqual(len(doc.getElementsByTagNameNS(SVGNS, 'linearGradient')), 1, self.assertEqual(len(doc.getElementsByTagNameNS(SVGNS, 'linearGradient')), 1,
'Referenced linearGradient removed from defs with `--keep-unreferenced-defs`' ) 'Referenced linearGradient removed from defs with `--keep-unreferenced-defs`' )
self.assertEqual(len(doc.getElementsByTagNameNS(SVGNS, 'radialGradient')), 1, self.assertEqual(len(doc.getElementsByTagNameNS(SVGNS, 'radialGradient')), 1,
@ -233,7 +233,7 @@ class KeepUnreferencedIDsWhenEnabled(unittest.TestCase):
class RemoveUnreferencedIDsWhenEnabled(unittest.TestCase): class RemoveUnreferencedIDsWhenEnabled(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/ids-to-strip.svg', doc = scour.scourXmlFile('unittests/ids-to-strip.svg',
scour.parse_args(['--enable-id-stripping'])[0]) scour.parse_args(['--enable-id-stripping']))
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'svg')[0].getAttribute('id'), '', self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'svg')[0].getAttribute('id'), '',
'<svg> ID not stripped' ) '<svg> ID not stripped' )
@ -246,7 +246,7 @@ class RemoveUselessNestedGroups(unittest.TestCase):
class DoNotRemoveUselessNestedGroups(unittest.TestCase): class DoNotRemoveUselessNestedGroups(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/nested-useless-groups.svg', doc = scour.scourXmlFile('unittests/nested-useless-groups.svg',
scour.parse_args(['--disable-group-collapsing'])[0]) scour.parse_args(['--disable-group-collapsing']))
self.assertEqual(len(doc.getElementsByTagNameNS(SVGNS, 'g')), 2, self.assertEqual(len(doc.getElementsByTagNameNS(SVGNS, 'g')), 2,
'Useless nested groups were removed despite --disable-group-collapsing' ) 'Useless nested groups were removed despite --disable-group-collapsing' )
@ -495,7 +495,7 @@ class RemoveFillOpacityWhenFillNone(unittest.TestCase):
class ConvertFillPropertyToAttr(unittest.TestCase): class ConvertFillPropertyToAttr(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/fill-none.svg', doc = scour.scourXmlFile('unittests/fill-none.svg',
scour.parse_args(['--disable-simplify-colors'])[0]) scour.parse_args(['--disable-simplify-colors']))
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'path')[1].getAttribute('fill'), 'black', self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'path')[1].getAttribute('fill'), 'black',
'fill property not converted to XML attribute' ) 'fill property not converted to XML attribute' )
@ -1144,7 +1144,7 @@ class PathImplicitLineWithMoveCommands(unittest.TestCase):
class RemoveMetadataOption(unittest.TestCase): class RemoveMetadataOption(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/full-metadata.svg', doc = scour.scourXmlFile('unittests/full-metadata.svg',
scour.parse_args(['--remove-metadata'])[0]) scour.parse_args(['--remove-metadata']))
self.assertEqual(doc.childNodes.length, 1, self.assertEqual(doc.childNodes.length, 1,
'Did not remove <metadata> tag with --remove-metadata') 'Did not remove <metadata> tag with --remove-metadata')
@ -1153,7 +1153,7 @@ class EnableCommentStrippingOption(unittest.TestCase):
with open('unittests/comment-beside-xml-decl.svg') as f: with open('unittests/comment-beside-xml-decl.svg') as f:
docStr = f.read() docStr = f.read()
docStr = scour.scourString(docStr, docStr = scour.scourString(docStr,
scour.parse_args(['--enable-comment-stripping'])[0]) scour.parse_args(['--enable-comment-stripping']))
self.assertEqual(docStr.find('<!--'), -1, self.assertEqual(docStr.find('<!--'), -1,
'Did not remove document-level comment with --enable-comment-stripping') 'Did not remove document-level comment with --enable-comment-stripping')
@ -1162,14 +1162,14 @@ class StripXmlPrologOption(unittest.TestCase):
with open('unittests/comment-beside-xml-decl.svg') as f: with open('unittests/comment-beside-xml-decl.svg') as f:
docStr = f.read() docStr = f.read()
docStr = scour.scourString(docStr, docStr = scour.scourString(docStr,
scour.parse_args(['--strip-xml-prolog'])[0]) scour.parse_args(['--strip-xml-prolog']))
self.assertEqual(docStr.find('<?xml'), -1, self.assertEqual(docStr.find('<?xml'), -1,
'Did not remove <?xml?> with --strip-xml-prolog') 'Did not remove <?xml?> with --strip-xml-prolog')
class ShortenIDsOption(unittest.TestCase): class ShortenIDsOption(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/shorten-ids.svg', doc = scour.scourXmlFile('unittests/shorten-ids.svg',
scour.parse_args(['--shorten-ids'])[0]) scour.parse_args(['--shorten-ids']))
gradientTag = doc.getElementsByTagName('linearGradient')[0] gradientTag = doc.getElementsByTagName('linearGradient')[0]
self.assertEqual(gradientTag.getAttribute('id'), 'a', self.assertEqual(gradientTag.getAttribute('id'), 'a',
"Did not shorten a linear gradient's ID with --shorten-ids") "Did not shorten a linear gradient's ID with --shorten-ids")
@ -1186,28 +1186,28 @@ class MustKeepGInSwitch(unittest.TestCase):
class MustKeepGInSwitch2(unittest.TestCase): class MustKeepGInSwitch2(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/groups-in-switch-with-id.svg', doc = scour.scourXmlFile('unittests/groups-in-switch-with-id.svg',
scour.parse_args(['--enable-id-stripping'])[0]) scour.parse_args(['--enable-id-stripping']))
self.assertEqual(doc.getElementsByTagName('g').length, 1, self.assertEqual(doc.getElementsByTagName('g').length, 1,
'Erroneously removed a <g> in a <switch>') 'Erroneously removed a <g> in a <switch>')
class GroupCreation(unittest.TestCase): class GroupCreation(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/group-creation.svg', doc = scour.scourXmlFile('unittests/group-creation.svg',
scour.parse_args(['--create-groups'])[0]) scour.parse_args(['--create-groups']))
self.assertEqual(doc.getElementsByTagName('g').length, 1, self.assertEqual(doc.getElementsByTagName('g').length, 1,
'Did not create a <g> for a run of elements having similar attributes') 'Did not create a <g> for a run of elements having similar attributes')
class GroupCreationForInheritableAttributesOnly(unittest.TestCase): class GroupCreationForInheritableAttributesOnly(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/group-creation.svg', doc = scour.scourXmlFile('unittests/group-creation.svg',
scour.parse_args(['--create-groups'])[0]) scour.parse_args(['--create-groups']))
self.assertEqual(doc.getElementsByTagName('g').item(0).getAttribute('y'), '', self.assertEqual(doc.getElementsByTagName('g').item(0).getAttribute('y'), '',
'Promoted the uninheritable attribute y to a <g>') 'Promoted the uninheritable attribute y to a <g>')
class GroupNoCreation(unittest.TestCase): class GroupNoCreation(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/group-no-creation.svg', doc = scour.scourXmlFile('unittests/group-no-creation.svg',
scour.parse_args(['--create-groups'])[0]) scour.parse_args(['--create-groups']))
self.assertEqual(doc.getElementsByTagName('g').length, 0, self.assertEqual(doc.getElementsByTagName('g').length, 0,
'Created a <g> for a run of elements having dissimilar attributes') 'Created a <g> for a run of elements having dissimilar attributes')
@ -1246,7 +1246,7 @@ class ShortenIDsInStyleCDATA(unittest.TestCase):
with open('unittests/style-cdata.svg') as f: with open('unittests/style-cdata.svg') as f:
docStr = f.read() docStr = f.read()
docStr = scour.scourString(docStr, docStr = scour.scourString(docStr,
scour.parse_args(['--shorten-ids'])[0]) scour.parse_args(['--shorten-ids']))
self.assertEqual(docStr.find('somethingreallylong'), -1, self.assertEqual(docStr.find('somethingreallylong'), -1,
'Did not shorten IDs in the internal stylesheet') 'Did not shorten IDs in the internal stylesheet')
@ -1436,7 +1436,7 @@ class TransformIdentityTranslate(unittest.TestCase):
class DuplicateGradientsUpdateStyle(unittest.TestCase): class DuplicateGradientsUpdateStyle(unittest.TestCase):
def runTest(self): def runTest(self):
doc = scour.scourXmlFile('unittests/duplicate-gradients-update-style.svg', doc = scour.scourXmlFile('unittests/duplicate-gradients-update-style.svg',
scour.parse_args(['--disable-style-to-xml'])[0]) scour.parse_args(['--disable-style-to-xml']))
gradientTag = doc.getElementsByTagName('linearGradient')[0] gradientTag = doc.getElementsByTagName('linearGradient')[0]
rectTag0 = doc.getElementsByTagName('rect')[0] rectTag0 = doc.getElementsByTagName('rect')[0]
rectTag1 = doc.getElementsByTagName('rect')[1] rectTag1 = doc.getElementsByTagName('rect')[1]
@ -1449,13 +1449,13 @@ class DocWithFlowtext(unittest.TestCase):
def runTest(self): def runTest(self):
with self.assertRaises(Exception): with self.assertRaises(Exception):
scour.scourXmlFile('unittests/flowtext.svg', scour.scourXmlFile('unittests/flowtext.svg',
scour.parse_args(['--error-on-flowtext'])[0]) scour.parse_args(['--error-on-flowtext']))
class DocWithNoFlowtext(unittest.TestCase): class DocWithNoFlowtext(unittest.TestCase):
def runTest(self): def runTest(self):
try: try:
scour.scourXmlFile('unittests/flowtext-less.svg', scour.scourXmlFile('unittests/flowtext-less.svg',
scour.parse_args(['--error-on-flowtext'])[0]) scour.parse_args(['--error-on-flowtext']))
except Exception as e: except Exception as e:
self.fail("exception '{}' was raised, and we didn't expect that!".format(e)) self.fail("exception '{}' was raised, and we didn't expect that!".format(e))