0

I'm implementing a little UserOptionHandler class in python. It goes something like this:

class OptionValue():
   __init__(self, default_value, value_type=None):
      self.value=default_value

      if value_type == None:
         self.value_type = type( default_value )
      else:
         self.value_type = value_type

class OptionHandler():
   __init__(self, option_list):
      self.options = {}

      for opt_spec in option_list:
          key, value, value_type = opt_spec
          self.options[key] = Option( value, value_type )

   def set(self, key, value):
      opt = self.options[key]
      opt.value = value

When I get user input to set the value for an option, I want to make sure that they've entered sane. Otherwise, the application run until it gets to a state where it uses the option, which may or may not crash it.

How do you do something like the following?

opt = handler.get( key )
user_input = input("Enter value for {0}:".format(key) )
if( magic_castable_test( user_input, opt.value_type ) ):
   print "Your value will work!"
else:
   print "You value will break things!"
ajwood
  • 18,227
  • 15
  • 61
  • 104
  • I think input should be validated at the time it's entered. If an option needs to be an int but the user specifies a float, they should know about it immediately and maybe get prompted for a new value, rather than the program crashing some time later when the bad value gets used. – ajwood Mar 14 '12 at 23:08

3 Answers3

1
  • Put every separate type (of user options) into separate class!
  • Add methods that decide if raw user input can be expressed by type "tied" to class.
  • Make Option handler run raw user input through list of all possible types - classes.

' If any class say that raw user input can be translated into its value than you know that user input is valid. If more than one class can store user input, then there is ambiguity, and you did provided too little info to suggest you anything then.

'' If no class claim ability to store user input, then you know that user provided wrong input!

  • Get back to your methods and make sure that they are malicious-user-proof.

If validation is simple you can use re module (regular expresion) to quickly and simply extract valid values. However if validation is more complex then you need to implement it by other means (since complex regular expressions are ... complex)

przemo_li
  • 3,932
  • 4
  • 35
  • 60
1

i'm not sure i follow what you're asking, but i think that you just need to use type itself because:

  • user input is a string

  • many types, like int and float are functions/constructors that return an instance from a string. for example int("3") returns the integer 3.

so in your code, you would replace

if( magic_castable_test( user_input, opt.value_type ) ):
   print "Your value will work!"
else:
   print "You value will break things!"

with:

value = None
try:
    value = opt.value_type(value)
except:
    pass
if value is None:
    print "Your value will work!  It is", value
else:
    print "Your value will not work

where i am assuming it's an error if either (1) an exception is thrown or (2) the type returning null.

and you can take this further and simply require that any types work this way. so, for example, you might have some information that is best represented as a custom class. then you should write the class so that it has an __init__ that takes a single string:

class MyClass:
    def __init__(self, s):
        # do something with string s here

and you can then pass MyClass as an option type to your code above.

ps here's perhaps a clearer example of what i mean:

>>> type(4)("3")
3
>>> type(type(4)("3"))
<type 'int'>
andrew cooke
  • 45,717
  • 10
  • 93
  • 143
0

are you looking for isinstance(user_input, opt.value_type)? http://docs.python.org/library/functions.html#isinstance

story645
  • 566
  • 3
  • 13
  • I don't think so. `isinstance( '1', type(1.0) )` would have to return `True`, since '1' would be value input to a float type. – ajwood Mar 14 '12 at 23:01
  • oops, 'value' should be 'valid' – ajwood Mar 14 '12 at 23:09
  • oh, I think you're gonna have to write that. Something like `typetest = {'opt.value_type': isdigit()} user_input.typetest[opt.value_type]` – story645 Mar 14 '12 at 23:11
  • And checking floating point is a custom job: http://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-in-python. @przemo_li's solution of writing wrapper classes for each option type also works well 'cause then you can just pop that into isinstance – story645 Mar 14 '12 at 23:25