#
#  $Id: Options.py,v 1.5 1999/12/11 12:35:12 rob Exp $
#
#  Copyright 1998-1999 Rob Tillotson <robt@debian.org>
#  All Rights Reserved
#
#  Permission to use, copy, modify, and distribute this software and
#  its documentation for any purpose and without fee or royalty is
#  hereby granted, provided that the above copyright notice appear in
#  all copies and that both the copyright notice and this permission
#  notice appear in supporting documentation or portions thereof,
#  including modifications, that you you make.
#
#  THE AUTHOR ROB TILLOTSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
#  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
#  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
#  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
#  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
#  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE!
#
"""Option processing.
"""

__version__ = '$Id: Options.py,v 1.5 1999/12/11 12:35:12 rob Exp $'

__copyright__ = 'Copyright 1998-1999 Rob Tillotson <robt@debian.org>'

import string

STRING = 'string'
INTEGER = 'int'
FLOAT = 'float'
BOOLEAN = 'boolean'
CHOICE = 'choice'
FILENAME = 'filename'

defaults = {
    STRING: '',
    INTEGER: 0,
    FLOAT: 0.0,
    BOOLEAN: None,
    CHOICE: None,
    FILENAME: ''
    }

ValidationError = 'Options.ValidationError'

O_NOSAVE = 'nosave'  # don't save into config file
O_NOCONFIG = 'noconfig'  # don't use config file at all
O_NONINTERACTIVE = 'noninteractive'  # don't configure interactively
O_NOCMDLINE = 'nocmdline'  # allow use on the command line
O_MULTIPLE = 'multiple' # has multiple values

class Option:
    """An option definition, and possibly its value."""
    def __init__(self, name, type=STRING, default=None, title=None, \
		 description=None,
		 flags=None,
		 cmd_names=None,
		 **kw):
	self.name = name
	self.type = type
	self.title = title
	self.flags = flags
	self.cmd_names = cmd_names
	self.description = description
	if not default:
	    self.default = defaults[type]
	else:
	    self.default = default

	for k, v in kw.items():
	    setattr(self, k, v)

    def __repr__(self):
	return '<%s option: %s>' % (self.type, self.name)
    
    def from_str(self, s):
	pass
    
    def validate(self, value=None):
	return None

    def has_flag(self, flag): return self.flags and (flag in self.flags)
    
	
class String(Option):
    def __init__(self, name, default=None, title=None, description=None,
		 flags = None, cmd_names = None,
		 match=None, **kw):
	apply(Option.__init__, (self, name, STRING, default, title, description,
				flags, cmd_names), kw)
	self.match = match

    def from_str(self, s):
	self.validate(s)
	return s
	
    def validate(self, value=None):
	if type(value) != type(''):
	    raise ValidationError, 'Type mismatch.'
	if self.match:
	    if not re.match(self.match, value):
		raise ValidationError, "Failed to match pattern '%s'." % self.match
	    
	
class Integer(Option):
    def __init__(self, name, default=None, title=None, description=None,
		 flags=None, cmd_names=None,
		 min=None, max=None, **kw):
	apply(Option.__init__, (self, name, INTEGER, default, title, description,
				flags, cmd_names), kw)
	self.min = min
	self.max = max

    def from_str(self, s):
	v = string.atoi(string.strip(s))
	self.validate(v)
	return v
	
    def validate(self, value=None):
	if type(value) != type(1):
	    raise ValidationError, 'Type mismatch.'
	if self.min is not None and value < self.min:
	    raise ValidationError, "Value must be at least %s." % self.min
	if self.max is not None and value >= self.max:
	    raise ValidationError, "Value must be less than %s." % self.max
	
class Float(Option):
    def __init__(self, name, default=None, title=None, description=None,
		 flags=None, cmd_names=None,
		 min=None, max=None, **kw):
	apply(Option.__init__, (self, name, FLOAT, default, title, description,
				flags, cmd_names), kw)
	self.min = min
	self.max = max

    def from_str(self, s):
	v = string.atof(string.strip(s))
	self.validate(v)
	return v
	
    def validate(self, value=None):
	if type(value) != type(1.1):
	    raise ValidationError, 'Type mismatch.'
	if self.min is not None and value < self.min:
	    raise ValidationError, "Value must be at least %s." % self.min
	if self.max is not None and value >= self.max:
	    raise ValidationError, "Value must be less than %s." % self.max
	
class Boolean(Option):
    def __init__(self, name, default=None, title=None, description=None,
		 flags=None, cmd_names=None, **kw):
	apply(Option.__init__, (self, name, BOOLEAN, default, title, description,
				flags, cmd_names), kw)

    def from_str(self, s):
	v = string.lower(string.strip(s))
	if v in ['yes', 'true', '1', 'y', 't']:
	    return 1
	else:
	    return None
	
	    
class Choice(Option):
    def __init__(self, name, default=None, title=None, description=None, \
		 flags=None, cmd_names=None,
		 items=None, values=None, **kw):
	apply(Option.__init__, (self, name, CHOICE, default, title, description,
				contexts, context_info), kw)
	self.items = items is not None and items or []
	self.values = values is not None and values or []

    def from_str(self, s):
	s = string.strip(s)
	if s in self.items: return self.values[self.items.index(s)]
	else: return s

class Filename(String):
    def __init__(self, name, default=None, title=None, description=None, \
		 flags=None, cmd_names=None,
		 initialdir=None, filetypes=None, **kw):
	apply(String.__init__, (self, name, default, title, description,
				flags, cmd_names), kw)
	self.type = FILENAME
	self.initialdir = initialdir
	self.filetypes = filetypes

	
    
