Module albow.References

Class Ref is the basis of a system for dynamically linking albow.widgets.Control classes with values to be displayed and edited. An instance of Ref is used as a starting point for constructing reference objects. There are a number of different kinds of reference objects, depending on whether the underlying value is accessed through an

  • attribute,
  • item index or
  • method call

All of these reference objects present a common interface, consisting of get() and set() methods, that the albow.widgets.Control uses to access the value whenever it needs to display or update it.

The simplest way of using Ref is illustrated by the following example.

Example 1


testVehicle = TestVehicle()

velocityRef = AttrRef(base=testVehicle, name="velocity")
self.logger.info("Created a velocity reference: %s", velocityRef)

velocityControl = DummyControl(ref=velocityRef)
self.logger.info("Created velocity control %s", velocityControl)
#
# Change the data model
#
testVehicle.velocity = 100

self.assertTrue(velocityControl.get_value() == testVehicle.velocity, "Reference did not update control")
#
# Change the control
#
velocityControl.set_value(500)
self.assertTrue(velocityControl.get_value() == testVehicle.velocity, "Control did not update reference")

Here, the expression AttrRef(base=testVehicle, _name="velocity") creates a reference source object from which reference objects can be derived.

Accessing the velocity attribute of this object creates an attribute reference object that refers to the velocity attribute of the vehicle. This attribute reference object is then attached to a DummyControl. The result is that the DummyControl will always display the current value of the vehicle's velocity attribute.

Additionally, if the user enters a new value into the field, the vehicle's velocity attribute is updated.

As well as attribute access, indexing and calling can also be performed on a reference source:

Example 2


itemRef[TEST_ITEM_INDEX] produces an item reference object that accesses an item of a sequence or mapping.

    vehicleList = self.getVehicleList()

    itemRef = ItemRef(base=vehicleList, index=TEST_ITEM_INDEX)
    self.logger.info("Created: %s", itemRef)

    testItem = itemRef[TEST_ITEM_INDEX]
    self.logger.info("Retrieved: %s", testItem)
    self.assertEqual(first=vehicleList[TEST_ITEM_INDEX],
                     second=testItem,
                     msg="Did not retrieve the correct item.")

Example 3


ref_source(args) produces a call reference object that performs a call when its get() method is called. This kind of reference object is read-only. However, it can be used as a source of further reference objects that are read-write.

    # More code to follow
Source code
"""
Class `Ref` is the basis of a system for dynamically linking `albow.widgets.Control` classes with values to be
displayed and
edited. An instance of Ref is used as a starting point for constructing reference objects. There are a number of
different kinds of reference objects, depending on whether the underlying value is accessed through an

- attribute,
- item index or
- method call

All of these reference objects present a common interface, consisting of `get()` and
`set()` methods, that the `albow.widgets.Control` uses to access the value whenever it needs to display or update it.

The simplest way of using Ref is illustrated by the following example.

**Example 1**

------

```python
testVehicle = TestVehicle()

velocityRef = AttrRef(base=testVehicle, name="velocity")
self.logger.info("Created a velocity reference: %s", velocityRef)

velocityControl = DummyControl(ref=velocityRef)
self.logger.info("Created velocity control %s", velocityControl)
#
# Change the data model
#
testVehicle.velocity = 100

self.assertTrue(velocityControl.get_value() == testVehicle.velocity, "Reference did not update control")
#
# Change the control
#
velocityControl.set_value(500)
self.assertTrue(velocityControl.get_value() == testVehicle.velocity, "Control did not update reference")

```


Here, the expression _AttrRef(base=testVehicle, _name="velocity")_ creates a reference source object from which
reference objects can be derived.

Accessing the velocity attribute of this object creates an attribute reference object that refers to
the velocity attribute of the vehicle. This attribute reference object is then attached to a
`DummyControl`. The result is that the `DummyControl` will always display the current value of the
vehicle's velocity attribute.

Additionally, if the user enters a new value into the field, the vehicle's velocity attribute is updated.

As well as attribute access, indexing and calling can also be performed on a reference source:

**Example 2**

------


_itemRef[TEST_ITEM_INDEX]_ produces an item reference object that accesses an item of a sequence or mapping.

```python
    vehicleList = self.getVehicleList()

    itemRef = ItemRef(base=vehicleList, index=TEST_ITEM_INDEX)
    self.logger.info("Created: %s", itemRef)

    testItem = itemRef[TEST_ITEM_INDEX]
    self.logger.info("Retrieved: %s", testItem)
    self.assertEqual(first=vehicleList[TEST_ITEM_INDEX],
                     second=testItem,
                     msg="Did not retrieve the correct item.")

```

**Example 3**

------

_ref_source(args)_ produces a call reference object that performs a call when its get() method is called. This kind
of reference object is read-only.  However, it can be used as a source of further reference objects that are
_read-write_.


```python
    # More code to follow
```

"""

from albow.ItemRefInsertionException import ItemRefInsertionException


class Ref:

    def __init__(self, base):
        """
         Creates a reference source object based on the given object. Reference objects can be derived from
         this reference source using the operations listed below.

        Args:
            base:  Derive from?
        """
        self.base = base

    def __getattr__(self, name):
        return AttrRef(self, name)

    def __getitem__(self, index):
        return self.base[index]

    def __call__(self, *args, **kwds):
        return CallRef(self, args, kwds)

    def __pos__(self):
        return RefCaller(self)

    def __repr__(self):
        return f"Ref({self.base})"

    def get(self):
        return self.base


class AttrRef(Ref):

    def __init__(self, base, name):

        super().__init__(base)
        self.name = name

    def __repr__(self):
        return f"AttrRef({self.base}, {self.name})"

    def get(self):
        val = getattr(self.base, self.name)
        return val

    def set(self, value):
        setattr(self.base, self.name, value)


class ItemRef(Ref):

    def __init__(self, base, index):

        super().__init__(base)
        self.index = index

    def __repr__(self):
        return f"ItemRef({self.index}, {self.base})"

    def get(self):
        return self.base[self.index]

    def set(self, value):
        if isinstance(value, self.__class__):
            self.base[self.index] = value
        else:
            ex: ItemRefInsertionException = ItemRefInsertionException(
                theIndex=self.index,
                theMessage="Type of insertion object does not match")
            raise ex


class CallRef(Ref):
    """
    TODO:  This is broken figure out how to fix it
    """
    def __init__(self, base, args, kwds):

        super().__init__(base)
        self.args = args
        self.kwds = kwds

    def __repr__(self):
        return f"CallRef({self.base})"

    def get(self):
        return self.base.get()(*self.args, **self.kwds)


class RefCaller:

    def __init__(self, base):
        self.base = base

    def __call__(self, *args, **kwds):
        return self.base.get()(*args, **kwds)

    def __repr__(self):
        return f"+{self.base}"

Classes

class AttrRef (base, name)

Creates a reference source object based on the given object. Reference objects can be derived from this reference source using the operations listed below.

Args

base
Derive from?
Source code
class AttrRef(Ref):

    def __init__(self, base, name):

        super().__init__(base)
        self.name = name

    def __repr__(self):
        return f"AttrRef({self.base}, {self.name})"

    def get(self):
        val = getattr(self.base, self.name)
        return val

    def set(self, value):
        setattr(self.base, self.name, value)

Ancestors

Methods

def get(self)
Source code
def get(self):
    val = getattr(self.base, self.name)
    return val
def set(self, value)
Source code
def set(self, value):
    setattr(self.base, self.name, value)
class CallRef (base, args, kwds)

TODO: This is broken figure out how to fix it

Creates a reference source object based on the given object. Reference objects can be derived from this reference source using the operations listed below.

Args

base
Derive from?
Source code
class CallRef(Ref):
    """
    TODO:  This is broken figure out how to fix it
    """
    def __init__(self, base, args, kwds):

        super().__init__(base)
        self.args = args
        self.kwds = kwds

    def __repr__(self):
        return f"CallRef({self.base})"

    def get(self):
        return self.base.get()(*self.args, **self.kwds)

Ancestors

Methods

def get(self)
Source code
def get(self):
    return self.base.get()(*self.args, **self.kwds)
class ItemRef (base, index)

Creates a reference source object based on the given object. Reference objects can be derived from this reference source using the operations listed below.

Args

base
Derive from?
Source code
class ItemRef(Ref):

    def __init__(self, base, index):

        super().__init__(base)
        self.index = index

    def __repr__(self):
        return f"ItemRef({self.index}, {self.base})"

    def get(self):
        return self.base[self.index]

    def set(self, value):
        if isinstance(value, self.__class__):
            self.base[self.index] = value
        else:
            ex: ItemRefInsertionException = ItemRefInsertionException(
                theIndex=self.index,
                theMessage="Type of insertion object does not match")
            raise ex

Ancestors

Methods

def get(self)
Source code
def get(self):
    return self.base[self.index]
def set(self, value)
Source code
def set(self, value):
    if isinstance(value, self.__class__):
        self.base[self.index] = value
    else:
        ex: ItemRefInsertionException = ItemRefInsertionException(
            theIndex=self.index,
            theMessage="Type of insertion object does not match")
        raise ex
class Ref (base)

Creates a reference source object based on the given object. Reference objects can be derived from this reference source using the operations listed below.

Args

base
Derive from?
Source code
class Ref:

    def __init__(self, base):
        """
         Creates a reference source object based on the given object. Reference objects can be derived from
         this reference source using the operations listed below.

        Args:
            base:  Derive from?
        """
        self.base = base

    def __getattr__(self, name):
        return AttrRef(self, name)

    def __getitem__(self, index):
        return self.base[index]

    def __call__(self, *args, **kwds):
        return CallRef(self, args, kwds)

    def __pos__(self):
        return RefCaller(self)

    def __repr__(self):
        return f"Ref({self.base})"

    def get(self):
        return self.base

Subclasses

Methods

def get(self)
Source code
def get(self):
    return self.base
class RefCaller (base)
Source code
class RefCaller:

    def __init__(self, base):
        self.base = base

    def __call__(self, *args, **kwds):
        return self.base.get()(*args, **kwds)

    def __repr__(self):
        return f"+{self.base}"