"Where is the Duck?"¶
This notebook illustrates how context-aware components can be developed in PyGX.
In this example, Duck is a symbolic class which subscribes the on_topo_parent_change and on_topo_path_change events. Therefore, when the containing context of a Duck object is changed, it can respond to such changes.
In [ ]:
Copied!
!pip install pygx
!pip install pygx
In [2]:
Copied!
from typing import Any, Literal
import pygx as pg
from typing import Any, Literal
import pygx as pg
In [3]:
Copied!
class Venue(pg.Object, topo=True):
occupied_by: Any = None
class Pool(Venue):
size: Literal['small', 'large'] = 'small'
color: Literal['green', 'blue', 'black'] = 'green'
def __str__(self):
return f'a {self.size} {self.color} pool'
class Cage(Venue):
def __str__(self):
return f'a small cold cage'
def free(self):
self.sym_rebind(occupied_by=None)
class Duck(pg.Object, topo=True):
def on_topo_parent_change(self, old_parent, new_parent):
super().on_topo_parent_change(old_parent, new_parent)
def venue(parent):
if isinstance(parent, Venue):
return str(parent)
return 'nowhere'
print(f'I am moving from {venue(old_parent)} '
f'to {venue(new_parent)}')
def on_topo_path_change(self, old_path, new_path):
super().on_topo_path_change(old_path, new_path)
print(f'I am now identified by path "{new_path}"')
def who_am_i(self):
if isinstance(self.topo_parent, Pool):
message = f'I am a happy duck swimming in {str(self.topo_parent)}.'
elif isinstance(self.topo_parent, Cage):
message = f'I am a sad duck wandering in {str(self.topo_parent)}.'
else:
message = f'I am just a duck.'
print(message)
class Venue(pg.Object, topo=True):
occupied_by: Any = None
class Pool(Venue):
size: Literal['small', 'large'] = 'small'
color: Literal['green', 'blue', 'black'] = 'green'
def __str__(self):
return f'a {self.size} {self.color} pool'
class Cage(Venue):
def __str__(self):
return f'a small cold cage'
def free(self):
self.sym_rebind(occupied_by=None)
class Duck(pg.Object, topo=True):
def on_topo_parent_change(self, old_parent, new_parent):
super().on_topo_parent_change(old_parent, new_parent)
def venue(parent):
if isinstance(parent, Venue):
return str(parent)
return 'nowhere'
print(f'I am moving from {venue(old_parent)} '
f'to {venue(new_parent)}')
def on_topo_path_change(self, old_path, new_path):
super().on_topo_path_change(old_path, new_path)
print(f'I am now identified by path "{new_path}"')
def who_am_i(self):
if isinstance(self.topo_parent, Pool):
message = f'I am a happy duck swimming in {str(self.topo_parent)}.'
elif isinstance(self.topo_parent, Cage):
message = f'I am a sad duck wandering in {str(self.topo_parent)}.'
else:
message = f'I am just a duck.'
print(message)
In [4]:
Copied!
duck = Duck()
duck.who_am_i()
duck = Duck()
duck.who_am_i()
I am just a duck.
In [5]:
Copied!
cage = Cage(occupied_by=duck)
duck.who_am_i()
cage = Cage(occupied_by=duck)
duck.who_am_i()
I am now identified by path "occupied_by" I am moving from nowhere to a small cold cage I am a sad duck wandering in a small cold cage.
In [6]:
Copied!
cage.free()
cage.free()
I am moving from a small cold cage to nowhere I am now identified by path ""
In [7]:
Copied!
pool = Pool(occupied_by=duck)
duck.who_am_i()
pool = Pool(occupied_by=duck)
duck.who_am_i()
I am now identified by path "occupied_by" I am moving from nowhere to a small green pool I am a happy duck swimming in a small green pool.