0

In this class:

class message:
    def __init__(self, node_info = None):
       if node_info is None: node_info = []
       self.node_info = node_info

    @property
    def node_info(self):
        return self._node_info

    @node_info.setter
    def node_info(self, value):
        self._node_info = value

node_info should have a layout similar to this:

sample_node_info = [
  'Node Name',
  'Node URL',
  status,
  ['Service1','ServiceURL1',status],
  ['Service2','ServiceURL2',status]
]

The first two elements are strings, and are required. Subsequent elements are lists, and are optional. The optional elements, if included, should contain three required elements:

 service_info = ['ServiceName','ServiceURL',status]

Question: How do I validate node_info against this format in the class above? Do I have to parse the list or is there some better way, like defining a schema/format of some sorts?

Laszlo
  • 769
  • 9
  • 19
  • So, what have you tried? – pbuck Feb 03 '17 at 15:37
  • I tried to save some time, and avoid validating it manually. – Laszlo Feb 03 '17 at 15:39
  • 1
    Two things about the existing code: 1) in `__init__`, should it be `self._node_info = ...`? 2) you shouldn't use the mutable default argument `node_info = []`, this will use the same list in all instances where the default argument is used. – Jared Goguen Feb 03 '17 at 15:49
  • 1
    This is basically a tool / software library request, which are off-topic on SO. There are several good schema validation libraries. [`voluptuous`](https://pypi.python.org/pypi/voluptuous) is a popular one. – wim Feb 03 '17 at 16:05
  • Great! Thanks @wim. :) – Laszlo Feb 03 '17 at 16:09
  • 1) Thanks @Jared, nice catch. 2) Ah, OK. thanks. I updated the code for both. – Laszlo Feb 03 '17 at 16:41

1 Answers1

1

This is a possible solution, using a custom validator:

import sys
from private import private

class message:
    #status_t = ['offline', 'online']

    def __init__(self, node_info = None):
      if node_info is None:
         self.node_info = []
      else:
         self.__validate_node_info(node_info)
         self.node_info = node_info

    @property
    def node_info(self):
        return self.node_info

    @node_info.setter
    def node_info(self, value):
      self.__validate_node_info(value)
      self.node_info = value

    def toString(self):
      s = ''
      return s


    @private
    def __validate_node_info(self, lst, level=0):

      '''
      Validates the node_info list, against this schema:

      node_info = [
         required(str),
         required(str),
         required(int),
         optional(service_info),
         optional(service_info),...]

      service_info = [required(str),required(str),required(int)]

      Sample input:

      sample_node_info = [
         'Node Name',
         'Node URL',
         status,
         ['Service1','ServiceURL1',status],
         ['Service2','ServiceURL2',status]
       ]

      '''

      i = 0
      lstlen = len(lst)

      if lstlen < 2:
        raise TypeError("The list %s is too short" % (lst))
      if level > 0:
        if len(lst) != 3:
           raise TypeError("The list %s should contain exactly %d elements" % (lst,3))
      for e in lst:
        argval = lst[i]
        if i < 2:
           if not type(argval) is str:
              raise TypeError("type is %s, must be %s" % (type(argval), str))
        elif i == 2:
           if not type(argval) is int:
              raise TypeError("type is %s, must be %s" % (type(argval), int))
        else:
           self.__validate_node_info(lst[i],level+1)
        i=i+1


#message.node_info = ['node1', 'nodeurl1', 1, ['service1', 'serviceurl1', 0], ['service2', 'serviceurl2', 1] ]
#print(message.node_info)

private.py is listed here

Community
  • 1
  • 1
Laszlo
  • 769
  • 9
  • 19