123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- #
- # This file is part of pyasn1 software.
- #
- # Copyright (c) 2005-2018, 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 0x%x enums %s>' % (self.__class__.__name__, id(self), 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),)
- )
|