| # |
| # This file is part of pyasn1 software. |
| # |
| # Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> |
| # License: http://snmplabs.com/pyasn1/license.html |
| # |
| # ASN.1 named integers |
| # |
| from pyasn1 import error |
| |
| __all__ = ['NamedValues'] |
| |
| |
| class NamedValues(object): |
| """Create named values object. |
| |
| The |NamedValues| object represents a collection of string names |
| associated with numeric IDs. These objects are used for giving |
| names to otherwise numerical values. |
| |
| |NamedValues| objects are immutable and duck-type Python |
| :class:`dict` object mapping ID to name and vice-versa. |
| |
| Parameters |
| ---------- |
| *args: variable number of two-element :py:class:`tuple` |
| |
| name: :py:class:`str` |
| Value label |
| |
| value: :py:class:`int` |
| Numeric value |
| |
| Keyword Args |
| ------------ |
| name: :py:class:`str` |
| Value label |
| |
| value: :py:class:`int` |
| Numeric value |
| |
| Examples |
| -------- |
| |
| .. code-block:: pycon |
| |
| >>> nv = NamedValues('a', 'b', ('c', 0), d=1) |
| >>> nv |
| >>> {'c': 0, 'd': 1, 'a': 2, 'b': 3} |
| >>> nv[0] |
| 'c' |
| >>> nv['a'] |
| 2 |
| """ |
| def __init__(self, *args, **kwargs): |
| self.__names = {} |
| self.__numbers = {} |
| |
| anonymousNames = [] |
| |
| for namedValue in args: |
| if isinstance(namedValue, (tuple, list)): |
| try: |
| name, number = namedValue |
| |
| except ValueError: |
| raise error.PyAsn1Error('Not a proper attribute-value pair %r' % (namedValue,)) |
| |
| else: |
| anonymousNames.append(namedValue) |
| continue |
| |
| if name in self.__names: |
| raise error.PyAsn1Error('Duplicate name %s' % (name,)) |
| |
| if number in self.__numbers: |
| raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) |
| |
| self.__names[name] = number |
| self.__numbers[number] = name |
| |
| for name, number in kwargs.items(): |
| if name in self.__names: |
| raise error.PyAsn1Error('Duplicate name %s' % (name,)) |
| |
| if number in self.__numbers: |
| raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) |
| |
| self.__names[name] = number |
| self.__numbers[number] = name |
| |
| if anonymousNames: |
| |
| number = self.__numbers and max(self.__numbers) + 1 or 0 |
| |
| for name in anonymousNames: |
| |
| if name in self.__names: |
| raise error.PyAsn1Error('Duplicate name %s' % (name,)) |
| |
| self.__names[name] = number |
| self.__numbers[number] = name |
| |
| number += 1 |
| |
| def __repr__(self): |
| representation = ', '.join(['%s=%d' % x for x in self.items()]) |
| |
| if len(representation) > 64: |
| representation = representation[:32] + '...' + representation[-32:] |
| |
| return '<%s object, enums %s>' % ( |
| self.__class__.__name__, representation) |
| |
| def __eq__(self, other): |
| return dict(self) == other |
| |
| def __ne__(self, other): |
| return dict(self) != other |
| |
| def __lt__(self, other): |
| return dict(self) < other |
| |
| def __le__(self, other): |
| return dict(self) <= other |
| |
| def __gt__(self, other): |
| return dict(self) > other |
| |
| def __ge__(self, other): |
| return dict(self) >= other |
| |
| def __hash__(self): |
| return hash(self.items()) |
| |
| # Python dict protocol (read-only) |
| |
| def __getitem__(self, key): |
| try: |
| return self.__numbers[key] |
| |
| except KeyError: |
| return self.__names[key] |
| |
| def __len__(self): |
| return len(self.__names) |
| |
| def __contains__(self, key): |
| return key in self.__names or key in self.__numbers |
| |
| def __iter__(self): |
| return iter(self.__names) |
| |
| def values(self): |
| return iter(self.__numbers) |
| |
| def keys(self): |
| return iter(self.__names) |
| |
| def items(self): |
| for name in self.__names: |
| yield name, self.__names[name] |
| |
| # support merging |
| |
| def __add__(self, namedValues): |
| return self.__class__(*tuple(self.items()) + tuple(namedValues.items())) |
| |
| # XXX clone/subtype? |
| |
| def clone(self, *args, **kwargs): |
| new = self.__class__(*args, **kwargs) |
| return self + new |
| |
| # legacy protocol |
| |
| def getName(self, value): |
| if value in self.__numbers: |
| return self.__numbers[value] |
| |
| def getValue(self, name): |
| if name in self.__names: |
| return self.__names[name] |
| |
| def getValues(self, *names): |
| try: |
| return [self.__names[name] for name in names] |
| |
| except KeyError: |
| raise error.PyAsn1Error( |
| 'Unknown bit identifier(s): %s' % (set(names).difference(self.__names),) |
| ) |