Imposing typesystem on a class#


It is often necessary to allow only certain values to be assigned to an attribute of a class. That can be achieved using properties. For instance, if we want to implement class Square and allow only positive values for the square edge length a, the implementation would be:

class Square:
    def __init__(self, a):
        self.a = a

    def a(self):
        return self._a

    def a(self, value):
        if value <= 0:
            raise ValueError("Edge length must be positive (a>0).")
            self._a = value

Now, if we attempt to use an invalid value to set the edge length a, an exception will be raised.

s = Square(a=5)  # Instantiate the class with correct attribute value

    s.a = -3
except ValueError:
    print("Exception raised.")
Exception raised.

Imposing typesystem using ubermagutil.typesystem#

In large projects with a large number of classes, a lot of input checks have to be performed. This makes the code grow and it causes a lot of code repetition. An example of the ubermagutil usage for the previously shown Square class is

import ubermagutil.typesystem as ts

class Square:
    def __init__(self, a):
        self.a = a

s = Square(a=5)

If we try to set an invalid value:

    s.a = -3
except ValueError:
    print("Exception raised.")
Exception raised.

Similarly, if we want to define MyClass with the following attributes:

  • a - an unsigned integer

  • b - a three-dimensional vector

  • c - one of the allowed values from the set {'left', 'right'}

  • d - variable of type list

  • name - a valid Python variable name

    a=ts.Scalar(expected_type=int, unsigned=True),
    c=ts.Subset(sample_set={"left", "right"}, unpack=False),
class MyClass:
    def __init__(self, a, b, c, d, name):
        self.a = a
        self.b = b
        self.c = c
        self.d = d = name

Now, we can attempt passing invalid values expect them to be rejected by the imposed typesystem.

mc = MyClass(
    a=5, b=(1, 2, 3), c="right", d=[1, 2, "abc"], name="myclass"
)  # valid initialisation

# Set mc.a with float
    mc.a = 3.14
except TypeError:
    print("mc.a: Exception raised.")

# Set mc.b with a two-dimensional vector
    mc.b = (10, 11)
except ValueError:
    print("mc.b: Exception raised.")

# Set mc.c with an invalid value of the string
    mc.c = "down"
except ValueError:
    print("mc.c: Exception raised.")

# Set mc.c with an invalid value of tuple
    mc.d = (1, 2, 3, 4)
except TypeError:
    print("mc.d: Exception raised.")

# Set with an invalid Python variable name
try: = "Nikola Tesla"  # contains spaces
except ValueError:
    print(" Exception raised.")
mc.a: Exception raised.
mc.b: Exception raised.
mc.c: Exception raised.
mc.d: Exception raised. Exception raised.

Deleting an attribute#

Deleting an attribute is never allowed and an AttributeError is raised.

# Attempt to delete an attribute.
    del mc.a
except AttributeError:
    print("Exception raised.")
Exception raised.