seminars.fb

Programming Fundamentals → “Object-Orientation in Python and the Python Object Model”

Seminar (Fri, Nov 6, 2020; 9 AM PST)

Theme: Programming (& Python!) Fundamentals

Topic: Object-Orientation in Python and the Python Object Model

Keywords: Python, object orientation, data model, object model

Presenter James Powell james@dutc.io
Date Friday, November 6, 2020
Time 9:00 AM PST
print("Let's get started!")

Pretend I have some library for controlling some hardware.

from lib import Scope
scope = Scope()
from lib import Scope
scope = Scope()

scope.connect('a::b::c')
scope.set_config(max_value=10)
scope.set_config(min_value=0, max_value=10)
scope.get_reading()
scope.restart()
scope.disconnect()
# TASK i: connect to a device
# TASK ii: set configuration on a device

with Scope.from_address('aa::bb::c') as dev:
    pass
# with ctx():
#     pass

# mgr = ctx()
# obj = mgr.__enter__()
# try:
#    ...
# except Exception as e:
#    mgr.__exit__(e, ...)
# else:
#    mgr.__exit__(None, ...)
class Context:
    def __enter__(self):
        print('before the block')
    def __exit__(self, *_):
        print('after the block')

with Context():
    print('inside the block')
    print('inside the block')
    print('inside the block')
from contextlib import contextmanager
class Scope:
    def __init__(self, resource):
        self.resource = resource
    def __enter__(self):
        print('Connecting to resource…')
        self.connect(self.resource) 
        return self
    def __exit__(self, *_):
        print('Disonnect to resource…')
        self.disconnect(self.resource) 
    @contextmanager
    def config(self, config=None):
        print(f'setting config to {config}')
        try:
            yield self
        finally:
            print(f'restoring old config')
    connect = lambda *_: None
    disconnect = lambda *_: None

CONFIG = 'some config'
ALTERNATE_CONFIG = 'some other config'

with Scope('aa::b::cc') as scope:
    with scope.config(CONFIG):
        ...
    with scope.config(ALTERNATE_CONFIG):
        ...
from collections import namedtuple
class ChOption(namedtuple('ChOption', 'channel position bandwidth coupling')):
    def __new__(cls, channel, position, bandwidth=20, coupling='ac'):
        return super().__new__(cls, channel, position, bandwidth, coupling)
    @property
    def commands(self):
        yield f'CH{self.channel}:POSITION:{self.position}'
        yield f'CH{self.channel}:BANDWIDTH:{self.bandwidth}'
        yield f'CH{self.channel}:COUPLING:{self.coupling}'

    def __str__(self):
        return '\n'.join(self.commands)

CONFIG = {
    ChOption(2, position=4),
    ChOption(3, position=5),
    ChOption(4, position=2, coupling='dc'),
}

for co in CONFIG:
    for cmd in co.commands:
        print(f'{cmd}')
# TASK iii: retrieve values from a device

from collections import namedtuple
from time import sleep
from numpy.random import bytes
from random import random
from contextlib import contextmanager
from queue import Queue

Result = namedtuple('Result', 'data time')

class Scope:
    def __init__(self, resource):
        self.resource = resource
        self.queue = Queue()
    def __enter__(self):
        print('Connecting to resource…')
        self.connect(self.resource) 
        return self
    def __exit__(self, *_):
        print('Disonnect to resource…')
        self.disconnect(self.resource) 
    @contextmanager
    def config(self, config=None):
        print(f'setting config to {config}')
        try:
            yield self
        finally:
            print(f'restoring old config')
    connect = lambda *_: None
    disconnect = lambda *_: None

    def read(self, size=10, wait=1):
        sleep(wait)
        return Result(bytes(size), random())

    def submit(self, action):
        self.queue.put(action)

    async def run(self):
        while not self.queue.empty():
            action = self.queue.get()
            try:
                ...
                await asyncio.sleep(1)
            except Exception:
                await asyncio.sleep(10)

Read = namedtuple('Read', '')

with Scope('aa:bb::c') as sc:
    sc.submit(Read())
    sc.submit(Read())
    sc.submit(Read())
    sc.run()
# TASK iv: retrieve values under different scenarios