frappy/src/validators.py
Enrico Faulhaber c11bca3c37 rework on transport (encoding/framing) and dispatcher
put encoders and framers into their own files.
also rework messages and dispatcher
make tcpserver functional

FIRST WORKING VERSION!
(no daemon mode yet, sorry)

start bin/server.py, connect a terminal to localhost:10767
and press enter....

note: not all requests are bug free yet, ListDevicesRequest() works

Change-Id: I46d6e469bca32fc53057d64ff48cce4f41ea12ea
2016-06-29 18:14:55 +02:00

123 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
# *****************************************************************************
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Module authors:
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
#
# *****************************************************************************
"""Define validators."""
# a Validator returns a validated object or raises an ValueError
# easy python validators: int(), float(), str()
# also validators should have a __repr__ returning a 'python' string
# which recreates them
class Validator(object):
# list of tuples: (name, converter)
params = []
valuetype = float
def __init__(self, *args, **kwds):
plist = self.params[:]
if len(args) > len(plist):
raise ProgrammingError('%s takes %d parameters only (%d given)' % (
self.__class__.__name__,
len(plist), len(args)))
for pval in args:
pname, pconv = plist.pop(0)
if pname in kwds:
raise ProgrammingError('%s: positional parameter %s als given '
'as keyword!' % (
self.__class__.__name__,
pname))
self.__dict__[pname] = pconv(pval)
for pname, pconv in plist:
if pname in kwds:
pval = kwds.pop(pname)
self.__dict__[pname] = pconv(pval)
else:
raise ProgrammingError('%s: param %s left unspecified!' % (
self.__class__.__name__,
pname))
if kwds:
raise ProgrammingError('%s got unknown arguments: %s' % (
self.__class__.__name__,
', '.join(list(kwds.keys()))))
def __repr__(self):
params = ['%s=%r' % (pn, self.__dict__[pn]) for pn in self.params]
return ('%s(%s)' % (self.__class__.__name__, ', '.join(params)))
def __call__(self, value):
return self.check(self.valuetype(value))
class floatrange(Validator):
params = [('lower', float), ('upper', float)]
def check(self, value):
if self.lower <= value <= self.upper:
return value
raise ValueError('Floatrange: value %r must be within %f and %f' %
(value, self.lower, self.upper))
class positive(Validator):
def check(self, value):
if value > 0:
return value
raise ValueError('Value %r must be positive!' % obj)
class nonnegative(Validator):
def check(self, value):
if value >= 0:
return value
raise ValueError('Value %r must be positive!' % obj)
# more complicated validator may not be able to use validator base class
class mapping(object):
def __init__(self, *args, **kwds):
self.mapping = {}
# use given kwds directly
self.mapping.update(kwds)
# enumerate args
i = -1
args = list(args)
while args:
i += 1
if i in self.mapping:
continue
self.mapping[args.pop(0)] = i
# generate reverse mapping too for use by protocol
self.revmapping = {}
for k, v in self.mapping.items():
self.revmapping[v] = k
def __call__(self, obj):
if obj in self.mapping:
return obj
raise ValueError("%r should be one of %r" %
(obj, list(self.mapping.keys())))
def __repr__(self):
params = ['%s=%r' % (mname, mval) for mname, mval in self.mapping]
return ('%s(%s)' % (self.__class__.__name__, ', '.join(params)))