Permalink
Browse files

Add the -m / --measurement command line argument

This allows you to add or override client measurements from the
command line, which is helpful for quickly generating variations.
Ex: mkpattern ... -m length=20in output.svg

- mkpattern: Parse the -m / --measurement argument. Add to documentation.
- client.py: Refactor measurement-setting code into setMeasurement function.
  • Loading branch information...
sachac committed Oct 27, 2015
1 parent 3be54d1 commit cf757b1244aa9bd5ca7a2cfbb176677950781ae3
Showing with 76 additions and 41 deletions.
  1. +36 −5 standalone/mkpattern
  2. +40 −36 standalone/tmtpl/client.py
View
@@ -88,7 +88,7 @@ class Cmdline:
#
def usage(self, defaults):
stdo(" Usage: \n")
stdo(" %s [--verbose] [--config=<cfg file>] --pattern=<pattern file> --styles=<styles file> --client=<client file> [--debug=[dump]] outfile \n" % self.cfg['app_name'])
stdo(" %s [--verbose] [--config=<cfg file>] --pattern=<pattern file> --styles=<styles file> --client=<client file> [--scale=<scale>] [-m/--measurement <name>=<val><unit>] [--debug=[dump]] outfile \n" % self.cfg['app_name'])
stdo(" \n")
stdo(" Options: \n")
stdo(" --help Prints this text. \n")
@@ -115,6 +115,12 @@ class Cmdline:
stdo(" --client=<client file> \n")
stdo(" The full path to the client data file to use. \n")
stdo(" \n")
stdo(" --scale=<scale> \n")
stdo(" Resize the output by the given factor (ex: 0.2). \n")
stdo(" \n")
stdo(" --measurement <name>=<val><unit> \n")
stdo(" Override a client measurement. Units: in, cm, ft, m \n")
stdo(" \n")
stdo(" --debug=[dump] \n")
stdo(" Performs additional output related to the option enabled and \n")
stdo(" the application defined support for the option. \n")
@@ -133,15 +139,15 @@ class Cmdline:
self.cfg['app_name'] = argv[0]
result = True
try:
optsShort = ''
optsLong = ['help', 'verbose', 'tooltips', 'config=', 'pattern=', 'cfgoptions=', 'printgroups=', 'styles=', 'client=', 'debug=', 'scale=']
optsShort = 'm:'
optsLong = ['help', 'verbose', 'tooltips', 'config=', 'pattern=', 'cfgoptions=', 'printgroups=', 'styles=', 'client=', 'debug=', 'scale=', 'measurement=']
opts, args = getopt(argv[1:], optsShort, optsLong)
if len(args) != 1:
raise CmdlineError('You must supply an output file name\n\n')
self.cfg['args'] = args
self.cfg['measurements'] = {}
for opt, val in opts:
if (opt == '--help'):
raise CmdlineError('')
@@ -176,6 +182,28 @@ class Cmdline:
elif opt in ('--scale'):
self.cfg['scale'] = float(val)
elif opt in ('-m', '--measurement'):
# ex: length=5in
# ex: width=0.25cm
m = re.search('([^=]+)=([0-9\.]+)(inch|cm|CM|in|foot|m|ft|IN"|\')', val)
name = m.group(1)
value = float(m.group(2))
unit = m.group(3)
calc_val = None
if unit in ('cm', 'CM'):
calc_val = value * CM_TO_PX
if unit in ('m', 'M'):
calc_val = value * 100 * CM_TO_PX
elif unit in ('in', 'IN', 'inch', '"'):
calc_val = value * IN_TO_PX
elif unit in ('ft', 'foot', '\''):
calc_val = value * 12 * IN_TO_PX
if calc_val is None:
raise CmdlineError('Unknown unit (should be in, cm, or ft): ' + unit)
else:
# TODO: Inherit the type if specified, and don't limit it to just floats
self.cfg['measurements'][name] = {'value': str(calc_val), 'type': 'float'}
except GetoptError, error:
print(error, defaults)
@@ -275,8 +303,11 @@ class AppTemplate(StdApp):
# open the client file and read the data
client = Client(self.cfg['client_file'])
# override any measurements specified on the command-line
for key, val in self.cfg['measurements'].iteritems():
client.setMeasurement(key, val, 1)
cd = client.data
if dbgdump:
print "========== Client Data Dump =========="
print client.dump(),
View
@@ -60,6 +60,44 @@ def __init__(self, filename, filetype= 'json'):
if filetype == 'json':
self.__readJson__(filename)
def setMeasurement(self, key, val, conversion_factor=None):
keyparts = key.split('.')
if conversion_factor is None:
conversion_factor = self.__conversion__
# make sure the objects are created in the dotted 'path'
parent = self.data
for i in range (0, len(keyparts)-1):
oname = keyparts[i]
if oname not in dir(parent):
# object does not exist, create a new ClientData object within the parent
setattr(parent, oname, ClientData())
# Now, set the parent to be the object we just created
parent = getattr(parent, oname)
else:
# object exists - it better be a clientdata type and not something
# else. This can be caused by errors in the variable naming in the json file
parent = getattr(parent, oname)
if not isinstance(parent, ClientData):
print "########################### ERROR: Malformed Client Data ###########################"
print "\nThe variable named <", oname, "> appears both as an attribute and as a parent"
print "Check the data file <", datafilename, ">"
print "\n####################################################################################"
raise ValueError
# now, we have all the containing objects in place
# get the rightmost part of the dotted variable, and add it
attrname = keyparts[-1]
# Create attribute based on the type in the json data
ty = val['type']
if ty == 'float':
setattr(parent, attrname, float(val['value']) * conversion_factor)
elif ty == 'string':
setattr(parent, attrname, val['value'])
elif ty == 'int':
setattr(parent, attrname, int(val['value']))
else:
raise ValueError('Unknown type ' + ty + 'in client data')
def __readJson__(self, datafilename):
self.info={}
@@ -82,47 +120,13 @@ def __readJson__(self, datafilename):
raise
#
# read all these and then create a heirarchy of objects and
# read all these and then create a hierarchy of objects and
# attributes, based on the 'dotted path' notation.
#
# read everything into attributes
for key, val in self.client.items():
keyparts = key.split('.')
# make sure the objects are created in the dotted 'path'
parent = self.data
for i in range (0, len(keyparts)-1):
oname = keyparts[i]
if oname not in dir(parent):
# object does not exist, create a new ClientData object within the parent
setattr(parent, oname, ClientData())
# Now, set the parent to be the object we just created
parent = getattr(parent, oname)
else:
# object exists - it better be a clientdata type and not something
# else. This can be caused by errors in the variable naming in the json file
parent = getattr(parent, oname)
if not isinstance(parent, ClientData):
print "########################### ERROR: Malformed Client Data ###########################"
print "\nThe valiable named <", oname, "> appears both as an attribute and as a parent"
print "Check the Data file <", datafilename, ">"
print "\n####################################################################################"
raise ValueError
# now, we have all the containing objects in place
# get the rightmost part of the dotted variable, and add it
attrname = keyparts[-1]
# Create attribute based on the type in the json data
ty = val['type']
if ty == 'float':
setattr(parent, attrname, float(val['value']) * self.__conversion__)
elif ty == 'string':
setattr(parent, attrname, val['value'])
elif ty == 'int':
setattr(parent, attrname, int(val['value']))
else:
raise ValueError('Unknown type ' + ty + 'in client data')
self.setMeasurement(key, val)
return
def __dump__(self, obj, parent = '', parentstring = '', outtxt = []):

0 comments on commit cf757b1

Please sign in to comment.