Skip to content

Instantly share code, notes, and snippets.

@erkandiken
Last active June 11, 2020 08:29
Show Gist options
  • Save erkandiken/8bebf633b776b4767e38ae6cf568d117 to your computer and use it in GitHub Desktop.
Save erkandiken/8bebf633b776b4767e38ae6cf568d117 to your computer and use it in GitHub Desktop.
Decorator examples for checking register read, write, range check operations
class BaseValidationError(Exception):
pass
class ValueExceedsMaximumError(BaseValidationError):
pass
class ValueUnderMinimumError(BaseValidationError):
pass
class NegativeValueError(BaseValidationError):
pass
class InvalidReadError(BaseValidationError):
pass
class InvalidWriteError(BaseValidationError):
pass
from decorators import check_read_access, check_write_access, check_range
class ExampleClass(object):
def __init__(self, device_comm):
self.device_comm = device_comm
@check_read_access
def read(self, reg):
return self.device_comm.read_register(reg.address)
@check_write_access
def write(self, reg, value):
self.device_comm.write_register(reg.address, value)
@check_range(1, 255)
def set_time_register(self, reg, value):
self.write(reg, value)
import logging
import functools
from custom_exceptions import BaseValidationError, ValueExceedsMaximumError, \
NegativeValueError, InvalidWriteError, InvalidReadError, ValueUnderMinimumError
logger = logging.getLogger(__name__)
def check_read_access(func):
"""
Decorator to check read access of a register before attempting to read
:param func: method passed to decorator
:return: wrapper function
"""
@functools.wraps(func)
def wrapper_check_read_access(*args, **kwargs):
"""
Wrapper func checks for the read access
:param args: positional arguments (args[0]: self, args[1]: reg)
:param kwargs: keyword arguments
:return: None or wrapped func method
"""
try:
reg = args[1]
if reg.read is False:
raise InvalidReadError(reg.reg_name)
except BaseValidationError as err:
logger.error(repr(err))
return None
else:
return func(*args, **kwargs)
return wrapper_check_read_access
def check_write_access(func):
"""
Decorator to check write access of a register before attempting to write
:param func: method passed to decorator
:return: wrapper function
"""
@functools.wraps(func)
def wrapper_check_write_access(*args, **kwargs):
"""
Wrapper func checks for the write access
:param args:positional arguments (args[0]: self, args[1]: reg)
:param kwargs: keyword arguments
:return: None or wrapped func method
"""
try:
reg = args[1]
if reg.write is False:
raise InvalidWriteError(reg.reg_name)
except BaseValidationError as err:
logger.error(repr(err))
return None
else:
return func(*args, **kwargs)
return wrapper_check_write_access
def check_range(min_value, max_value):
"""
Decorator for checking input value against min and max values
:param min_value: min value required
:param max_value: max value required
:return: wrapper function
"""
def decorator_check_range(func):
@functools.wraps(func)
def wrapper_check_range(*args, **kwargs):
"""
:param args: positional arguments
:param kwargs: keyword arguments
:return: None or wrapped func
"""
try:
value = args[1]
if value > max_value:
raise ValueExceedsMaximumError(value)
elif value < min_value:
raise ValueUnderMinimumError(value)
elif value < 0.0:
raise NegativeValueError(value)
except BaseValidationError as err:
logger.error(repr(err))
return None
else:
return func(*args, **kwargs)
return wrapper_check_range
return decorator_check_range
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment