From c67d4f273cfe5896a6f9c131b9e813543d50aa46 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 3 Aug 2010 16:26:37 -0400 Subject: [PATCH] Broke type conversion out into hooke.util.convert and expanded its use. --- hooke/config.py | 25 +++------------- hooke/plugin/curve.py | 2 +- hooke/plugin/playlist.py | 2 +- hooke/plugin/playlists.py | 2 +- hooke/plugin/vclamp.py | 10 +++---- hooke/ui/commandline.py | 34 +++++++++++++++++---- hooke/util/convert.py | 63 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 104 insertions(+), 34 deletions(-) create mode 100644 hooke/util/convert.py diff --git a/hooke/config.py b/hooke/config.py index c1776c8..1c5c487 100644 --- a/hooke/config.py +++ b/hooke/config.py @@ -26,6 +26,7 @@ import textwrap import unittest from .compat.odict import odict as OrderedDict +from .util.convert import to_string, from_string DEFAULT_PATHS = [ @@ -39,24 +40,6 @@ specific user files, so the user can override the sysadmin who in turn overrides the developer defaults. """ -CONVERT_FROM_STRING = { - 'string': lambda x: x, - 'bool': lambda x: x == 'True', - 'int': lambda x: int(x), - 'float': lambda x: float(x), - } -"""Functions converting strings to values, keyed by type. -""" - -CONVERT_TO_STRING = { - 'string': lambda x: x, - 'bool': lambda x: str(x), - 'int': lambda x: str(x), - 'float': lambda x: str(x), - } -"""Functions converting values to strings, keyed by type. -""" - class Setting (object): """An entry (section or option) in HookeConfigParser. """ @@ -64,7 +47,7 @@ class Setting (object): help=None, wrap=True): self.section = section self.option = option - self.value = CONVERT_TO_STRING[type](value) + self.value = to_string(value=value, type=type) self.type = type self.help = help self.wrap = wrap @@ -316,13 +299,13 @@ class HookeConfigParser (configparser.RawConfigParser): for i,kv in enumerate(items): key,value = kv setting = self._default_settings_dict[(section, key)] - items[i] = (key, CONVERT_FROM_STRING[setting.type](value)) + items[i] = (key, from_string(value=value, type=setting.type)) return items def set(self, section, option, value): """Set an option.""" setting = self._default_settings_dict[(section, option)] - value = CONVERT_TO_STRING[setting.type](value) + value = to_string(value=value, type=setting.type) # Can't use super() because RawConfigParser is a classic class #return super(HookeConfigParser, self).set(section, option, value) configparser.RawConfigParser.set(self, section, option, value) diff --git a/hooke/plugin/curve.py b/hooke/plugin/curve.py index 7621fc7..6221dbe 100644 --- a/hooke/plugin/curve.py +++ b/hooke/plugin/curve.py @@ -163,7 +163,7 @@ True if you want the column-naming header line. help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - data = params['curve'].data[int(params['block'])] # HACK, int() should be handled by ui + data = params['curve'].data[params['block']] f = open(params['output'], 'w') if params['header'] == True: diff --git a/hooke/plugin/playlist.py b/hooke/plugin/playlist.py index 73fd5a3..dccc572 100644 --- a/hooke/plugin/playlist.py +++ b/hooke/plugin/playlist.py @@ -117,7 +117,7 @@ Index of target curve. help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - params['playlist'].jump(int(params['index'])) # HACK, int() should be handled by ui + params['playlist'].jump(params['index']) class IndexCommand (Command): """Print the index of the current curve. diff --git a/hooke/plugin/playlists.py b/hooke/plugin/playlists.py index 44bbe92..2ba4ecf 100644 --- a/hooke/plugin/playlists.py +++ b/hooke/plugin/playlists.py @@ -71,7 +71,7 @@ Index of target curve. help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - hooke.playlists.jump(int(params['index'])) # HACK, int() should be handled by ui + hooke.playlists.jump(params['index']) class IndexCommand (Command): """Print the index of the current playlist. diff --git a/hooke/plugin/vclamp.py b/hooke/plugin/vclamp.py index 5751d38..2365122 100644 --- a/hooke/plugin/vclamp.py +++ b/hooke/plugin/vclamp.py @@ -246,7 +246,7 @@ selects the retracting curve. help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - data = params['curve'].data[int(params['block'])] # HACK, int() should be handled by ui + data = params['curve'].data[params['block']] # HACK? rely on params['curve'] being bound to the local hooke # playlist (i.e. not a copy, as you would get by passing a # curve through the queue). Ugh. Stupid queues. As an @@ -267,8 +267,8 @@ selects the retracting curve. new.info['surface detection parameters'] = ps new[:,-2] = z_data - surface_offset new[:,-1] = d_data - deflection_offset - data = params['curve'].data[int(params['block'])] # HACK, int() should be handled by ui - params['curve'].data[int(params['block'])] = new # HACK, int() should be handled by ui + data = params['curve'].data[params['block']] + params['curve'].data[params['block']] = new def find_contact_point(self, curve, z_data, d_data, outqueue=None): """Railyard for the `find_contact_point_*` family. @@ -433,7 +433,7 @@ selects the retracting curve. help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - data = params['curve'].data[int(params['block'])] # HACK, int() should be handled by ui + data = params['curve'].data[params['block']] # HACK? rely on params['curve'] being bound to the local hooke # playlist (i.e. not a copy, as you would get by passing a # curve through the queue). Ugh. Stupid queues. As an @@ -445,7 +445,7 @@ selects the retracting curve. new.info['columns'].append('deflection (N)') d_data = data[:,data.info['columns'].index('surface adjusted deflection (m)')] new[:,-1] = d_data * data.info['spring constant (N/m)'] - params['curve'].data[int(params['block'])] = new # HACK, int() should be handled by ui + params['curve'].data[params['block']] = new class generalvclampCommands(object): diff --git a/hooke/ui/commandline.py b/hooke/ui/commandline.py index 132d657..4baaf85 100644 --- a/hooke/ui/commandline.py +++ b/hooke/ui/commandline.py @@ -29,6 +29,7 @@ import shlex from ..command import CommandExit, Exit, Command, Argument, StoreValue from ..interaction import Request, BooleanRequest, ReloadUserInterfaceConfig from ..ui import UserInterface, CommandMessage +from ..util.convert import from_string from ..util.encoding import get_input_encoding, get_output_encoding @@ -53,8 +54,27 @@ class CommandLineParser (optparse.OptionParser): continue # 'help' is a default OptionParser option if a.optional == True: name = name_fn(a.name) + type = a.type + if type == 'bool': + if a.default == True: + self.add_option( + '--disable-%s' % name, dest=name, default=Default, + action='store_false') + self.command_opts.append(a) + continue + elif a.default == False: + self.add_option( + '--enable-%s' % name, dest=name, default=Default, + action='store_true') + self.command_opts.append(a) + continue + else: + type = 'string' + elif type not in ['string', 'int', 'long', 'choice', 'float', + 'complex']: + type = 'string' self.add_option( - '--%s' % name, dest=name, default=Default) + '--%s' % name, dest=name, type=type, default=Default) self.command_opts.append(a) else: self.command_args.append(a) @@ -102,6 +122,7 @@ class DoCommand (CommandMethod): self.cmd.stdout.write(str(e).lstrip()+'\n') self.cmd.stdout.write('Failure\n') return + print args self.cmd.inqueue.put(CommandMessage(self.command, args)) while True: msg = self.cmd.outqueue.get() @@ -130,12 +151,15 @@ class DoCommand (CommandMethod): arg_index = 0 for argument in self.parser.command_args: if argument.count == 1: - params[argument.name] = args[arg_index] + params[argument.name] = from_string(args[arg_index], + argument.type) elif argument.count > 1: - params[argument.name] = \ - args[arg_index:arg_index+argument.count] + params[argument.name] = [ + from_string(a, argument.type) + for a in args[arg_index:arg_index+argument.count]] else: # argument.count == -1: - params[argument.name] = args[arg_index:] + params[argument.name] = [ + from_string(a, argument.type) for a in args[arg_index:]] arg_index += argument.count return params diff --git a/hooke/util/convert.py b/hooke/util/convert.py new file mode 100644 index 0000000..92e6b64 --- /dev/null +++ b/hooke/util/convert.py @@ -0,0 +1,63 @@ +# Copyright + +"""Type conversion utilities. +""" + +CONVERT_FROM_STRING = { + 'string': lambda x: x, + 'bool': lambda x: x == 'True', + 'int': lambda x: int(x), + 'float': lambda x: float(x), + } +"""Functions converting strings to values, keyed by type. +""" + +ANALOGS = { + 'file': 'string', + 'point': 'int', + } +"""Types that may be treated as other types. + +These types may have optional special handling on the UI end +(e.g. file picker dialogs), but it is not required. +""" + +RAW_TYPES = [ + 'curve', + 'dict', + 'driver', + 'function', + 'object', + 'playlist', + ] +"""List of types that should not be converted. +""" + +def to_string(value, type): + """Convert `value` from `type` to a unicode string. + """ + type = ANALOGS.get(type, type) + if type in RAW_TYPES: + return value + return unicode(value) + +def from_string(value, type): + """Convert `value` from a string to `type`. + """ + type = ANALOGS.get(type, type) + if type in RAW_TYPES: + return value + fn = globals()['_string_to_%s' % type] + return fn(value) + +def _string_to_string(value): + return unicode(value) + +def _string_to_bool(value): + return value == 'True' + +def _string_to_int(value): + return int(value) + +def _string_to_float(value): + return float(value) -- 2.26.2