Source code for tt.definitions.operands

"""Definitions related to operands."""

import re

from collections import namedtuple
from keyword import kwlist

from tt.errors import (
    InvalidArgumentTypeError,
    InvalidArgumentValueError)


BOOLEAN_VALUES = {0, 1, True, False}
"""Set of truthy values valid to submit for evaluation.

:type: Set[:class:`int <python:int>`, :class:`bool <python:bool>`]

"""


DONT_CARE_VALUE = 'x'
"""The don't care string identifier.

:type: :class:`str <python:str>`

"""


# False and True are not considered keywords in Python 2
_tt_keywords = set(kwlist) | {'False', 'True'}


[docs]def is_valid_identifier(identifier_name): """Returns whether the string is a valid symbol identifier. Valid identifiers are those that follow Python variable naming conventions, are not Python keywords, and do not begin with an underscore. :param identifier_name: The string to test. :type identifier_name: :class:`str <python:str>` :returns: True if the passed string is valid identifier, otherwise False. :rtype: :class:`bool <python:bool>` :raises InvalidArgumentTypeError: If ``identifier_name`` is not a string. :raises InvalidArgumentValueError: If ``identifier_name`` is an empty string. As an example:: >>> from tt import is_valid_identifier >>> is_valid_identifier('$var') False >>> is_valid_identifier('va#r') False >>> is_valid_identifier('for') False >>> is_valid_identifier('False') False >>> is_valid_identifier('var') True >>> is_valid_identifier('') Traceback (most recent call last): ... tt.errors.arguments.InvalidArgumentValueError: identifier_name cannot \ be empty >>> is_valid_identifier(None) Traceback (most recent call last): ... tt.errors.arguments.InvalidArgumentTypeError: identifier_name must be \ a string """ if not isinstance(identifier_name, str): raise InvalidArgumentTypeError('identifier_name must be a string') if not identifier_name: raise InvalidArgumentValueError('identifier_name cannot be empty') if identifier_name.startswith('_'): return False if identifier_name in _tt_keywords: return False identifier_re = re.compile(r'^[^\d\W]\w*\Z', re.UNICODE) if re.match(identifier_re, identifier_name) is None: return False return True
[docs]def boolean_variables_factory(symbols): """Returns a class for namedtuple-like objects for holding boolean values. :param symbols: A list of the symbol names for which instances of this class will hold an entry. :type symbols: List[:class:`str <python:str>`] :returns: An object where the passed ``symbols`` can be accessed as attributes. :rtype: :func:`namedtuple <python:collections.namedtuple>`-like object This functionality is best demonstrated with an example:: >>> from tt import boolean_variables_factory >>> factory = boolean_variables_factory(['op1', 'op2', 'op3']) >>> instance = factory(op1=True, op2=False, op3=False) >>> instance.op1 True >>> instance.op2 False >>> print(instance) op1=1, op2=0, op3=0 >>> instance = factory(op1=0, op2=0, op3=1) >>> instance.op3 1 >>> print(instance) op1=0, op2=0, op3=1 It should be noted that this function is used internally within functionality where the validity of inputs is already checked. As such, this class won't enforce the Boolean-ness of input values:: >>> factory = boolean_variables_factory(['A', 'B']) >>> instance = factory(A=-1, B='value') >>> print(instance) A=-1, B=value Instances produced from the generated factory are descendants of :func:`namedtuple <python:collections.namedtuple>` generated classes; some of the inherited attributes may be useful:: >>> instance = factory(A=True, B=False) >>> instance._fields ('A', 'B') >>> dict(instance._asdict()) {'A': True, 'B': False} """ class _bvf(namedtuple('_bvf', symbols)): __slots__ = () def __str__(self): pairs = [] for field, val in self._asdict().items(): val = int(val) if isinstance(val, bool) else val pairs.append(field + '=' + str(val)) return ', '.join(pairs) def __repr__(self): return '<BooleanValues [{}]>'.format(str(self)) return _bvf