about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pyasn1/type
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pyasn1/type
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/pyasn1/type')
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/__init__.py1
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/base.py699
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/char.py288
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/constraint.py751
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/error.py11
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/namedtype.py550
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/namedval.py192
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/opentype.py104
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/tag.py335
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/tagmap.py96
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/univ.py3327
-rw-r--r--.venv/lib/python3.12/site-packages/pyasn1/type/useful.py189
12 files changed, 6543 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/__init__.py b/.venv/lib/python3.12/site-packages/pyasn1/type/__init__.py
new file mode 100644
index 00000000..8c3066b2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/__init__.py
@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/base.py b/.venv/lib/python3.12/site-packages/pyasn1/type/base.py
new file mode 100644
index 00000000..aa86e520
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/base.py
@@ -0,0 +1,699 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+import sys
+
+from pyasn1 import error
+from pyasn1.type import constraint
+from pyasn1.type import tag
+from pyasn1.type import tagmap
+
+__all__ = ['Asn1Item', 'Asn1Type', 'SimpleAsn1Type',
+           'ConstructedAsn1Type']
+
+
+class Asn1Item(object):
+    @classmethod
+    def getTypeId(cls, increment=1):
+        try:
+            Asn1Item._typeCounter += increment
+        except AttributeError:
+            Asn1Item._typeCounter = increment
+        return Asn1Item._typeCounter
+
+
+class Asn1Type(Asn1Item):
+    """Base class for all classes representing ASN.1 types.
+
+    In the user code, |ASN.1| class is normally used only for telling
+    ASN.1 objects from others.
+
+    Note
+    ----
+    For as long as ASN.1 is concerned, a way to compare ASN.1 types
+    is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods.
+    """
+    #: Set or return a :py:class:`~pyasn1.type.tag.TagSet` object representing
+    #: ASN.1 tag(s) associated with |ASN.1| type.
+    tagSet = tag.TagSet()
+
+    #: Default :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+    #: object imposing constraints on initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Disambiguation ASN.1 types identification
+    typeId = None
+
+    def __init__(self, **kwargs):
+        readOnly = {
+            'tagSet': self.tagSet,
+            'subtypeSpec': self.subtypeSpec
+        }
+
+        readOnly.update(kwargs)
+
+        self.__dict__.update(readOnly)
+
+        self._readOnly = readOnly
+
+    def __setattr__(self, name, value):
+        if name[0] != '_' and name in self._readOnly:
+            raise error.PyAsn1Error('read-only instance attribute "%s"' % name)
+
+        self.__dict__[name] = value
+
+    def __str__(self):
+        return self.prettyPrint()
+
+    @property
+    def readOnly(self):
+        return self._readOnly
+
+    @property
+    def effectiveTagSet(self):
+        """For |ASN.1| type is equivalent to *tagSet*
+        """
+        return self.tagSet  # used by untagged types
+
+    @property
+    def tagMap(self):
+        """Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects within callee object.
+        """
+        return tagmap.TagMap({self.tagSet: self})
+
+    def isSameTypeWith(self, other, matchTags=True, matchConstraints=True):
+        """Examine |ASN.1| type for equality with other ASN.1 type.
+
+        ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
+        (:py:mod:`~pyasn1.type.constraint`) are examined when carrying
+        out ASN.1 types comparison.
+
+        Python class inheritance relationship is NOT considered.
+
+        Parameters
+        ----------
+        other: a pyasn1 type object
+            Class instance representing ASN.1 type.
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`True` if *other* is |ASN.1| type,
+            :obj:`False` otherwise.
+        """
+        return (self is other or
+                (not matchTags or self.tagSet == other.tagSet) and
+                (not matchConstraints or self.subtypeSpec == other.subtypeSpec))
+
+    def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
+        """Examine |ASN.1| type for subtype relationship with other ASN.1 type.
+
+        ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
+        (:py:mod:`~pyasn1.type.constraint`) are examined when carrying
+        out ASN.1 types comparison.
+
+        Python class inheritance relationship is NOT considered.
+
+        Parameters
+        ----------
+            other: a pyasn1 type object
+                Class instance representing ASN.1 type.
+
+        Returns
+        -------
+            : :class:`bool`
+                :obj:`True` if *other* is a subtype of |ASN.1| type,
+                :obj:`False` otherwise.
+        """
+        return (not matchTags or
+                (self.tagSet.isSuperTagSetOf(other.tagSet)) and
+                 (not matchConstraints or self.subtypeSpec.isSuperTypeOf(other.subtypeSpec)))
+
+    @staticmethod
+    def isNoValue(*values):
+        for value in values:
+            if value is not noValue:
+                return False
+        return True
+
+    def prettyPrint(self, scope=0):
+        raise NotImplementedError
+
+    # backward compatibility
+
+    def getTagSet(self):
+        return self.tagSet
+
+    def getEffectiveTagSet(self):
+        return self.effectiveTagSet
+
+    def getTagMap(self):
+        return self.tagMap
+
+    def getSubtypeSpec(self):
+        return self.subtypeSpec
+
+    # backward compatibility
+    def hasValue(self):
+        return self.isValue
+
+# Backward compatibility
+Asn1ItemBase = Asn1Type
+
+
+class NoValue(object):
+    """Create a singleton instance of NoValue class.
+
+    The *NoValue* sentinel object represents an instance of ASN.1 schema
+    object as opposed to ASN.1 value object.
+
+    Only ASN.1 schema-related operations can be performed on ASN.1
+    schema objects.
+
+    Warning
+    -------
+    Any operation attempted on the *noValue* object will raise the
+    *PyAsn1Error* exception.
+    """
+    skipMethods = {
+        '__slots__',
+        # attributes
+        '__getattribute__',
+        '__getattr__',
+        '__setattr__',
+        '__delattr__',
+        # class instance
+        '__class__',
+        '__init__',
+        '__del__',
+        '__new__',
+        '__repr__',
+        '__qualname__',
+        '__objclass__',
+        'im_class',
+        '__sizeof__',
+        # pickle protocol
+        '__reduce__',
+        '__reduce_ex__',
+        '__getnewargs__',
+        '__getinitargs__',
+        '__getstate__',
+        '__setstate__',
+    }
+
+    _instance = None
+
+    def __new__(cls):
+        if cls._instance is None:
+            def getPlug(name):
+                def plug(self, *args, **kw):
+                    raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name)
+                return plug
+
+            op_names = [name
+                        for typ in (str, int, list, dict)
+                        for name in dir(typ)
+                        if (name not in cls.skipMethods and
+                            name.startswith('__') and
+                            name.endswith('__') and
+                            callable(getattr(typ, name)))]
+
+            for name in set(op_names):
+                setattr(cls, name, getPlug(name))
+
+            cls._instance = object.__new__(cls)
+
+        return cls._instance
+
+    def __getattr__(self, attr):
+        if attr in self.skipMethods:
+            raise AttributeError('Attribute %s not present' % attr)
+
+        raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr)
+
+    def __repr__(self):
+        return '<%s object>' % self.__class__.__name__
+
+
+noValue = NoValue()
+
+
+class SimpleAsn1Type(Asn1Type):
+    """Base class for all simple classes representing ASN.1 types.
+
+    ASN.1 distinguishes types by their ability to hold other objects.
+    Scalar types are known as *simple* in ASN.1.
+
+    In the user code, |ASN.1| class is normally used only for telling
+    ASN.1 objects from others.
+
+    Note
+    ----
+    For as long as ASN.1 is concerned, a way to compare ASN.1 types
+    is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods.
+    """
+    #: Default payload value
+    defaultValue = noValue
+
+    def __init__(self, value=noValue, **kwargs):
+        Asn1Type.__init__(self, **kwargs)
+        if value is noValue:
+            value = self.defaultValue
+        else:
+            value = self.prettyIn(value)
+            try:
+                self.subtypeSpec(value)
+
+            except error.PyAsn1Error as exValue:
+                raise type(exValue)('%s at %s' % (exValue, self.__class__.__name__))
+
+        self._value = value
+
+    def __repr__(self):
+        representation = '%s %s object' % (
+            self.__class__.__name__, self.isValue and 'value' or 'schema')
+
+        for attr, value in self.readOnly.items():
+            if value:
+                representation += ', %s %s' % (attr, value)
+
+        if self.isValue:
+            value = self.prettyPrint()
+            if len(value) > 32:
+                value = value[:16] + '...' + value[-16:]
+            representation += ', payload [%s]' % value
+
+        return '<%s>' % representation
+
+    def __eq__(self, other):
+        if self is other:
+            return True
+        return self._value == other
+
+    def __ne__(self, other):
+        return self._value != other
+
+    def __lt__(self, other):
+        return self._value < other
+
+    def __le__(self, other):
+        return self._value <= other
+
+    def __gt__(self, other):
+        return self._value > other
+
+    def __ge__(self, other):
+        return self._value >= other
+
+    def __bool__(self):
+        return bool(self._value)
+
+    def __hash__(self):
+        return hash(self._value)
+
+    @property
+    def isValue(self):
+        """Indicate that |ASN.1| object represents ASN.1 value.
+
+        If *isValue* is :obj:`False` then this object represents just
+        ASN.1 schema.
+
+        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema
+        features, this object can also be used like a Python built-in object
+        (e.g. :class:`int`, :class:`str`, :class:`dict` etc.).
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`False` if object represents just ASN.1 schema.
+            :obj:`True` if object represents ASN.1 schema and can be used as a normal value.
+
+        Note
+        ----
+        There is an important distinction between PyASN1 schema and value objects.
+        The PyASN1 schema objects can only participate in ASN.1 schema-related
+        operations (e.g. defining or testing the structure of the data). Most
+        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
+        encoding/decoding serialised ASN.1 contents.
+
+        The PyASN1 value objects can **additionally** participate in many operations
+        involving regular Python objects (e.g. arithmetic, comprehension etc).
+        """
+        return self._value is not noValue
+
+    def clone(self, value=noValue, **kwargs):
+        """Create a modified version of |ASN.1| schema or value object.
+
+        The `clone()` method accepts the same set arguments as |ASN.1|
+        class takes on instantiation except that all arguments
+        of the `clone()` method are optional.
+
+        Whatever arguments are supplied, they are used to create a copy
+        of `self` taking precedence over the ones used to instantiate `self`.
+
+        Note
+        ----
+        Due to the immutable nature of the |ASN.1| object, if no arguments
+        are supplied, no new |ASN.1| object will be created and `self` will
+        be returned instead.
+        """
+        if value is noValue:
+            if not kwargs:
+                return self
+
+            value = self._value
+
+        initializers = self.readOnly.copy()
+        initializers.update(kwargs)
+
+        return self.__class__(value, **initializers)
+
+    def subtype(self, value=noValue, **kwargs):
+        """Create a specialization of |ASN.1| schema or value object.
+
+        The subtype relationship between ASN.1 types has no correlation with
+        subtype relationship between Python types. ASN.1 type is mainly identified
+        by its tag(s) (:py:class:`~pyasn1.type.tag.TagSet`) and value range
+        constraints (:py:class:`~pyasn1.type.constraint.ConstraintsIntersection`).
+        These ASN.1 type properties are implemented as |ASN.1| attributes.  
+
+        The `subtype()` method accepts the same set arguments as |ASN.1|
+        class takes on instantiation except that all parameters
+        of the `subtype()` method are optional.
+
+        With the exception of the arguments described below, the rest of
+        supplied arguments they are used to create a copy of `self` taking
+        precedence over the ones used to instantiate `self`.
+
+        The following arguments to `subtype()` create a ASN.1 subtype out of
+        |ASN.1| type:
+
+        Other Parameters
+        ----------------
+        implicitTag: :py:class:`~pyasn1.type.tag.Tag`
+            Implicitly apply given ASN.1 tag object to `self`'s
+            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
+            new object's ASN.1 tag(s).
+
+        explicitTag: :py:class:`~pyasn1.type.tag.Tag`
+            Explicitly apply given ASN.1 tag object to `self`'s
+            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
+            new object's ASN.1 tag(s).
+
+        subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+            Add ASN.1 constraints object to one of the `self`'s, then
+            use the result as new object's ASN.1 constraints.
+
+        Returns
+        -------
+        :
+            new instance of |ASN.1| schema or value object
+
+        Note
+        ----
+        Due to the immutable nature of the |ASN.1| object, if no arguments
+        are supplied, no new |ASN.1| object will be created and `self` will
+        be returned instead.
+        """
+        if value is noValue:
+            if not kwargs:
+                return self
+
+            value = self._value
+
+        initializers = self.readOnly.copy()
+
+        implicitTag = kwargs.pop('implicitTag', None)
+        if implicitTag is not None:
+            initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag)
+
+        explicitTag = kwargs.pop('explicitTag', None)
+        if explicitTag is not None:
+            initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag)
+
+        for arg, option in kwargs.items():
+            initializers[arg] += option
+
+        return self.__class__(value, **initializers)
+
+    def prettyIn(self, value):
+        return value
+
+    def prettyOut(self, value):
+        return str(value)
+
+    def prettyPrint(self, scope=0):
+        return self.prettyOut(self._value)
+
+    def prettyPrintType(self, scope=0):
+        return '%s -> %s' % (self.tagSet, self.__class__.__name__)
+
+# Backward compatibility
+AbstractSimpleAsn1Item = SimpleAsn1Type
+
+#
+# Constructed types:
+# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
+# * ASN1 types and values are represened by Python class instances
+# * Value initialization is made for defaulted components only
+# * Primary method of component addressing is by-position. Data model for base
+#   type is Python sequence. Additional type-specific addressing methods
+#   may be implemented for particular types.
+# * SequenceOf and SetOf types do not implement any additional methods
+# * Sequence, Set and Choice types also implement by-identifier addressing
+# * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing
+# * Sequence and Set types may include optional and defaulted
+#   components
+# * Constructed types hold a reference to component types used for value
+#   verification and ordering.
+# * Component type is a scalar type for SequenceOf/SetOf types and a list
+#   of types for Sequence/Set/Choice.
+#
+
+
+class ConstructedAsn1Type(Asn1Type):
+    """Base class for all constructed classes representing ASN.1 types.
+
+    ASN.1 distinguishes types by their ability to hold other objects.
+    Those "nesting" types are known as *constructed* in ASN.1.
+
+    In the user code, |ASN.1| class is normally used only for telling
+    ASN.1 objects from others.
+
+    Note
+    ----
+    For as long as ASN.1 is concerned, a way to compare ASN.1 types
+    is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods.
+    """
+
+    #: If :obj:`True`, requires exact component type matching,
+    #: otherwise subtype relation is only enforced
+    strictConstraints = False
+
+    componentType = None
+
+    # backward compatibility, unused
+    sizeSpec = constraint.ConstraintsIntersection()
+
+    def __init__(self, **kwargs):
+        readOnly = {
+            'componentType': self.componentType,
+            # backward compatibility, unused
+            'sizeSpec': self.sizeSpec
+        }
+
+        # backward compatibility: preserve legacy sizeSpec support
+        kwargs = self._moveSizeSpec(**kwargs)
+
+        readOnly.update(kwargs)
+
+        Asn1Type.__init__(self, **readOnly)
+
+    def _moveSizeSpec(self, **kwargs):
+        # backward compatibility, unused
+        sizeSpec = kwargs.pop('sizeSpec', self.sizeSpec)
+        if sizeSpec:
+            subtypeSpec = kwargs.pop('subtypeSpec', self.subtypeSpec)
+            if subtypeSpec:
+                subtypeSpec = sizeSpec
+
+            else:
+                subtypeSpec += sizeSpec
+
+            kwargs['subtypeSpec'] = subtypeSpec
+
+        return kwargs
+
+    def __repr__(self):
+        representation = '%s %s object' % (
+            self.__class__.__name__, self.isValue and 'value' or 'schema'
+        )
+
+        for attr, value in self.readOnly.items():
+            if value is not noValue:
+                representation += ', %s=%r' % (attr, value)
+
+        if self.isValue and self.components:
+            representation += ', payload [%s]' % ', '.join(
+                [repr(x) for x in self.components])
+
+        return '<%s>' % representation
+
+    def __eq__(self, other):
+        return self is other or self.components == other
+
+    def __ne__(self, other):
+        return self.components != other
+
+    def __lt__(self, other):
+        return self.components < other
+
+    def __le__(self, other):
+        return self.components <= other
+
+    def __gt__(self, other):
+        return self.components > other
+
+    def __ge__(self, other):
+        return self.components >= other
+
+    def __bool__(self):
+        return bool(self.components)
+
+    @property
+    def components(self):
+        raise error.PyAsn1Error('Method not implemented')
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        pass
+
+    def clone(self, **kwargs):
+        """Create a modified version of |ASN.1| schema object.
+
+        The `clone()` method accepts the same set arguments as |ASN.1|
+        class takes on instantiation except that all arguments
+        of the `clone()` method are optional.
+
+        Whatever arguments are supplied, they are used to create a copy
+        of `self` taking precedence over the ones used to instantiate `self`.
+
+        Possible values of `self` are never copied over thus `clone()` can
+        only create a new schema object.
+
+        Returns
+        -------
+        :
+            new instance of |ASN.1| type/value
+
+        Note
+        ----
+        Due to the mutable nature of the |ASN.1| object, even if no arguments
+        are supplied, a new |ASN.1| object will be created and returned.
+        """
+        cloneValueFlag = kwargs.pop('cloneValueFlag', False)
+
+        initializers = self.readOnly.copy()
+        initializers.update(kwargs)
+
+        clone = self.__class__(**initializers)
+
+        if cloneValueFlag:
+            self._cloneComponentValues(clone, cloneValueFlag)
+
+        return clone
+
+    def subtype(self, **kwargs):
+        """Create a specialization of |ASN.1| schema object.
+
+        The `subtype()` method accepts the same set arguments as |ASN.1|
+        class takes on instantiation except that all parameters
+        of the `subtype()` method are optional.
+
+        With the exception of the arguments described below, the rest of
+        supplied arguments they are used to create a copy of `self` taking
+        precedence over the ones used to instantiate `self`.
+
+        The following arguments to `subtype()` create a ASN.1 subtype out of
+        |ASN.1| type.
+
+        Other Parameters
+        ----------------
+        implicitTag: :py:class:`~pyasn1.type.tag.Tag`
+            Implicitly apply given ASN.1 tag object to `self`'s
+            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
+            new object's ASN.1 tag(s).
+
+        explicitTag: :py:class:`~pyasn1.type.tag.Tag`
+            Explicitly apply given ASN.1 tag object to `self`'s
+            :py:class:`~pyasn1.type.tag.TagSet`, then use the result as
+            new object's ASN.1 tag(s).
+
+        subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+            Add ASN.1 constraints object to one of the `self`'s, then
+            use the result as new object's ASN.1 constraints.
+
+
+        Returns
+        -------
+        :
+            new instance of |ASN.1| type/value
+
+        Note
+        ----
+        Due to the mutable nature of the |ASN.1| object, even if no arguments
+        are supplied, a new |ASN.1| object will be created and returned.
+        """
+
+        initializers = self.readOnly.copy()
+
+        cloneValueFlag = kwargs.pop('cloneValueFlag', False)
+
+        implicitTag = kwargs.pop('implicitTag', None)
+        if implicitTag is not None:
+            initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag)
+
+        explicitTag = kwargs.pop('explicitTag', None)
+        if explicitTag is not None:
+            initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag)
+
+        for arg, option in kwargs.items():
+            initializers[arg] += option
+
+        clone = self.__class__(**initializers)
+
+        if cloneValueFlag:
+            self._cloneComponentValues(clone, cloneValueFlag)
+
+        return clone
+
+    def getComponentByPosition(self, idx):
+        raise error.PyAsn1Error('Method not implemented')
+
+    def setComponentByPosition(self, idx, value, verifyConstraints=True):
+        raise error.PyAsn1Error('Method not implemented')
+
+    def setComponents(self, *args, **kwargs):
+        for idx, value in enumerate(args):
+            self[idx] = value
+        for k in kwargs:
+            self[k] = kwargs[k]
+        return self
+
+    # backward compatibility
+
+    def setDefaultComponents(self):
+        pass
+
+    def getComponentType(self):
+        return self.componentType
+
+    # backward compatibility, unused
+    def verifySizeSpec(self):
+        self.subtypeSpec(self)
+
+
+        # Backward compatibility
+AbstractConstructedAsn1Item = ConstructedAsn1Type
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/char.py b/.venv/lib/python3.12/site-packages/pyasn1/type/char.py
new file mode 100644
index 00000000..ec65f006
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/char.py
@@ -0,0 +1,288 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+import sys
+
+from pyasn1 import error
+from pyasn1.type import tag
+from pyasn1.type import univ
+
+__all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString',
+           'IA5String', 'GraphicString', 'VisibleString', 'ISO646String',
+           'GeneralString', 'UniversalString', 'BMPString', 'UTF8String']
+
+NoValue = univ.NoValue
+noValue = univ.noValue
+
+
+class AbstractCharacterString(univ.OctetString):
+    """Creates |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
+    its objects are immutable and duck-type :class:`bytes`.
+    When used in octet-stream context, |ASN.1| type assumes
+    "|encoding|" encoding.
+
+    Keyword Args
+    ------------
+    value: :class:`str`, :class:`bytes` or |ASN.1| object
+        :class:`str`, alternatively :class:`bytes`
+        representing octet-stream of serialised unicode string
+        (note `encoding` parameter) or |ASN.1| class instance.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    encoding: :py:class:`str`
+        Unicode codec ID to encode/decode
+        :class:`str` the payload when |ASN.1| object is used
+        in octet-stream context.
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+    """
+
+    def __str__(self):
+        return str(self._value)
+
+    def __bytes__(self):
+        try:
+            return self._value.encode(self.encoding)
+        except UnicodeEncodeError as exc:
+            raise error.PyAsn1UnicodeEncodeError(
+                "Can't encode string '%s' with codec "
+                "%s" % (self._value, self.encoding), exc
+            )
+
+    def prettyIn(self, value):
+        try:
+            if isinstance(value, str):
+                return value
+            elif isinstance(value, bytes):
+                return value.decode(self.encoding)
+            elif isinstance(value, (tuple, list)):
+                return self.prettyIn(bytes(value))
+            elif isinstance(value, univ.OctetString):
+                return value.asOctets().decode(self.encoding)
+            else:
+                return str(value)
+
+        except (UnicodeDecodeError, LookupError) as exc:
+            raise error.PyAsn1UnicodeDecodeError(
+                "Can't decode string '%s' with codec "
+                "%s" % (value, self.encoding), exc
+            )
+
+    def asOctets(self, padding=True):
+        return bytes(self)
+
+    def asNumbers(self, padding=True):
+        return tuple(bytes(self))
+
+    #
+    # See OctetString.prettyPrint() for the explanation
+    #
+
+    def prettyOut(self, value):
+        return value
+
+    def prettyPrint(self, scope=0):
+        # first see if subclass has its own .prettyOut()
+        value = self.prettyOut(self._value)
+
+        if value is not self._value:
+            return value
+
+        return AbstractCharacterString.__str__(self)
+
+    def __reversed__(self):
+        return reversed(self._value)
+
+
+class NumericString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18)
+    )
+    encoding = 'us-ascii'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class PrintableString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19)
+    )
+    encoding = 'us-ascii'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class TeletexString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20)
+    )
+    encoding = 'iso-8859-1'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class T61String(TeletexString):
+    __doc__ = TeletexString.__doc__
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class VideotexString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21)
+    )
+    encoding = 'iso-8859-1'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class IA5String(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22)
+    )
+    encoding = 'us-ascii'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class GraphicString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25)
+    )
+    encoding = 'iso-8859-1'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class VisibleString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26)
+    )
+    encoding = 'us-ascii'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class ISO646String(VisibleString):
+    __doc__ = VisibleString.__doc__
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+class GeneralString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27)
+    )
+    encoding = 'iso-8859-1'
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class UniversalString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28)
+    )
+    encoding = "utf-32-be"
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class BMPString(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30)
+    )
+    encoding = "utf-16-be"
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
+
+
+class UTF8String(AbstractCharacterString):
+    __doc__ = AbstractCharacterString.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = AbstractCharacterString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
+    )
+    encoding = "utf-8"
+
+    # Optimization for faster codec lookup
+    typeId = AbstractCharacterString.getTypeId()
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/constraint.py b/.venv/lib/python3.12/site-packages/pyasn1/type/constraint.py
new file mode 100644
index 00000000..02368d0a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/constraint.py
@@ -0,0 +1,751 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+# Original concept and code by Mike C. Fletcher.
+#
+import sys
+
+from pyasn1.type import error
+
+__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint',
+           'ValueRangeConstraint', 'ValueSizeConstraint',
+           'PermittedAlphabetConstraint', 'InnerTypeConstraint',
+           'ConstraintsExclusion', 'ConstraintsIntersection',
+           'ConstraintsUnion']
+
+
+class AbstractConstraint(object):
+
+    def __init__(self, *values):
+        self._valueMap = set()
+        self._setValues(values)
+        self.__hash = hash((self.__class__.__name__, self._values))
+
+    def __call__(self, value, idx=None):
+        if not self._values:
+            return
+
+        try:
+            self._testValue(value, idx)
+
+        except error.ValueConstraintError as exc:
+            raise error.ValueConstraintError(
+                '%s failed at: %r' % (self, exc)
+            )
+
+    def __repr__(self):
+        representation = '%s object' % (self.__class__.__name__)
+
+        if self._values:
+            representation += ', consts %s' % ', '.join(
+                [repr(x) for x in self._values])
+
+        return '<%s>' % representation
+
+    def __eq__(self, other):
+        if self is other:
+            return True
+        return self._values == other
+
+    def __ne__(self, other):
+        return self._values != other
+
+    def __lt__(self, other):
+        return self._values < other
+
+    def __le__(self, other):
+        return self._values <= other
+
+    def __gt__(self, other):
+        return self._values > other
+
+    def __ge__(self, other):
+        return self._values >= other
+
+    def __bool__(self):
+        return bool(self._values)
+
+    def __hash__(self):
+        return self.__hash
+
+    def _setValues(self, values):
+        self._values = values
+
+    def _testValue(self, value, idx):
+        raise error.ValueConstraintError(value)
+
+    # Constraints derivation logic
+    def getValueMap(self):
+        return self._valueMap
+
+    def isSuperTypeOf(self, otherConstraint):
+        # TODO: fix possible comparison of set vs scalars here
+        return (otherConstraint is self or
+                not self._values or
+                otherConstraint == self or
+                self in otherConstraint.getValueMap())
+
+    def isSubTypeOf(self, otherConstraint):
+        return (otherConstraint is self or
+                not self or
+                otherConstraint == self or
+                otherConstraint in self._valueMap)
+
+
+class SingleValueConstraint(AbstractConstraint):
+    """Create a SingleValueConstraint object.
+
+    The SingleValueConstraint satisfies any value that
+    is present in the set of permitted values.
+
+    Objects of this type are iterable (emitting constraint values) and
+    can act as operands for some arithmetic operations e.g. addition
+    and subtraction. The latter can be used for combining multiple
+    SingleValueConstraint objects into one.
+
+    The SingleValueConstraint object can be applied to
+    any ASN.1 type.
+
+    Parameters
+    ----------
+    *values: :class:`int`
+        Full set of values permitted by this constraint object.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class DivisorOfSix(Integer):
+            '''
+            ASN.1 specification:
+
+            Divisor-Of-6 ::= INTEGER (1 | 2 | 3 | 6)
+            '''
+            subtypeSpec = SingleValueConstraint(1, 2, 3, 6)
+
+        # this will succeed
+        divisor_of_six = DivisorOfSix(1)
+
+        # this will raise ValueConstraintError
+        divisor_of_six = DivisorOfSix(7)
+    """
+    def _setValues(self, values):
+        self._values = values
+        self._set = set(values)
+
+    def _testValue(self, value, idx):
+        if value not in self._set:
+            raise error.ValueConstraintError(value)
+
+    # Constrains can be merged or reduced
+
+    def __contains__(self, item):
+        return item in self._set
+
+    def __iter__(self):
+        return iter(self._set)
+
+    def __add__(self, constraint):
+        return self.__class__(*(self._set.union(constraint)))
+
+    def __sub__(self, constraint):
+        return self.__class__(*(self._set.difference(constraint)))
+
+
+class ContainedSubtypeConstraint(AbstractConstraint):
+    """Create a ContainedSubtypeConstraint object.
+
+    The ContainedSubtypeConstraint satisfies any value that
+    is present in the set of permitted values and also
+    satisfies included constraints.
+
+    The ContainedSubtypeConstraint object can be applied to
+    any ASN.1 type.
+
+    Parameters
+    ----------
+    *values:
+        Full set of values and constraint objects permitted
+        by this constraint object.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class DivisorOfEighteen(Integer):
+            '''
+            ASN.1 specification:
+
+            Divisors-of-18 ::= INTEGER (INCLUDES Divisors-of-6 | 9 | 18)
+            '''
+            subtypeSpec = ContainedSubtypeConstraint(
+                SingleValueConstraint(1, 2, 3, 6), 9, 18
+            )
+
+        # this will succeed
+        divisor_of_eighteen = DivisorOfEighteen(9)
+
+        # this will raise ValueConstraintError
+        divisor_of_eighteen = DivisorOfEighteen(10)
+    """
+    def _testValue(self, value, idx):
+        for constraint in self._values:
+            if isinstance(constraint, AbstractConstraint):
+                constraint(value, idx)
+            elif value not in self._set:
+                raise error.ValueConstraintError(value)
+
+
+class ValueRangeConstraint(AbstractConstraint):
+    """Create a ValueRangeConstraint object.
+
+    The ValueRangeConstraint satisfies any value that
+    falls in the range of permitted values.
+
+    The ValueRangeConstraint object can only be applied
+    to :class:`~pyasn1.type.univ.Integer` and
+    :class:`~pyasn1.type.univ.Real` types.
+
+    Parameters
+    ----------
+    start: :class:`int`
+        Minimum permitted value in the range (inclusive)
+
+    end: :class:`int`
+        Maximum permitted value in the range (inclusive)
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class TeenAgeYears(Integer):
+            '''
+            ASN.1 specification:
+
+            TeenAgeYears ::= INTEGER (13 .. 19)
+            '''
+            subtypeSpec = ValueRangeConstraint(13, 19)
+
+        # this will succeed
+        teen_year = TeenAgeYears(18)
+
+        # this will raise ValueConstraintError
+        teen_year = TeenAgeYears(20)
+    """
+    def _testValue(self, value, idx):
+        if value < self.start or value > self.stop:
+            raise error.ValueConstraintError(value)
+
+    def _setValues(self, values):
+        if len(values) != 2:
+            raise error.PyAsn1Error(
+                '%s: bad constraint values' % (self.__class__.__name__,)
+            )
+        self.start, self.stop = values
+        if self.start > self.stop:
+            raise error.PyAsn1Error(
+                '%s: screwed constraint values (start > stop): %s > %s' % (
+                    self.__class__.__name__,
+                    self.start, self.stop
+                )
+            )
+        AbstractConstraint._setValues(self, values)
+
+
+class ValueSizeConstraint(ValueRangeConstraint):
+    """Create a ValueSizeConstraint object.
+
+    The ValueSizeConstraint satisfies any value for
+    as long as its size falls within the range of
+    permitted sizes.
+
+    The ValueSizeConstraint object can be applied
+    to :class:`~pyasn1.type.univ.BitString`,
+    :class:`~pyasn1.type.univ.OctetString` (including
+    all :ref:`character ASN.1 types <type.char>`),
+    :class:`~pyasn1.type.univ.SequenceOf`
+    and :class:`~pyasn1.type.univ.SetOf` types.
+
+    Parameters
+    ----------
+    minimum: :class:`int`
+        Minimum permitted size of the value (inclusive)
+
+    maximum: :class:`int`
+        Maximum permitted size of the value (inclusive)
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class BaseballTeamRoster(SetOf):
+            '''
+            ASN.1 specification:
+
+            BaseballTeamRoster ::= SET SIZE (1..25) OF PlayerNames
+            '''
+            componentType = PlayerNames()
+            subtypeSpec = ValueSizeConstraint(1, 25)
+
+        # this will succeed
+        team = BaseballTeamRoster()
+        team.extend(['Jan', 'Matej'])
+        encode(team)
+
+        # this will raise ValueConstraintError
+        team = BaseballTeamRoster()
+        team.extend(['Jan'] * 26)
+        encode(team)
+
+    Note
+    ----
+    Whenever ValueSizeConstraint is applied to mutable types
+    (e.g. :class:`~pyasn1.type.univ.SequenceOf`,
+    :class:`~pyasn1.type.univ.SetOf`), constraint
+    validation only happens at the serialisation phase rather
+    than schema instantiation phase (as it is with immutable
+    types).
+    """
+    def _testValue(self, value, idx):
+        valueSize = len(value)
+        if valueSize < self.start or valueSize > self.stop:
+            raise error.ValueConstraintError(value)
+
+
+class PermittedAlphabetConstraint(SingleValueConstraint):
+    """Create a PermittedAlphabetConstraint object.
+
+    The PermittedAlphabetConstraint satisfies any character
+    string for as long as all its characters are present in
+    the set of permitted characters.
+
+    Objects of this type are iterable (emitting constraint values) and
+    can act as operands for some arithmetic operations e.g. addition
+    and subtraction.
+
+    The PermittedAlphabetConstraint object can only be applied
+    to the :ref:`character ASN.1 types <type.char>` such as
+    :class:`~pyasn1.type.char.IA5String`.
+
+    Parameters
+    ----------
+    *alphabet: :class:`str`
+        Full set of characters permitted by this constraint object.
+
+    Example
+    -------
+    .. code-block:: python
+
+        class BooleanValue(IA5String):
+            '''
+            ASN.1 specification:
+
+            BooleanValue ::= IA5String (FROM ('T' | 'F'))
+            '''
+            subtypeSpec = PermittedAlphabetConstraint('T', 'F')
+
+        # this will succeed
+        truth = BooleanValue('T')
+        truth = BooleanValue('TF')
+
+        # this will raise ValueConstraintError
+        garbage = BooleanValue('TAF')
+
+    ASN.1 `FROM ... EXCEPT ...` clause can be modelled by combining multiple
+    PermittedAlphabetConstraint objects into one:
+
+    Example
+    -------
+    .. code-block:: python
+
+        class Lipogramme(IA5String):
+            '''
+            ASN.1 specification:
+
+            Lipogramme ::=
+                IA5String (FROM (ALL EXCEPT ("e"|"E")))
+            '''
+            subtypeSpec = (
+                PermittedAlphabetConstraint(*string.printable) -
+                PermittedAlphabetConstraint('e', 'E')
+            )
+
+        # this will succeed
+        lipogramme = Lipogramme('A work of fiction?')
+
+        # this will raise ValueConstraintError
+        lipogramme = Lipogramme('Eel')
+
+    Note
+    ----
+    Although `ConstraintsExclusion` object could seemingly be used for this
+    purpose, practically, for it to work, it needs to represent its operand
+    constraints as sets and intersect one with the other. That would require
+    the insight into the constraint values (and their types) that are otherwise
+    hidden inside the constraint object.
+
+    Therefore it's more practical to model `EXCEPT` clause at
+    `PermittedAlphabetConstraint` level instead.
+    """
+    def _setValues(self, values):
+        self._values = values
+        self._set = set(values)
+
+    def _testValue(self, value, idx):
+        if not self._set.issuperset(value):
+            raise error.ValueConstraintError(value)
+
+
+class ComponentPresentConstraint(AbstractConstraint):
+    """Create a ComponentPresentConstraint object.
+
+    The ComponentPresentConstraint is only satisfied when the value
+    is not `None`.
+
+    The ComponentPresentConstraint object is typically used with
+    `WithComponentsConstraint`.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        present = ComponentPresentConstraint()
+
+        # this will succeed
+        present('whatever')
+
+        # this will raise ValueConstraintError
+        present(None)
+    """
+    def _setValues(self, values):
+        self._values = ('<must be present>',)
+
+        if values:
+            raise error.PyAsn1Error('No arguments expected')
+
+    def _testValue(self, value, idx):
+        if value is None:
+            raise error.ValueConstraintError(
+                'Component is not present:')
+
+
+class ComponentAbsentConstraint(AbstractConstraint):
+    """Create a ComponentAbsentConstraint object.
+
+    The ComponentAbsentConstraint is only satisfied when the value
+    is `None`.
+
+    The ComponentAbsentConstraint object is typically used with
+    `WithComponentsConstraint`.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        absent = ComponentAbsentConstraint()
+
+        # this will succeed
+        absent(None)
+
+        # this will raise ValueConstraintError
+        absent('whatever')
+    """
+    def _setValues(self, values):
+        self._values = ('<must be absent>',)
+
+        if values:
+            raise error.PyAsn1Error('No arguments expected')
+
+    def _testValue(self, value, idx):
+        if value is not None:
+            raise error.ValueConstraintError(
+                'Component is not absent: %r' % value)
+
+
+class WithComponentsConstraint(AbstractConstraint):
+    """Create a WithComponentsConstraint object.
+
+    The `WithComponentsConstraint` satisfies any mapping object that has
+    constrained fields present or absent, what is indicated by
+    `ComponentPresentConstraint` and `ComponentAbsentConstraint`
+    objects respectively.
+
+    The `WithComponentsConstraint` object is typically applied
+    to  :class:`~pyasn1.type.univ.Set` or
+    :class:`~pyasn1.type.univ.Sequence` types.
+
+    Parameters
+    ----------
+    *fields: :class:`tuple`
+        Zero or more tuples of (`field`, `constraint`) indicating constrained
+        fields.
+
+    Notes
+    -----
+    On top of the primary use of `WithComponentsConstraint` (ensuring presence
+    or absence of particular components of a :class:`~pyasn1.type.univ.Set` or
+    :class:`~pyasn1.type.univ.Sequence`), it is also possible to pass any other
+    constraint objects or their combinations. In case of scalar fields, these
+    constraints will be verified in addition to the constraints belonging to
+    scalar components themselves. However, formally, these additional
+    constraints do not change the type of these ASN.1 objects.
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class Item(Sequence):  #  Set is similar
+            '''
+            ASN.1 specification:
+
+            Item ::= SEQUENCE {
+                id    INTEGER OPTIONAL,
+                name  OCTET STRING OPTIONAL
+            } WITH COMPONENTS id PRESENT, name ABSENT | id ABSENT, name PRESENT
+            '''
+            componentType = NamedTypes(
+                OptionalNamedType('id', Integer()),
+                OptionalNamedType('name', OctetString())
+            )
+            withComponents = ConstraintsUnion(
+                WithComponentsConstraint(
+                    ('id', ComponentPresentConstraint()),
+                    ('name', ComponentAbsentConstraint())
+                ),
+                WithComponentsConstraint(
+                    ('id', ComponentAbsentConstraint()),
+                    ('name', ComponentPresentConstraint())
+                )
+            )
+
+        item = Item()
+
+        # This will succeed
+        item['id'] = 1
+
+        # This will succeed
+        item.reset()
+        item['name'] = 'John'
+
+        # This will fail (on encoding)
+        item.reset()
+        descr['id'] = 1
+        descr['name'] = 'John'
+    """
+    def _testValue(self, value, idx):
+        for field, constraint in self._values:
+            constraint(value.get(field))
+
+    def _setValues(self, values):
+        AbstractConstraint._setValues(self, values)
+
+
+# This is a bit kludgy, meaning two op modes within a single constraint
+class InnerTypeConstraint(AbstractConstraint):
+    """Value must satisfy the type and presence constraints"""
+
+    def _testValue(self, value, idx):
+        if self.__singleTypeConstraint:
+            self.__singleTypeConstraint(value)
+        elif self.__multipleTypeConstraint:
+            if idx not in self.__multipleTypeConstraint:
+                raise error.ValueConstraintError(value)
+            constraint, status = self.__multipleTypeConstraint[idx]
+            if status == 'ABSENT':  # XXX presence is not checked!
+                raise error.ValueConstraintError(value)
+            constraint(value)
+
+    def _setValues(self, values):
+        self.__multipleTypeConstraint = {}
+        self.__singleTypeConstraint = None
+        for v in values:
+            if isinstance(v, tuple):
+                self.__multipleTypeConstraint[v[0]] = v[1], v[2]
+            else:
+                self.__singleTypeConstraint = v
+        AbstractConstraint._setValues(self, values)
+
+
+# Logic operations on constraints
+
+class ConstraintsExclusion(AbstractConstraint):
+    """Create a ConstraintsExclusion logic operator object.
+
+    The ConstraintsExclusion logic operator succeeds when the
+    value does *not* satisfy the operand constraint.
+
+    The ConstraintsExclusion object can be applied to
+    any constraint and logic operator object.
+
+    Parameters
+    ----------
+    *constraints:
+        Constraint or logic operator objects.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class LuckyNumber(Integer):
+            subtypeSpec = ConstraintsExclusion(
+                SingleValueConstraint(13)
+            )
+
+        # this will succeed
+        luckyNumber = LuckyNumber(12)
+
+        # this will raise ValueConstraintError
+        luckyNumber = LuckyNumber(13)
+
+    Note
+    ----
+    The `FROM ... EXCEPT ...` ASN.1 clause should be modeled by combining
+    constraint objects into one. See `PermittedAlphabetConstraint` for more
+    information.
+    """
+    def _testValue(self, value, idx):
+        for constraint in self._values:
+            try:
+                constraint(value, idx)
+
+            except error.ValueConstraintError:
+                continue
+
+            raise error.ValueConstraintError(value)
+
+    def _setValues(self, values):
+        AbstractConstraint._setValues(self, values)
+
+
+class AbstractConstraintSet(AbstractConstraint):
+
+    def __getitem__(self, idx):
+        return self._values[idx]
+
+    def __iter__(self):
+        return iter(self._values)
+
+    def __add__(self, value):
+        return self.__class__(*(self._values + (value,)))
+
+    def __radd__(self, value):
+        return self.__class__(*((value,) + self._values))
+
+    def __len__(self):
+        return len(self._values)
+
+    # Constraints inclusion in sets
+
+    def _setValues(self, values):
+        self._values = values
+        for constraint in values:
+            if constraint:
+                self._valueMap.add(constraint)
+                self._valueMap.update(constraint.getValueMap())
+
+
+class ConstraintsIntersection(AbstractConstraintSet):
+    """Create a ConstraintsIntersection logic operator object.
+
+    The ConstraintsIntersection logic operator only succeeds
+    if *all* its operands succeed.
+
+    The ConstraintsIntersection object can be applied to
+    any constraint and logic operator objects.
+
+    The ConstraintsIntersection object duck-types the immutable
+    container object like Python :py:class:`tuple`.
+
+    Parameters
+    ----------
+    *constraints:
+        Constraint or logic operator objects.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class CapitalAndSmall(IA5String):
+            '''
+            ASN.1 specification:
+
+            CapitalAndSmall ::=
+                IA5String (FROM ("A".."Z"|"a".."z"))
+            '''
+            subtypeSpec = ConstraintsIntersection(
+                PermittedAlphabetConstraint('A', 'Z'),
+                PermittedAlphabetConstraint('a', 'z')
+            )
+
+        # this will succeed
+        capital_and_small = CapitalAndSmall('Hello')
+
+        # this will raise ValueConstraintError
+        capital_and_small = CapitalAndSmall('hello')
+    """
+    def _testValue(self, value, idx):
+        for constraint in self._values:
+            constraint(value, idx)
+
+
+class ConstraintsUnion(AbstractConstraintSet):
+    """Create a ConstraintsUnion logic operator object.
+
+    The ConstraintsUnion logic operator succeeds if
+    *at least* a single operand succeeds.
+
+    The ConstraintsUnion object can be applied to
+    any constraint and logic operator objects.
+
+    The ConstraintsUnion object duck-types the immutable
+    container object like Python :py:class:`tuple`.
+
+    Parameters
+    ----------
+    *constraints:
+        Constraint or logic operator objects.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class CapitalOrSmall(IA5String):
+            '''
+            ASN.1 specification:
+
+            CapitalOrSmall ::=
+                IA5String (FROM ("A".."Z") | FROM ("a".."z"))
+            '''
+            subtypeSpec = ConstraintsUnion(
+                PermittedAlphabetConstraint('A', 'Z'),
+                PermittedAlphabetConstraint('a', 'z')
+            )
+
+        # this will succeed
+        capital_or_small = CapitalAndSmall('Hello')
+
+        # this will raise ValueConstraintError
+        capital_or_small = CapitalOrSmall('hello!')
+    """
+    def _testValue(self, value, idx):
+        for constraint in self._values:
+            try:
+                constraint(value, idx)
+            except error.ValueConstraintError:
+                pass
+            else:
+                return
+
+        raise error.ValueConstraintError(
+            'all of %s failed for "%s"' % (self._values, value)
+        )
+
+# TODO:
+# refactor InnerTypeConstraint
+# add tests for type check
+# implement other constraint types
+# make constraint validation easy to skip
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/error.py b/.venv/lib/python3.12/site-packages/pyasn1/type/error.py
new file mode 100644
index 00000000..0ff082ab
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/error.py
@@ -0,0 +1,11 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+from pyasn1.error import PyAsn1Error
+
+
+class ValueConstraintError(PyAsn1Error):
+    pass
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/namedtype.py b/.venv/lib/python3.12/site-packages/pyasn1/type/namedtype.py
new file mode 100644
index 00000000..5f6c4ca3
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/namedtype.py
@@ -0,0 +1,550 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+import sys
+
+from pyasn1 import error
+from pyasn1.type import tag
+from pyasn1.type import tagmap
+
+__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType',
+           'NamedTypes']
+
+class NamedType(object):
+    """Create named field object for a constructed ASN.1 type.
+
+    The |NamedType| object represents a single name and ASN.1 type of a constructed ASN.1 type.
+
+    |NamedType| objects are immutable and duck-type Python :class:`tuple` objects
+    holding *name* and *asn1Object* components.
+
+    Parameters
+    ----------
+    name: :py:class:`str`
+        Field name
+
+    asn1Object:
+        ASN.1 type object
+    """
+    isOptional = False
+    isDefaulted = False
+
+    def __init__(self, name, asn1Object, openType=None):
+        self.__name = name
+        self.__type = asn1Object
+        self.__nameAndType = name, asn1Object
+        self.__openType = openType
+
+    def __repr__(self):
+        representation = '%s=%r' % (self.name, self.asn1Object)
+
+        if self.openType:
+            representation += ', open type %r' % self.openType
+
+        return '<%s object, type %s>' % (
+            self.__class__.__name__, representation)
+
+    def __eq__(self, other):
+        return self.__nameAndType == other
+
+    def __ne__(self, other):
+        return self.__nameAndType != other
+
+    def __lt__(self, other):
+        return self.__nameAndType < other
+
+    def __le__(self, other):
+        return self.__nameAndType <= other
+
+    def __gt__(self, other):
+        return self.__nameAndType > other
+
+    def __ge__(self, other):
+        return self.__nameAndType >= other
+
+    def __hash__(self):
+        return hash(self.__nameAndType)
+
+    def __getitem__(self, idx):
+        return self.__nameAndType[idx]
+
+    def __iter__(self):
+        return iter(self.__nameAndType)
+
+    @property
+    def name(self):
+        return self.__name
+
+    @property
+    def asn1Object(self):
+        return self.__type
+
+    @property
+    def openType(self):
+        return self.__openType
+
+    # Backward compatibility
+
+    def getName(self):
+        return self.name
+
+    def getType(self):
+        return self.asn1Object
+
+
+class OptionalNamedType(NamedType):
+    __doc__ = NamedType.__doc__
+
+    isOptional = True
+
+
+class DefaultedNamedType(NamedType):
+    __doc__ = NamedType.__doc__
+
+    isDefaulted = True
+
+
+class NamedTypes(object):
+    """Create a collection of named fields for a constructed ASN.1 type.
+
+    The NamedTypes object represents a collection of named fields of a constructed ASN.1 type.
+
+    *NamedTypes* objects are immutable and duck-type Python :class:`dict` objects
+    holding *name* as keys and ASN.1 type object as values.
+
+    Parameters
+    ----------
+    *namedTypes: :class:`~pyasn1.type.namedtype.NamedType`
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class Description(Sequence):
+            '''
+            ASN.1 specification:
+
+            Description ::= SEQUENCE {
+                surname    IA5String,
+                first-name IA5String OPTIONAL,
+                age        INTEGER DEFAULT 40
+            }
+            '''
+            componentType = NamedTypes(
+                NamedType('surname', IA5String()),
+                OptionalNamedType('first-name', IA5String()),
+                DefaultedNamedType('age', Integer(40))
+            )
+
+        descr = Description()
+        descr['surname'] = 'Smith'
+        descr['first-name'] = 'John'
+    """
+    def __init__(self, *namedTypes, **kwargs):
+        self.__namedTypes = namedTypes
+        self.__namedTypesLen = len(self.__namedTypes)
+        self.__minTagSet = self.__computeMinTagSet()
+        self.__nameToPosMap = self.__computeNameToPosMap()
+        self.__tagToPosMap = self.__computeTagToPosMap()
+        self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {}
+        self.__uniqueTagMap = self.__computeTagMaps(unique=True)
+        self.__nonUniqueTagMap = self.__computeTagMaps(unique=False)
+        self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes
+                                           if namedType.isDefaulted or namedType.isOptional])
+        self.__hasOpenTypes = any([True for namedType in self.__namedTypes
+                                   if namedType.openType])
+
+        self.__requiredComponents = frozenset(
+                [idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted]
+            )
+        self.__keys = frozenset([namedType.name for namedType in self.__namedTypes])
+        self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes])
+        self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes])
+
+    def __repr__(self):
+        representation = ', '.join(['%r' % x for x in self.__namedTypes])
+        return '<%s object, types %s>' % (
+            self.__class__.__name__, representation)
+
+    def __eq__(self, other):
+        return self.__namedTypes == other
+
+    def __ne__(self, other):
+        return self.__namedTypes != other
+
+    def __lt__(self, other):
+        return self.__namedTypes < other
+
+    def __le__(self, other):
+        return self.__namedTypes <= other
+
+    def __gt__(self, other):
+        return self.__namedTypes > other
+
+    def __ge__(self, other):
+        return self.__namedTypes >= other
+
+    def __hash__(self):
+        return hash(self.__namedTypes)
+
+    def __getitem__(self, idx):
+        try:
+            return self.__namedTypes[idx]
+
+        except TypeError:
+            return self.__namedTypes[self.__nameToPosMap[idx]]
+
+    def __contains__(self, key):
+        return key in self.__nameToPosMap
+
+    def __iter__(self):
+        return (x[0] for x in self.__namedTypes)
+
+    def __bool__(self):
+        return self.__namedTypesLen > 0
+
+    def __len__(self):
+        return self.__namedTypesLen
+
+    # Python dict protocol
+
+    def values(self):
+        return self.__values
+
+    def keys(self):
+        return self.__keys
+
+    def items(self):
+        return self.__items
+
+    def clone(self):
+        return self.__class__(*self.__namedTypes)
+
+    class PostponedError(object):
+        def __init__(self, errorMsg):
+            self.__errorMsg = errorMsg
+
+        def __getitem__(self, item):
+            raise  error.PyAsn1Error(self.__errorMsg)
+
+    def __computeTagToPosMap(self):
+        tagToPosMap = {}
+        for idx, namedType in enumerate(self.__namedTypes):
+            tagMap = namedType.asn1Object.tagMap
+            if isinstance(tagMap, NamedTypes.PostponedError):
+                return tagMap
+            if not tagMap:
+                continue
+            for _tagSet in tagMap.presentTypes:
+                if _tagSet in tagToPosMap:
+                    return NamedTypes.PostponedError('Duplicate component tag %s at %s' % (_tagSet, namedType))
+                tagToPosMap[_tagSet] = idx
+
+        return tagToPosMap
+
+    def __computeNameToPosMap(self):
+        nameToPosMap = {}
+        for idx, namedType in enumerate(self.__namedTypes):
+            if namedType.name in nameToPosMap:
+                return NamedTypes.PostponedError('Duplicate component name %s at %s' % (namedType.name, namedType))
+            nameToPosMap[namedType.name] = idx
+
+        return nameToPosMap
+
+    def __computeAmbiguousTypes(self):
+        ambiguousTypes = {}
+        partialAmbiguousTypes = ()
+        for idx, namedType in reversed(tuple(enumerate(self.__namedTypes))):
+            if namedType.isOptional or namedType.isDefaulted:
+                partialAmbiguousTypes = (namedType,) + partialAmbiguousTypes
+            else:
+                partialAmbiguousTypes = (namedType,)
+            if len(partialAmbiguousTypes) == len(self.__namedTypes):
+                ambiguousTypes[idx] = self
+            else:
+                ambiguousTypes[idx] = NamedTypes(*partialAmbiguousTypes, **dict(terminal=True))
+        return ambiguousTypes
+
+    def getTypeByPosition(self, idx):
+        """Return ASN.1 type object by its position in fields set.
+
+        Parameters
+        ----------
+        idx: :py:class:`int`
+            Field index
+
+        Returns
+        -------
+        :
+            ASN.1 type
+
+        Raises
+        ------
+        ~pyasn1.error.PyAsn1Error
+            If given position is out of fields range
+        """
+        try:
+            return self.__namedTypes[idx].asn1Object
+
+        except IndexError:
+            raise error.PyAsn1Error('Type position out of range')
+
+    def getPositionByType(self, tagSet):
+        """Return field position by its ASN.1 type.
+
+        Parameters
+        ----------
+        tagSet: :class:`~pysnmp.type.tag.TagSet`
+            ASN.1 tag set distinguishing one ASN.1 type from others.
+
+        Returns
+        -------
+        : :py:class:`int`
+            ASN.1 type position in fields set
+
+        Raises
+        ------
+        ~pyasn1.error.PyAsn1Error
+            If *tagSet* is not present or ASN.1 types are not unique within callee *NamedTypes*
+        """
+        try:
+            return self.__tagToPosMap[tagSet]
+
+        except KeyError:
+            raise error.PyAsn1Error('Type %s not found' % (tagSet,))
+
+    def getNameByPosition(self, idx):
+        """Return field name by its position in fields set.
+
+        Parameters
+        ----------
+        idx: :py:class:`idx`
+            Field index
+
+        Returns
+        -------
+        : :py:class:`str`
+            Field name
+
+        Raises
+        ------
+        ~pyasn1.error.PyAsn1Error
+            If given field name is not present in callee *NamedTypes*
+        """
+        try:
+            return self.__namedTypes[idx].name
+
+        except IndexError:
+            raise error.PyAsn1Error('Type position out of range')
+
+    def getPositionByName(self, name):
+        """Return field position by filed name.
+
+        Parameters
+        ----------
+        name: :py:class:`str`
+            Field name
+
+        Returns
+        -------
+        : :py:class:`int`
+            Field position in fields set
+
+        Raises
+        ------
+        ~pyasn1.error.PyAsn1Error
+            If *name* is not present or not unique within callee *NamedTypes*
+        """
+        try:
+            return self.__nameToPosMap[name]
+
+        except KeyError:
+            raise error.PyAsn1Error('Name %s not found' % (name,))
+
+    def getTagMapNearPosition(self, idx):
+        """Return ASN.1 types that are allowed at or past given field position.
+
+        Some ASN.1 serialisation allow for skipping optional and defaulted fields.
+        Some constructed ASN.1 types allow reordering of the fields. When recovering
+        such objects it may be important to know which types can possibly be
+        present at any given position in the field sets.
+
+        Parameters
+        ----------
+        idx: :py:class:`int`
+            Field index
+
+        Returns
+        -------
+        : :class:`~pyasn1.type.tagmap.TagMap`
+            Map if ASN.1 types allowed at given field position
+
+        Raises
+        ------
+        ~pyasn1.error.PyAsn1Error
+            If given position is out of fields range
+        """
+        try:
+            return self.__ambiguousTypes[idx].tagMap
+
+        except KeyError:
+            raise error.PyAsn1Error('Type position out of range')
+
+    def getPositionNearType(self, tagSet, idx):
+        """Return the closest field position where given ASN.1 type is allowed.
+
+        Some ASN.1 serialisation allow for skipping optional and defaulted fields.
+        Some constructed ASN.1 types allow reordering of the fields. When recovering
+        such objects it may be important to know at which field position, in field set,
+        given *tagSet* is allowed at or past *idx* position.
+
+        Parameters
+        ----------
+        tagSet: :class:`~pyasn1.type.tag.TagSet`
+           ASN.1 type which field position to look up
+
+        idx: :py:class:`int`
+            Field position at or past which to perform ASN.1 type look up
+
+        Returns
+        -------
+        : :py:class:`int`
+            Field position in fields set
+
+        Raises
+        ------
+        ~pyasn1.error.PyAsn1Error
+            If *tagSet* is not present or not unique within callee *NamedTypes*
+            or *idx* is out of fields range
+        """
+        try:
+            return idx + self.__ambiguousTypes[idx].getPositionByType(tagSet)
+
+        except KeyError:
+            raise error.PyAsn1Error('Type position out of range')
+
+    def __computeMinTagSet(self):
+        minTagSet = None
+        for namedType in self.__namedTypes:
+            asn1Object = namedType.asn1Object
+
+            try:
+                tagSet = asn1Object.minTagSet
+
+            except AttributeError:
+                tagSet = asn1Object.tagSet
+
+            if minTagSet is None or tagSet < minTagSet:
+                minTagSet = tagSet
+
+        return minTagSet or tag.TagSet()
+
+    @property
+    def minTagSet(self):
+        """Return the minimal TagSet among ASN.1 type in callee *NamedTypes*.
+
+        Some ASN.1 types/serialisation protocols require ASN.1 types to be
+        arranged based on their numerical tag value. The *minTagSet* property
+        returns that.
+
+        Returns
+        -------
+        : :class:`~pyasn1.type.tagset.TagSet`
+            Minimal TagSet among ASN.1 types in callee *NamedTypes*
+        """
+        return self.__minTagSet
+
+    def __computeTagMaps(self, unique):
+        presentTypes = {}
+        skipTypes = {}
+        defaultType = None
+        for namedType in self.__namedTypes:
+            tagMap = namedType.asn1Object.tagMap
+            if isinstance(tagMap, NamedTypes.PostponedError):
+                return tagMap
+            for tagSet in tagMap:
+                if unique and tagSet in presentTypes:
+                    return NamedTypes.PostponedError('Non-unique tagSet %s of %s at %s' % (tagSet, namedType, self))
+                presentTypes[tagSet] = namedType.asn1Object
+            skipTypes.update(tagMap.skipTypes)
+
+            if defaultType is None:
+                defaultType = tagMap.defaultType
+            elif tagMap.defaultType is not None:
+                return NamedTypes.PostponedError('Duplicate default ASN.1 type at %s' % (self,))
+
+        return tagmap.TagMap(presentTypes, skipTypes, defaultType)
+
+    @property
+    def tagMap(self):
+        """Return a *TagMap* object from tags and types recursively.
+
+        Return a :class:`~pyasn1.type.tagmap.TagMap` object by
+        combining tags from *TagMap* objects of children types and
+        associating them with their immediate child type.
+
+        Example
+        -------
+        .. code-block:: python
+
+           OuterType ::= CHOICE {
+               innerType INTEGER
+           }
+
+        Calling *.tagMap* on *OuterType* will yield a map like this:
+
+        .. code-block:: python
+
+           Integer.tagSet -> Choice
+        """
+        return self.__nonUniqueTagMap
+
+    @property
+    def tagMapUnique(self):
+        """Return a *TagMap* object from unique tags and types recursively.
+
+        Return a :class:`~pyasn1.type.tagmap.TagMap` object by
+        combining tags from *TagMap* objects of children types and
+        associating them with their immediate child type.
+
+        Example
+        -------
+        .. code-block:: python
+
+           OuterType ::= CHOICE {
+               innerType INTEGER
+           }
+
+        Calling *.tagMapUnique* on *OuterType* will yield a map like this:
+
+        .. code-block:: python
+
+           Integer.tagSet -> Choice
+
+        Note
+        ----
+
+        Duplicate *TagSet* objects found in the tree of children
+        types would cause error.
+        """
+        return self.__uniqueTagMap
+
+    @property
+    def hasOptionalOrDefault(self):
+        return self.__hasOptionalOrDefault
+
+    @property
+    def hasOpenTypes(self):
+        return self.__hasOpenTypes
+
+    @property
+    def namedTypes(self):
+        return tuple(self.__namedTypes)
+
+    @property
+    def requiredComponents(self):
+        return self.__requiredComponents
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/namedval.py b/.venv/lib/python3.12/site-packages/pyasn1/type/namedval.py
new file mode 100644
index 00000000..46a6496d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/namedval.py
@@ -0,0 +1,192 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/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),)
+            )
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/opentype.py b/.venv/lib/python3.12/site-packages/pyasn1/type/opentype.py
new file mode 100644
index 00000000..5a15f896
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/opentype.py
@@ -0,0 +1,104 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+
+__all__ = ['OpenType']
+
+
+class OpenType(object):
+    """Create ASN.1 type map indexed by a value
+
+    The *OpenType* object models an untyped field of a constructed ASN.1
+    type. In ASN.1 syntax it is usually represented by the
+    `ANY DEFINED BY` for scalars or `SET OF ANY DEFINED BY`,
+    `SEQUENCE OF ANY DEFINED BY` for container types clauses. Typically
+    used together with :class:`~pyasn1.type.univ.Any` object.
+
+    OpenType objects duck-type a read-only Python :class:`dict` objects,
+    however the passed `typeMap` is not copied, but stored by reference.
+    That means the user can manipulate `typeMap` at run time having this
+    reflected on *OpenType* object behavior.
+
+    The |OpenType| class models an untyped field of a constructed ASN.1
+    type. In ASN.1 syntax it is usually represented by the
+    `ANY DEFINED BY` for scalars or `SET OF ANY DEFINED BY`,
+    `SEQUENCE OF ANY DEFINED BY` for container types clauses. Typically
+    used with :class:`~pyasn1.type.univ.Any` type.
+
+    Parameters
+    ----------
+    name: :py:class:`str`
+        Field name
+
+    typeMap: :py:class:`dict`
+        A map of value->ASN.1 type. It's stored by reference and can be
+        mutated later to register new mappings.
+
+    Examples
+    --------
+
+    For untyped scalars:
+
+    .. code-block:: python
+
+        openType = OpenType(
+            'id', {1: Integer(),
+                   2: OctetString()}
+        )
+        Sequence(
+            componentType=NamedTypes(
+                NamedType('id', Integer()),
+                NamedType('blob', Any(), openType=openType)
+            )
+        )
+
+    For untyped `SET OF` or `SEQUENCE OF` vectors:
+
+    .. code-block:: python
+
+        openType = OpenType(
+            'id', {1: Integer(),
+                   2: OctetString()}
+        )
+        Sequence(
+            componentType=NamedTypes(
+                NamedType('id', Integer()),
+                NamedType('blob', SetOf(componentType=Any()),
+                          openType=openType)
+            )
+        )
+    """
+
+    def __init__(self, name, typeMap=None):
+        self.__name = name
+        if typeMap is None:
+            self.__typeMap = {}
+        else:
+            self.__typeMap = typeMap
+
+    @property
+    def name(self):
+        return self.__name
+
+    # Python dict protocol
+
+    def values(self):
+        return self.__typeMap.values()
+
+    def keys(self):
+        return self.__typeMap.keys()
+
+    def items(self):
+        return self.__typeMap.items()
+
+    def __contains__(self, key):
+        return key in self.__typeMap
+
+    def __getitem__(self, key):
+        return self.__typeMap[key]
+
+    def __iter__(self):
+        return iter(self.__typeMap)
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/tag.py b/.venv/lib/python3.12/site-packages/pyasn1/type/tag.py
new file mode 100644
index 00000000..ccb8b00c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/tag.py
@@ -0,0 +1,335 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+from pyasn1 import error
+
+__all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext',
+           'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed',
+           'tagCategoryImplicit', 'tagCategoryExplicit',
+           'tagCategoryUntagged', 'Tag', 'TagSet']
+
+#: Identifier for ASN.1 class UNIVERSAL
+tagClassUniversal = 0x00
+
+#: Identifier for ASN.1 class APPLICATION
+tagClassApplication = 0x40
+
+#: Identifier for ASN.1 class context-specific
+tagClassContext = 0x80
+
+#: Identifier for ASN.1 class private
+tagClassPrivate = 0xC0
+
+#: Identifier for "simple" ASN.1 structure (e.g. scalar)
+tagFormatSimple = 0x00
+
+#: Identifier for "constructed" ASN.1 structure (e.g. may have inner components)
+tagFormatConstructed = 0x20
+
+tagCategoryImplicit = 0x01
+tagCategoryExplicit = 0x02
+tagCategoryUntagged = 0x04
+
+
+class Tag(object):
+    """Create ASN.1 tag
+
+    Represents ASN.1 tag that can be attached to a ASN.1 type to make
+    types distinguishable from each other.
+
+    *Tag* objects are immutable and duck-type Python :class:`tuple` objects
+    holding three integer components of a tag.
+
+    Parameters
+    ----------
+    tagClass: :py:class:`int`
+        Tag *class* value
+
+    tagFormat: :py:class:`int`
+        Tag *format* value
+
+    tagId: :py:class:`int`
+        Tag ID value
+    """
+    def __init__(self, tagClass, tagFormat, tagId):
+        if tagId < 0:
+            raise error.PyAsn1Error('Negative tag ID (%s) not allowed' % tagId)
+        self.__tagClass = tagClass
+        self.__tagFormat = tagFormat
+        self.__tagId = tagId
+        self.__tagClassId = tagClass, tagId
+        self.__hash = hash(self.__tagClassId)
+
+    def __repr__(self):
+        representation = '[%s:%s:%s]' % (
+            self.__tagClass, self.__tagFormat, self.__tagId)
+        return '<%s object, tag %s>' % (
+            self.__class__.__name__, representation)
+
+    def __eq__(self, other):
+        return self.__tagClassId == other
+
+    def __ne__(self, other):
+        return self.__tagClassId != other
+
+    def __lt__(self, other):
+        return self.__tagClassId < other
+
+    def __le__(self, other):
+        return self.__tagClassId <= other
+
+    def __gt__(self, other):
+        return self.__tagClassId > other
+
+    def __ge__(self, other):
+        return self.__tagClassId >= other
+
+    def __hash__(self):
+        return self.__hash
+
+    def __getitem__(self, idx):
+        if idx == 0:
+            return self.__tagClass
+        elif idx == 1:
+            return self.__tagFormat
+        elif idx == 2:
+            return self.__tagId
+        else:
+            raise IndexError
+
+    def __iter__(self):
+        yield self.__tagClass
+        yield self.__tagFormat
+        yield self.__tagId
+
+    def __and__(self, otherTag):
+        return self.__class__(self.__tagClass & otherTag.tagClass,
+                              self.__tagFormat & otherTag.tagFormat,
+                              self.__tagId & otherTag.tagId)
+
+    def __or__(self, otherTag):
+        return self.__class__(self.__tagClass | otherTag.tagClass,
+                              self.__tagFormat | otherTag.tagFormat,
+                              self.__tagId | otherTag.tagId)
+
+    @property
+    def tagClass(self):
+        """ASN.1 tag class
+
+        Returns
+        -------
+        : :py:class:`int`
+            Tag class
+        """
+        return self.__tagClass
+
+    @property
+    def tagFormat(self):
+        """ASN.1 tag format
+
+        Returns
+        -------
+        : :py:class:`int`
+            Tag format
+        """
+        return self.__tagFormat
+
+    @property
+    def tagId(self):
+        """ASN.1 tag ID
+
+        Returns
+        -------
+        : :py:class:`int`
+            Tag ID
+        """
+        return self.__tagId
+
+
+class TagSet(object):
+    """Create a collection of ASN.1 tags
+
+    Represents a combination of :class:`~pyasn1.type.tag.Tag` objects
+    that can be attached to a ASN.1 type to make types distinguishable
+    from each other.
+
+    *TagSet* objects are immutable and duck-type Python :class:`tuple` objects
+    holding arbitrary number of :class:`~pyasn1.type.tag.Tag` objects.
+
+    Parameters
+    ----------
+    baseTag: :class:`~pyasn1.type.tag.Tag`
+        Base *Tag* object. This tag survives IMPLICIT tagging.
+
+    *superTags: :class:`~pyasn1.type.tag.Tag`
+        Additional *Tag* objects taking part in subtyping.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class OrderNumber(NumericString):
+            '''
+            ASN.1 specification
+
+            Order-number ::=
+                [APPLICATION 5] IMPLICIT NumericString
+            '''
+            tagSet = NumericString.tagSet.tagImplicitly(
+                Tag(tagClassApplication, tagFormatSimple, 5)
+            )
+
+        orderNumber = OrderNumber('1234')
+    """
+    def __init__(self, baseTag=(), *superTags):
+        self.__baseTag = baseTag
+        self.__superTags = superTags
+        self.__superTagsClassId = tuple(
+            [(superTag.tagClass, superTag.tagId) for superTag in superTags]
+        )
+        self.__lenOfSuperTags = len(superTags)
+        self.__hash = hash(self.__superTagsClassId)
+
+    def __repr__(self):
+        representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId)
+                                   for x in self.__superTags])
+        if representation:
+            representation = 'tags ' + representation
+        else:
+            representation = 'untagged'
+
+        return '<%s object, %s>' % (self.__class__.__name__, representation)
+
+    def __add__(self, superTag):
+        return self.__class__(self.__baseTag, *self.__superTags + (superTag,))
+
+    def __radd__(self, superTag):
+        return self.__class__(self.__baseTag, *(superTag,) + self.__superTags)
+
+    def __getitem__(self, i):
+        if i.__class__ is slice:
+            return self.__class__(self.__baseTag, *self.__superTags[i])
+        else:
+            return self.__superTags[i]
+
+    def __eq__(self, other):
+        return self.__superTagsClassId == other
+
+    def __ne__(self, other):
+        return self.__superTagsClassId != other
+
+    def __lt__(self, other):
+        return self.__superTagsClassId < other
+
+    def __le__(self, other):
+        return self.__superTagsClassId <= other
+
+    def __gt__(self, other):
+        return self.__superTagsClassId > other
+
+    def __ge__(self, other):
+        return self.__superTagsClassId >= other
+
+    def __hash__(self):
+        return self.__hash
+
+    def __len__(self):
+        return self.__lenOfSuperTags
+
+    @property
+    def baseTag(self):
+        """Return base ASN.1 tag
+
+        Returns
+        -------
+        : :class:`~pyasn1.type.tag.Tag`
+            Base tag of this *TagSet*
+        """
+        return self.__baseTag
+
+    @property
+    def superTags(self):
+        """Return ASN.1 tags
+
+        Returns
+        -------
+        : :py:class:`tuple`
+            Tuple of :class:`~pyasn1.type.tag.Tag` objects that this *TagSet* contains
+        """
+        return self.__superTags
+
+    def tagExplicitly(self, superTag):
+        """Return explicitly tagged *TagSet*
+
+        Create a new *TagSet* representing callee *TagSet* explicitly tagged
+        with passed tag(s). With explicit tagging mode, new tags are appended
+        to existing tag(s).
+
+        Parameters
+        ----------
+        superTag: :class:`~pyasn1.type.tag.Tag`
+            *Tag* object to tag this *TagSet*
+
+        Returns
+        -------
+        : :class:`~pyasn1.type.tag.TagSet`
+            New *TagSet* object
+        """
+        if superTag.tagClass == tagClassUniversal:
+            raise error.PyAsn1Error("Can't tag with UNIVERSAL class tag")
+        if superTag.tagFormat != tagFormatConstructed:
+            superTag = Tag(superTag.tagClass, tagFormatConstructed, superTag.tagId)
+        return self + superTag
+
+    def tagImplicitly(self, superTag):
+        """Return implicitly tagged *TagSet*
+
+        Create a new *TagSet* representing callee *TagSet* implicitly tagged
+        with passed tag(s). With implicit tagging mode, new tag(s) replace the
+        last existing tag.
+
+        Parameters
+        ----------
+        superTag: :class:`~pyasn1.type.tag.Tag`
+            *Tag* object to tag this *TagSet*
+
+        Returns
+        -------
+        : :class:`~pyasn1.type.tag.TagSet`
+            New *TagSet* object
+        """
+        if self.__superTags:
+            superTag = Tag(superTag.tagClass, self.__superTags[-1].tagFormat, superTag.tagId)
+        return self[:-1] + superTag
+
+    def isSuperTagSetOf(self, tagSet):
+        """Test type relationship against given *TagSet*
+
+        The callee is considered to be a supertype of given *TagSet*
+        tag-wise if all tags in *TagSet* are present in the callee and
+        they are in the same order.
+
+        Parameters
+        ----------
+        tagSet: :class:`~pyasn1.type.tag.TagSet`
+            *TagSet* object to evaluate against the callee
+
+        Returns
+        -------
+        : :py:class:`bool`
+            :obj:`True` if callee is a supertype of *tagSet*
+        """
+        if len(tagSet) < self.__lenOfSuperTags:
+            return False
+        return self.__superTags == tagSet[:self.__lenOfSuperTags]
+
+    # Backward compatibility
+
+    def getBaseTag(self):
+        return self.__baseTag
+
+def initTagSet(tag):
+    return TagSet(tag, tag)
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/tagmap.py b/.venv/lib/python3.12/site-packages/pyasn1/type/tagmap.py
new file mode 100644
index 00000000..7f8a955a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/tagmap.py
@@ -0,0 +1,96 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+from pyasn1 import error
+
+__all__ = ['TagMap']
+
+
+class TagMap(object):
+    """Map *TagSet* objects to ASN.1 types
+
+    Create an object mapping *TagSet* object to ASN.1 type.
+
+    *TagMap* objects are immutable and duck-type read-only Python
+    :class:`dict` objects holding *TagSet* objects as keys and ASN.1
+    type objects as values.
+
+    Parameters
+    ----------
+    presentTypes: :py:class:`dict`
+        Map of :class:`~pyasn1.type.tag.TagSet` to ASN.1 objects considered
+        as being unconditionally present in the *TagMap*.
+
+    skipTypes: :py:class:`dict`
+        A collection of :class:`~pyasn1.type.tag.TagSet` objects considered
+        as absent in the *TagMap* even when *defaultType* is present.
+
+    defaultType: ASN.1 type object
+        An ASN.1 type object callee *TagMap* returns for any *TagSet* key not present
+        in *presentTypes* (unless given key is present in *skipTypes*).
+    """
+    def __init__(self, presentTypes=None, skipTypes=None, defaultType=None):
+        self.__presentTypes = presentTypes or {}
+        self.__skipTypes = skipTypes or {}
+        self.__defaultType = defaultType
+
+    def __contains__(self, tagSet):
+        return (tagSet in self.__presentTypes or
+                self.__defaultType is not None and tagSet not in self.__skipTypes)
+
+    def __getitem__(self, tagSet):
+        try:
+            return self.__presentTypes[tagSet]
+        except KeyError:
+            if self.__defaultType is None:
+                raise
+            elif tagSet in self.__skipTypes:
+                raise error.PyAsn1Error('Key in negative map')
+            else:
+                return self.__defaultType
+
+    def __iter__(self):
+        return iter(self.__presentTypes)
+
+    def __repr__(self):
+        representation = '%s object' % self.__class__.__name__
+
+        if self.__presentTypes:
+            representation += ', present %s' % repr(self.__presentTypes)
+
+        if self.__skipTypes:
+            representation += ', skip %s' % repr(self.__skipTypes)
+
+        if self.__defaultType is not None:
+            representation += ', default %s' % repr(self.__defaultType)
+
+        return '<%s>' % representation
+
+    @property
+    def presentTypes(self):
+        """Return *TagSet* to ASN.1 type map present in callee *TagMap*"""
+        return self.__presentTypes
+
+    @property
+    def skipTypes(self):
+        """Return *TagSet* collection unconditionally absent in callee *TagMap*"""
+        return self.__skipTypes
+
+    @property
+    def defaultType(self):
+        """Return default ASN.1 type being returned for any missing *TagSet*"""
+        return self.__defaultType
+
+    # Backward compatibility
+
+    def getPosMap(self):
+        return self.presentTypes
+
+    def getNegMap(self):
+        return self.skipTypes
+
+    def getDef(self):
+        return self.defaultType
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/univ.py b/.venv/lib/python3.12/site-packages/pyasn1/type/univ.py
new file mode 100644
index 00000000..9aff5e69
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/univ.py
@@ -0,0 +1,3327 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+import math
+import sys
+
+from pyasn1 import error
+from pyasn1.codec.ber import eoo
+from pyasn1.compat import integer
+from pyasn1.type import base
+from pyasn1.type import constraint
+from pyasn1.type import namedtype
+from pyasn1.type import namedval
+from pyasn1.type import tag
+from pyasn1.type import tagmap
+
+NoValue = base.NoValue
+noValue = NoValue()
+
+__all__ = ['Integer', 'Boolean', 'BitString', 'OctetString', 'Null',
+           'ObjectIdentifier', 'Real', 'Enumerated',
+           'SequenceOfAndSetOfBase', 'SequenceOf', 'SetOf',
+           'SequenceAndSetBase', 'Sequence', 'Set', 'Choice', 'Any',
+           'NoValue', 'noValue']
+
+# "Simple" ASN.1 types (yet incomplete)
+
+
+class Integer(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`int` objects.
+
+    Keyword Args
+    ------------
+    value: :class:`int`, :class:`str` or |ASN.1| object
+        Python :class:`int` or :class:`str` literal or |ASN.1| class
+        instance. If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
+        Object representing non-default symbolic aliases for numbers
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class ErrorCode(Integer):
+            '''
+            ASN.1 specification:
+
+            ErrorCode ::=
+                INTEGER { disk-full(1), no-disk(-1),
+                          disk-not-formatted(2) }
+
+            error ErrorCode ::= disk-full
+            '''
+            namedValues = NamedValues(
+                ('disk-full', 1), ('no-disk', -1),
+                ('disk-not-formatted', 2)
+            )
+
+        error = ErrorCode('disk-full')
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
+    #: representing symbolic aliases for numbers
+    namedValues = namedval.NamedValues()
+
+    # Optimization for faster codec lookup
+    typeId = base.SimpleAsn1Type.getTypeId()
+
+    def __init__(self, value=noValue, **kwargs):
+        if 'namedValues' not in kwargs:
+            kwargs['namedValues'] = self.namedValues
+
+        base.SimpleAsn1Type.__init__(self, value, **kwargs)
+
+    def __and__(self, value):
+        return self.clone(self._value & value)
+
+    def __rand__(self, value):
+        return self.clone(value & self._value)
+
+    def __or__(self, value):
+        return self.clone(self._value | value)
+
+    def __ror__(self, value):
+        return self.clone(value | self._value)
+
+    def __xor__(self, value):
+        return self.clone(self._value ^ value)
+
+    def __rxor__(self, value):
+        return self.clone(value ^ self._value)
+
+    def __lshift__(self, value):
+        return self.clone(self._value << value)
+
+    def __rshift__(self, value):
+        return self.clone(self._value >> value)
+
+    def __add__(self, value):
+        return self.clone(self._value + value)
+
+    def __radd__(self, value):
+        return self.clone(value + self._value)
+
+    def __sub__(self, value):
+        return self.clone(self._value - value)
+
+    def __rsub__(self, value):
+        return self.clone(value - self._value)
+
+    def __mul__(self, value):
+        return self.clone(self._value * value)
+
+    def __rmul__(self, value):
+        return self.clone(value * self._value)
+
+    def __mod__(self, value):
+        return self.clone(self._value % value)
+
+    def __rmod__(self, value):
+        return self.clone(value % self._value)
+
+    def __pow__(self, value, modulo=None):
+        return self.clone(pow(self._value, value, modulo))
+
+    def __rpow__(self, value):
+        return self.clone(pow(value, self._value))
+
+    def __floordiv__(self, value):
+        return self.clone(self._value // value)
+
+    def __rfloordiv__(self, value):
+        return self.clone(value // self._value)
+
+    def __truediv__(self, value):
+        return Real(self._value / value)
+
+    def __rtruediv__(self, value):
+        return Real(value / self._value)
+
+    def __divmod__(self, value):
+        return self.clone(divmod(self._value, value))
+
+    def __rdivmod__(self, value):
+        return self.clone(divmod(value, self._value))
+
+    __hash__ = base.SimpleAsn1Type.__hash__
+
+    def __int__(self):
+        return int(self._value)
+
+    def __float__(self):
+        return float(self._value)
+
+    def __abs__(self):
+        return self.clone(abs(self._value))
+
+    def __index__(self):
+        return int(self._value)
+
+    def __pos__(self):
+        return self.clone(+self._value)
+
+    def __neg__(self):
+        return self.clone(-self._value)
+
+    def __invert__(self):
+        return self.clone(~self._value)
+
+    def __round__(self, n=0):
+        r = round(self._value, n)
+        if n:
+            return self.clone(r)
+        else:
+            return r
+
+    def __floor__(self):
+        return math.floor(self._value)
+
+    def __ceil__(self):
+        return math.ceil(self._value)
+
+    def __trunc__(self):
+        return self.clone(math.trunc(self._value))
+
+    def __lt__(self, value):
+        return self._value < value
+
+    def __le__(self, value):
+        return self._value <= value
+
+    def __eq__(self, value):
+        return self._value == value
+
+    def __ne__(self, value):
+        return self._value != value
+
+    def __gt__(self, value):
+        return self._value > value
+
+    def __ge__(self, value):
+        return self._value >= value
+
+    def prettyIn(self, value):
+        try:
+            return int(value)
+
+        except ValueError:
+            try:
+                return self.namedValues[value]
+
+            except KeyError as exc:
+                raise error.PyAsn1Error(
+                    'Can\'t coerce %r into integer: %s' % (value, exc)
+                )
+
+    def prettyOut(self, value):
+        try:
+            return str(self.namedValues[value])
+
+        except KeyError:
+            return str(value)
+
+    # backward compatibility
+
+    def getNamedValues(self):
+        return self.namedValues
+
+
+class Boolean(Integer):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`int` objects.
+
+    Keyword Args
+    ------------
+    value: :class:`int`, :class:`str` or |ASN.1| object
+        Python :class:`int` or :class:`str` literal or |ASN.1| class
+        instance. If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s).Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
+        Object representing non-default symbolic aliases for numbers
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class RoundResult(Boolean):
+            '''
+            ASN.1 specification:
+
+            RoundResult ::= BOOLEAN
+
+            ok RoundResult ::= TRUE
+            ko RoundResult ::= FALSE
+            '''
+        ok = RoundResult(True)
+        ko = RoundResult(False)
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01),
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = Integer.subtypeSpec + constraint.SingleValueConstraint(0, 1)
+
+    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
+    #: representing symbolic aliases for numbers
+    namedValues = namedval.NamedValues(('False', 0), ('True', 1))
+
+    # Optimization for faster codec lookup
+    typeId = Integer.getTypeId()
+
+
+class SizedInteger(int):
+    bitLength = leadingZeroBits = None
+
+    def setBitLength(self, bitLength):
+        self.bitLength = bitLength
+        self.leadingZeroBits = max(bitLength - self.bit_length(), 0)
+        return self
+
+    def __len__(self):
+        if self.bitLength is None:
+            self.setBitLength(self.bit_length())
+
+        return self.bitLength
+
+
+class BitString(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type both Python :class:`tuple` (as a tuple
+    of bits) and :class:`int` objects.
+
+    Keyword Args
+    ------------
+    value: :class:`int`, :class:`str` or |ASN.1| object
+        Python :class:`int` or :class:`str` literal representing binary
+        or hexadecimal number or sequence of integer bits or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
+        Object representing non-default symbolic aliases for numbers
+
+    binValue: :py:class:`str`
+        Binary string initializer to use instead of the *value*.
+        Example: '10110011'.
+
+    hexValue: :py:class:`str`
+        Hexadecimal string initializer to use instead of the *value*.
+        Example: 'DEADBEEF'.
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class Rights(BitString):
+            '''
+            ASN.1 specification:
+
+            Rights ::= BIT STRING { user-read(0), user-write(1),
+                                    group-read(2), group-write(3),
+                                    other-read(4), other-write(5) }
+
+            group1 Rights ::= { group-read, group-write }
+            group2 Rights ::= '0011'B
+            group3 Rights ::= '3'H
+            '''
+            namedValues = NamedValues(
+                ('user-read', 0), ('user-write', 1),
+                ('group-read', 2), ('group-write', 3),
+                ('other-read', 4), ('other-write', 5)
+            )
+
+        group1 = Rights(('group-read', 'group-write'))
+        group2 = Rights('0011')
+        group3 = Rights(0x3)
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
+    #: representing symbolic aliases for numbers
+    namedValues = namedval.NamedValues()
+
+    # Optimization for faster codec lookup
+    typeId = base.SimpleAsn1Type.getTypeId()
+
+    defaultBinValue = defaultHexValue = noValue
+
+    def __init__(self, value=noValue, **kwargs):
+        if value is noValue:
+            if kwargs:
+                try:
+                    value = self.fromBinaryString(kwargs.pop('binValue'), internalFormat=True)
+
+                except KeyError:
+                    pass
+
+                try:
+                    value = self.fromHexString(kwargs.pop('hexValue'), internalFormat=True)
+
+                except KeyError:
+                    pass
+
+        if value is noValue:
+            if self.defaultBinValue is not noValue:
+                value = self.fromBinaryString(self.defaultBinValue, internalFormat=True)
+
+            elif self.defaultHexValue is not noValue:
+                value = self.fromHexString(self.defaultHexValue, internalFormat=True)
+
+        if 'namedValues' not in kwargs:
+            kwargs['namedValues'] = self.namedValues
+
+        base.SimpleAsn1Type.__init__(self, value, **kwargs)
+
+    def __str__(self):
+        return self.asBinary()
+
+    def __eq__(self, other):
+        other = self.prettyIn(other)
+        return self is other or self._value == other and len(self._value) == len(other)
+
+    def __ne__(self, other):
+        other = self.prettyIn(other)
+        return self._value != other or len(self._value) != len(other)
+
+    def __lt__(self, other):
+        other = self.prettyIn(other)
+        return len(self._value) < len(other) or len(self._value) == len(other) and self._value < other
+
+    def __le__(self, other):
+        other = self.prettyIn(other)
+        return len(self._value) <= len(other) or len(self._value) == len(other) and self._value <= other
+
+    def __gt__(self, other):
+        other = self.prettyIn(other)
+        return len(self._value) > len(other) or len(self._value) == len(other) and self._value > other
+
+    def __ge__(self, other):
+        other = self.prettyIn(other)
+        return len(self._value) >= len(other) or len(self._value) == len(other) and self._value >= other
+
+    # Immutable sequence object protocol
+
+    def __len__(self):
+        return len(self._value)
+
+    def __getitem__(self, i):
+        if i.__class__ is slice:
+            return self.clone([self[x] for x in range(*i.indices(len(self)))])
+        else:
+            length = len(self._value) - 1
+            if i > length or i < 0:
+                raise IndexError('bit index out of range')
+            return (self._value >> (length - i)) & 1
+
+    def __iter__(self):
+        length = len(self._value)
+        while length:
+            length -= 1
+            yield (self._value >> length) & 1
+
+    def __reversed__(self):
+        return reversed(tuple(self))
+
+    # arithmetic operators
+
+    def __add__(self, value):
+        value = self.prettyIn(value)
+        return self.clone(SizedInteger(self._value << len(value) | value).setBitLength(len(self._value) + len(value)))
+
+    def __radd__(self, value):
+        value = self.prettyIn(value)
+        return self.clone(SizedInteger(value << len(self._value) | self._value).setBitLength(len(self._value) + len(value)))
+
+    def __mul__(self, value):
+        bitString = self._value
+        while value > 1:
+            bitString <<= len(self._value)
+            bitString |= self._value
+            value -= 1
+        return self.clone(bitString)
+
+    def __rmul__(self, value):
+        return self * value
+
+    def __lshift__(self, count):
+        return self.clone(SizedInteger(self._value << count).setBitLength(len(self._value) + count))
+
+    def __rshift__(self, count):
+        return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count)))
+
+    def __int__(self):
+        return int(self._value)
+
+    def __float__(self):
+        return float(self._value)
+
+    def asNumbers(self):
+        """Get |ASN.1| value as a sequence of 8-bit integers.
+
+        If |ASN.1| object length is not a multiple of 8, result
+        will be left-padded with zeros.
+        """
+        return tuple(self.asOctets())
+
+    def asOctets(self):
+        """Get |ASN.1| value as a sequence of octets.
+
+        If |ASN.1| object length is not a multiple of 8, result
+        will be left-padded with zeros.
+        """
+        return integer.to_bytes(self._value, length=len(self))
+
+    def asInteger(self):
+        """Get |ASN.1| value as a single integer value.
+        """
+        return self._value
+
+    def asBinary(self):
+        """Get |ASN.1| value as a text string of bits.
+        """
+        binString = bin(self._value)[2:]
+        return '0' * (len(self._value) - len(binString)) + binString
+
+    @classmethod
+    def fromHexString(cls, value, internalFormat=False, prepend=None):
+        """Create a |ASN.1| object initialized from the hex string.
+
+        Parameters
+        ----------
+        value: :class:`str`
+            Text string like 'DEADBEEF'
+        """
+        try:
+            value = SizedInteger(value, 16).setBitLength(len(value) * 4)
+
+        except ValueError as exc:
+            raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, exc))
+
+        if prepend is not None:
+            value = SizedInteger(
+                (SizedInteger(prepend) << len(value)) | value
+            ).setBitLength(len(prepend) + len(value))
+
+        if not internalFormat:
+            value = cls(value)
+
+        return value
+
+    @classmethod
+    def fromBinaryString(cls, value, internalFormat=False, prepend=None):
+        """Create a |ASN.1| object initialized from a string of '0' and '1'.
+
+        Parameters
+        ----------
+        value: :class:`str`
+            Text string like '1010111'
+        """
+        try:
+            value = SizedInteger(value or '0', 2).setBitLength(len(value))
+
+        except ValueError as exc:
+            raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, exc))
+
+        if prepend is not None:
+            value = SizedInteger(
+                (SizedInteger(prepend) << len(value)) | value
+            ).setBitLength(len(prepend) + len(value))
+
+        if not internalFormat:
+            value = cls(value)
+
+        return value
+
+    @classmethod
+    def fromOctetString(cls, value, internalFormat=False, prepend=None, padding=0):
+        """Create a |ASN.1| object initialized from a string.
+
+        Parameters
+        ----------
+        value: :class:`bytes`
+            Text string like b'\\\\x01\\\\xff'
+        """
+        value = SizedInteger(int.from_bytes(bytes(value), 'big') >> padding).setBitLength(len(value) * 8 - padding)
+
+        if prepend is not None:
+            value = SizedInteger(
+                (SizedInteger(prepend) << len(value)) | value
+            ).setBitLength(len(prepend) + len(value))
+
+        if not internalFormat:
+            value = cls(value)
+
+        return value
+
+    def prettyIn(self, value):
+        if isinstance(value, SizedInteger):
+            return value
+        elif isinstance(value, str):
+            if not value:
+                return SizedInteger(0).setBitLength(0)
+
+            elif value[0] == '\'':  # "'1011'B" -- ASN.1 schema representation (deprecated)
+                if value[-2:] == '\'B':
+                    return self.fromBinaryString(value[1:-2], internalFormat=True)
+                elif value[-2:] == '\'H':
+                    return self.fromHexString(value[1:-2], internalFormat=True)
+                else:
+                    raise error.PyAsn1Error(
+                        'Bad BIT STRING value notation %s' % (value,)
+                    )
+
+            elif self.namedValues and not value.isdigit():  # named bits like 'Urgent, Active'
+                names = [x.strip() for x in value.split(',')]
+
+                try:
+
+                    bitPositions = [self.namedValues[name] for name in names]
+
+                except KeyError:
+                    raise error.PyAsn1Error('unknown bit name(s) in %r' % (names,))
+
+                rightmostPosition = max(bitPositions)
+
+                number = 0
+                for bitPosition in bitPositions:
+                    number |= 1 << (rightmostPosition - bitPosition)
+
+                return SizedInteger(number).setBitLength(rightmostPosition + 1)
+
+            elif value.startswith('0x'):
+                return self.fromHexString(value[2:], internalFormat=True)
+
+            elif value.startswith('0b'):
+                return self.fromBinaryString(value[2:], internalFormat=True)
+
+            else:  # assume plain binary string like '1011'
+                return self.fromBinaryString(value, internalFormat=True)
+
+        elif isinstance(value, (tuple, list)):
+            return self.fromBinaryString(''.join([b and '1' or '0' for b in value]), internalFormat=True)
+
+        elif isinstance(value, BitString):
+            return SizedInteger(value).setBitLength(len(value))
+
+        elif isinstance(value, int):
+            return SizedInteger(value)
+
+        else:
+            raise error.PyAsn1Error(
+                'Bad BitString initializer type \'%s\'' % (value,)
+            )
+
+
+class OctetString(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type :class:`bytes`.
+    When used in Unicode context, |ASN.1| type
+    assumes "|encoding|" serialisation.
+
+    Keyword Args
+    ------------
+    value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
+        :class:`bytes`, alternatively :class:`str`
+        representing character string to be serialised into octets
+        (note `encoding` parameter) or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    encoding: :py:class:`str`
+        Unicode codec ID to encode/decode
+        :class:`str` the payload when |ASN.1| object is used
+        in text string context.
+
+    binValue: :py:class:`str`
+        Binary string initializer to use instead of the *value*.
+        Example: '10110011'.
+
+    hexValue: :py:class:`str`
+        Hexadecimal string initializer to use instead of the *value*.
+        Example: 'DEADBEEF'.
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class Icon(OctetString):
+            '''
+            ASN.1 specification:
+
+            Icon ::= OCTET STRING
+
+            icon1 Icon ::= '001100010011001000110011'B
+            icon2 Icon ::= '313233'H
+            '''
+        icon1 = Icon.fromBinaryString('001100010011001000110011')
+        icon2 = Icon.fromHexString('313233')
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Optimization for faster codec lookup
+    typeId = base.SimpleAsn1Type.getTypeId()
+
+    defaultBinValue = defaultHexValue = noValue
+    encoding = 'iso-8859-1'
+
+    def __init__(self, value=noValue, **kwargs):
+        if kwargs:
+            if value is noValue:
+                try:
+                    value = self.fromBinaryString(kwargs.pop('binValue'))
+
+                except KeyError:
+                    pass
+
+                try:
+                    value = self.fromHexString(kwargs.pop('hexValue'))
+
+                except KeyError:
+                    pass
+
+        if value is noValue:
+            if self.defaultBinValue is not noValue:
+                value = self.fromBinaryString(self.defaultBinValue)
+
+            elif self.defaultHexValue is not noValue:
+                value = self.fromHexString(self.defaultHexValue)
+
+        if 'encoding' not in kwargs:
+            kwargs['encoding'] = self.encoding
+
+        base.SimpleAsn1Type.__init__(self, value, **kwargs)
+
+    def prettyIn(self, value):
+        if isinstance(value, bytes):
+            return value
+
+        elif isinstance(value, str):
+            try:
+                return value.encode(self.encoding)
+
+            except UnicodeEncodeError as exc:
+                raise error.PyAsn1UnicodeEncodeError(
+                    "Can't encode string '%s' with '%s' "
+                    "codec" % (value, self.encoding), exc
+                )
+        elif isinstance(value, OctetString):  # a shortcut, bytes() would work the same way
+            return value.asOctets()
+
+        elif isinstance(value, base.SimpleAsn1Type):  # this mostly targets Integer objects
+            return self.prettyIn(str(value))
+
+        elif isinstance(value, (tuple, list)):
+            return self.prettyIn(bytes(value))
+
+        else:
+            return bytes(value)
+
+    def __str__(self):
+        try:
+            return self._value.decode(self.encoding)
+
+        except UnicodeDecodeError as exc:
+            raise error.PyAsn1UnicodeDecodeError(
+                "Can't decode string '%s' with '%s' codec at "
+                "'%s'" % (self._value, self.encoding,
+                            self.__class__.__name__), exc
+            )
+
+    def __bytes__(self):
+        return bytes(self._value)
+
+    def asOctets(self):
+        return bytes(self._value)
+
+    def asNumbers(self):
+        return tuple(self._value)
+
+    #
+    # Normally, `.prettyPrint()` is called from `__str__()`. Historically,
+    # OctetString.prettyPrint() used to return hexified payload
+    # representation in cases when non-printable content is present. At the
+    # same time `str()` used to produce either octet-stream (Py2) or
+    # text (Py3) representations.
+    #
+    # Therefore `OctetString.__str__()` -> `.prettyPrint()` call chain is
+    # reversed to preserve the original behaviour.
+    #
+    # Eventually we should deprecate `.prettyPrint()` / `.prettyOut()` harness
+    # and end up with just `__str__()` producing hexified representation while
+    # both text and octet-stream representation should only be requested via
+    # the `.asOctets()` method.
+    #
+    # Note: ASN.1 OCTET STRING is never mean to contain text!
+    #
+
+    def prettyOut(self, value):
+        return value
+
+    def prettyPrint(self, scope=0):
+        # first see if subclass has its own .prettyOut()
+        value = self.prettyOut(self._value)
+
+        if value is not self._value:
+            return value
+
+        numbers = self.asNumbers()
+
+        for x in numbers:
+            # hexify if needed
+            if x < 32 or x > 126:
+                return '0x' + ''.join(('%.2x' % x for x in numbers))
+        else:
+            # this prevents infinite recursion
+            return OctetString.__str__(self)
+
+    @staticmethod
+    def fromBinaryString(value):
+        """Create a |ASN.1| object initialized from a string of '0' and '1'.
+
+        Parameters
+        ----------
+        value: :class:`str`
+            Text string like '1010111'
+        """
+        bitNo = 8
+        byte = 0
+        r = []
+        for v in value:
+            if bitNo:
+                bitNo -= 1
+            else:
+                bitNo = 7
+                r.append(byte)
+                byte = 0
+            if v in ('0', '1'):
+                v = int(v)
+            else:
+                raise error.PyAsn1Error(
+                    'Non-binary OCTET STRING initializer %s' % (v,)
+                )
+            byte |= v << bitNo
+
+        r.append(byte)
+
+        return bytes(r)
+
+    @staticmethod
+    def fromHexString(value):
+        """Create a |ASN.1| object initialized from the hex string.
+
+        Parameters
+        ----------
+        value: :class:`str`
+            Text string like 'DEADBEEF'
+        """
+        r = []
+        p = []
+        for v in value:
+            if p:
+                r.append(int(p + v, 16))
+                p = None
+            else:
+                p = v
+        if p:
+            r.append(int(p + '0', 16))
+
+        return bytes(r)
+
+    # Immutable sequence object protocol
+
+    def __len__(self):
+        return len(self._value)
+
+    def __getitem__(self, i):
+        if i.__class__ is slice:
+            return self.clone(self._value[i])
+        else:
+            return self._value[i]
+
+    def __iter__(self):
+        return iter(self._value)
+
+    def __contains__(self, value):
+        return value in self._value
+
+    def __add__(self, value):
+        return self.clone(self._value + self.prettyIn(value))
+
+    def __radd__(self, value):
+        return self.clone(self.prettyIn(value) + self._value)
+
+    def __mul__(self, value):
+        return self.clone(self._value * value)
+
+    def __rmul__(self, value):
+        return self * value
+
+    def __int__(self):
+        return int(self._value)
+
+    def __float__(self):
+        return float(self._value)
+
+    def __reversed__(self):
+        return reversed(self._value)
+
+
+class Null(OctetString):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`str` objects
+    (always empty).
+
+    Keyword Args
+    ------------
+    value: :class:`str` or |ASN.1| object
+        Python empty :class:`str` literal or any object that evaluates to :obj:`False`
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class Ack(Null):
+            '''
+            ASN.1 specification:
+
+            Ack ::= NULL
+            '''
+        ack = Ack('')
+    """
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05)
+    )
+    subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(b'')
+
+    # Optimization for faster codec lookup
+    typeId = OctetString.getTypeId()
+
+    def prettyIn(self, value):
+        if value:
+            return value
+
+        return b''
+
+
+class ObjectIdentifier(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`tuple` objects
+    (tuple of non-negative integers).
+
+    Keyword Args
+    ------------
+    value: :class:`tuple`, :class:`str` or |ASN.1| object
+        Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class ID(ObjectIdentifier):
+            '''
+            ASN.1 specification:
+
+            ID ::= OBJECT IDENTIFIER
+
+            id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) }
+            id-bp ID ::= { id-edims 11 }
+            '''
+        id_edims = ID('2.6.7')
+        id_bp = id_edims + (11,)
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Optimization for faster codec lookup
+    typeId = base.SimpleAsn1Type.getTypeId()
+
+    def __add__(self, other):
+        return self.clone(self._value + other)
+
+    def __radd__(self, other):
+        return self.clone(other + self._value)
+
+    def asTuple(self):
+        return self._value
+
+    # Sequence object protocol
+
+    def __len__(self):
+        return len(self._value)
+
+    def __getitem__(self, i):
+        if i.__class__ is slice:
+            return self.clone(self._value[i])
+        else:
+            return self._value[i]
+
+    def __iter__(self):
+        return iter(self._value)
+
+    def __contains__(self, value):
+        return value in self._value
+
+    def index(self, suboid):
+        return self._value.index(suboid)
+
+    def isPrefixOf(self, other):
+        """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object.
+
+        Parameters
+        ----------
+        other: |ASN.1| object
+            |ASN.1| object
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
+            or :obj:`False` otherwise.
+        """
+        l = len(self)
+        if l <= len(other):
+            if self._value[:l] == other[:l]:
+                return True
+        return False
+
+    def prettyIn(self, value):
+        if isinstance(value, ObjectIdentifier):
+            return tuple(value)
+        elif isinstance(value, str):
+            if '-' in value:
+                raise error.PyAsn1Error(
+                    # sys.exc_info in case prettyIn was called while handling an exception
+                    'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
+                )
+            try:
+                return tuple([int(subOid) for subOid in value.split('.') if subOid])
+            except ValueError as exc:
+                raise error.PyAsn1Error(
+                    'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc)
+                )
+
+        try:
+            tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
+
+        except (ValueError, TypeError) as exc:
+            raise error.PyAsn1Error(
+                'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc)
+            )
+
+        if len(tupleOfInts) == len(value):
+            return tupleOfInts
+
+        raise error.PyAsn1Error('Malformed Object ID %s at %s' % (value, self.__class__.__name__))
+
+    def prettyOut(self, value):
+        return '.'.join([str(x) for x in value])
+
+
+class RelativeOID(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`tuple` objects
+    (tuple of non-negative integers).
+    Keyword Args
+    ------------
+    value: :class:`tuple`, :class:`str` or |ASN.1| object
+        Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+    Examples
+    --------
+    .. code-block:: python
+        class RelOID(RelativeOID):
+            '''
+            ASN.1 specification:
+            id-pad-null RELATIVE-OID ::= { 0 }
+            id-pad-once RELATIVE-OID ::= { 5 6 }
+            id-pad-twice RELATIVE-OID ::= { 5 6 7 }
+            '''
+        id_pad_null = RelOID('0')
+        id_pad_once = RelOID('5.6')
+        id_pad_twice = id_pad_once + (7,)
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0d)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Optimization for faster codec lookup
+    typeId = base.SimpleAsn1Type.getTypeId()
+
+    def __add__(self, other):
+        return self.clone(self._value + other)
+
+    def __radd__(self, other):
+        return self.clone(other + self._value)
+
+    def asTuple(self):
+        return self._value
+
+    # Sequence object protocol
+
+    def __len__(self):
+        return len(self._value)
+
+    def __getitem__(self, i):
+        if i.__class__ is slice:
+            return self.clone(self._value[i])
+        else:
+            return self._value[i]
+
+    def __iter__(self):
+        return iter(self._value)
+
+    def __contains__(self, value):
+        return value in self._value
+
+    def index(self, suboid):
+        return self._value.index(suboid)
+
+    def isPrefixOf(self, other):
+        """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object.
+        Parameters
+        ----------
+        other: |ASN.1| object
+            |ASN.1| object
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
+            or :obj:`False` otherwise.
+        """
+        l = len(self)
+        if l <= len(other):
+            if self._value[:l] == other[:l]:
+                return True
+        return False
+
+    def prettyIn(self, value):
+        if isinstance(value, RelativeOID):
+            return tuple(value)
+        elif isinstance(value, str):
+            if '-' in value:
+                raise error.PyAsn1Error(
+                    # sys.exc_info in case prettyIn was called while handling an exception
+                    'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])
+                )
+            try:
+                return tuple([int(subOid) for subOid in value.split('.') if subOid])
+            except ValueError as exc:
+                raise error.PyAsn1Error(
+                    'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc)
+                )
+
+        try:
+            tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0])
+
+        except (ValueError, TypeError) as exc:
+            raise error.PyAsn1Error(
+                'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc)
+            )
+
+        if len(tupleOfInts) == len(value):
+            return tupleOfInts
+
+        raise error.PyAsn1Error('Malformed RELATIVE-OID %s at %s' % (value, self.__class__.__name__))
+
+    def prettyOut(self, value):
+        return '.'.join([str(x) for x in value])
+
+
+class Real(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`float` objects.
+    Additionally, |ASN.1| objects behave like a :class:`tuple` in which case its
+    elements are mantissa, base and exponent.
+
+    Keyword Args
+    ------------
+    value: :class:`tuple`, :class:`float` or |ASN.1| object
+        Python sequence of :class:`int` (representing mantissa, base and
+        exponent) or :class:`float` instance or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class Pi(Real):
+            '''
+            ASN.1 specification:
+
+            Pi ::= REAL
+
+            pi Pi ::= { mantissa 314159, base 10, exponent -5 }
+
+            '''
+        pi = Pi((314159, 10, -5))
+    """
+    binEncBase = None  # binEncBase = 16 is recommended for large numbers
+
+    try:
+        _plusInf = float('inf')
+        _minusInf = float('-inf')
+        _inf = _plusInf, _minusInf
+
+    except ValueError:
+        # Infinity support is platform and Python dependent
+        _plusInf = _minusInf = None
+        _inf = ()
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Optimization for faster codec lookup
+    typeId = base.SimpleAsn1Type.getTypeId()
+
+    @staticmethod
+    def __normalizeBase10(value):
+        m, b, e = value
+        while m and m % 10 == 0:
+            m /= 10
+            e += 1
+        return m, b, e
+
+    def prettyIn(self, value):
+        if isinstance(value, tuple) and len(value) == 3:
+            if (not isinstance(value[0], (int, float)) or
+                    not isinstance(value[1], int) or
+                    not isinstance(value[2], int)):
+                raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
+            if (isinstance(value[0], float) and
+                    self._inf and value[0] in self._inf):
+                return value[0]
+            if value[1] not in (2, 10):
+                raise error.PyAsn1Error(
+                    'Prohibited base for Real value: %s' % (value[1],)
+                )
+            if value[1] == 10:
+                value = self.__normalizeBase10(value)
+            return value
+        elif isinstance(value, int):
+            return self.__normalizeBase10((value, 10, 0))
+        elif isinstance(value, float) or isinstance(value, str):
+            if isinstance(value, str):
+                try:
+                    value = float(value)
+                except ValueError:
+                    raise error.PyAsn1Error(
+                        'Bad real value syntax: %s' % (value,)
+                    )
+            if self._inf and value in self._inf:
+                return value
+            else:
+                e = 0
+                while int(value) != value:
+                    value *= 10
+                    e -= 1
+                return self.__normalizeBase10((int(value), 10, e))
+        elif isinstance(value, Real):
+            return tuple(value)
+        raise error.PyAsn1Error(
+            'Bad real value syntax: %s' % (value,)
+        )
+
+    def prettyPrint(self, scope=0):
+        try:
+            return self.prettyOut(float(self))
+
+        except OverflowError:
+            return '<overflow>'
+
+    @property
+    def isPlusInf(self):
+        """Indicate PLUS-INFINITY object value
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`True` if calling object represents plus infinity
+            or :obj:`False` otherwise.
+
+        """
+        return self._value == self._plusInf
+
+    @property
+    def isMinusInf(self):
+        """Indicate MINUS-INFINITY object value
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`True` if calling object represents minus infinity
+            or :obj:`False` otherwise.
+        """
+        return self._value == self._minusInf
+
+    @property
+    def isInf(self):
+        return self._value in self._inf
+
+    def __add__(self, value):
+        return self.clone(float(self) + value)
+
+    def __radd__(self, value):
+        return self + value
+
+    def __mul__(self, value):
+        return self.clone(float(self) * value)
+
+    def __rmul__(self, value):
+        return self * value
+
+    def __sub__(self, value):
+        return self.clone(float(self) - value)
+
+    def __rsub__(self, value):
+        return self.clone(value - float(self))
+
+    def __mod__(self, value):
+        return self.clone(float(self) % value)
+
+    def __rmod__(self, value):
+        return self.clone(value % float(self))
+
+    def __pow__(self, value, modulo=None):
+        return self.clone(pow(float(self), value, modulo))
+
+    def __rpow__(self, value):
+        return self.clone(pow(value, float(self)))
+
+    def __truediv__(self, value):
+        return self.clone(float(self) / value)
+
+    def __rtruediv__(self, value):
+        return self.clone(value / float(self))
+
+    def __divmod__(self, value):
+        return self.clone(float(self) // value)
+
+    def __rdivmod__(self, value):
+        return self.clone(value // float(self))
+
+    def __int__(self):
+        return int(float(self))
+
+    def __float__(self):
+        if self._value in self._inf:
+            return self._value
+        else:
+            return float(
+                self._value[0] * pow(self._value[1], self._value[2])
+            )
+
+    def __abs__(self):
+        return self.clone(abs(float(self)))
+
+    def __pos__(self):
+        return self.clone(+float(self))
+
+    def __neg__(self):
+        return self.clone(-float(self))
+
+    def __round__(self, n=0):
+        r = round(float(self), n)
+        if n:
+            return self.clone(r)
+        else:
+            return r
+
+    def __floor__(self):
+        return self.clone(math.floor(float(self)))
+
+    def __ceil__(self):
+        return self.clone(math.ceil(float(self)))
+
+    def __trunc__(self):
+        return self.clone(math.trunc(float(self)))
+
+    def __lt__(self, value):
+        return float(self) < value
+
+    def __le__(self, value):
+        return float(self) <= value
+
+    def __eq__(self, value):
+        return float(self) == value
+
+    def __ne__(self, value):
+        return float(self) != value
+
+    def __gt__(self, value):
+        return float(self) > value
+
+    def __ge__(self, value):
+        return float(self) >= value
+
+    def __bool__(self):
+        return bool(float(self))
+
+    __hash__ = base.SimpleAsn1Type.__hash__
+
+    def __getitem__(self, idx):
+        if self._value in self._inf:
+            raise error.PyAsn1Error('Invalid infinite value operation')
+        else:
+            return self._value[idx]
+
+    # compatibility stubs
+
+    def isPlusInfinity(self):
+        return self.isPlusInf
+
+    def isMinusInfinity(self):
+        return self.isMinusInf
+
+    def isInfinity(self):
+        return self.isInf
+
+
+class Enumerated(Integer):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python :class:`int` objects.
+
+    Keyword Args
+    ------------
+    value: :class:`int`, :class:`str` or |ASN.1| object
+        Python :class:`int` or :class:`str` literal or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    namedValues: :py:class:`~pyasn1.type.namedval.NamedValues`
+        Object representing non-default symbolic aliases for numbers
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class RadioButton(Enumerated):
+            '''
+            ASN.1 specification:
+
+            RadioButton ::= ENUMERATED { button1(0), button2(1),
+                                         button3(2) }
+
+            selected-by-default RadioButton ::= button1
+            '''
+            namedValues = NamedValues(
+                ('button1', 0), ('button2', 1),
+                ('button3', 2)
+            )
+
+        selected_by_default = RadioButton('button1')
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Optimization for faster codec lookup
+    typeId = Integer.getTypeId()
+
+    #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object
+    #: representing symbolic aliases for numbers
+    namedValues = namedval.NamedValues()
+
+
+# "Structured" ASN.1 types
+
+class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
+    its objects are mutable and duck-type Python :class:`list` objects.
+
+    Keyword Args
+    ------------
+    componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+        A pyasn1 object representing ASN.1 type allowed within |ASN.1| type
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type can only occur on explicit
+        `.isInconsistent` call.
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class LotteryDraw(SequenceOf):  #  SetOf is similar
+            '''
+            ASN.1 specification:
+
+            LotteryDraw ::= SEQUENCE OF INTEGER
+            '''
+            componentType = Integer()
+
+        lotteryDraw = LotteryDraw()
+        lotteryDraw.extend([123, 456, 789])
+    """
+    def __init__(self, *args, **kwargs):
+        # support positional params for backward compatibility
+        if args:
+            for key, value in zip(('componentType', 'tagSet',
+                                   'subtypeSpec'), args):
+                if key in kwargs:
+                    raise error.PyAsn1Error('Conflicting positional and keyword params!')
+                kwargs['componentType'] = value
+
+        self._componentValues = noValue
+
+        base.ConstructedAsn1Type.__init__(self, **kwargs)
+
+    # Python list protocol
+
+    def __getitem__(self, idx):
+        try:
+            return self.getComponentByPosition(idx)
+
+        except error.PyAsn1Error as exc:
+            raise IndexError(exc)
+
+    def __setitem__(self, idx, value):
+        try:
+            self.setComponentByPosition(idx, value)
+
+        except error.PyAsn1Error as exc:
+            raise IndexError(exc)
+
+    def append(self, value):
+        if self._componentValues is noValue:
+            pos = 0
+
+        else:
+            pos = len(self._componentValues)
+
+        self[pos] = value
+
+    def count(self, value):
+        return list(self._componentValues.values()).count(value)
+
+    def extend(self, values):
+        for value in values:
+            self.append(value)
+
+        if self._componentValues is noValue:
+            self._componentValues = {}
+
+    def index(self, value, start=0, stop=None):
+        if stop is None:
+            stop = len(self)
+
+        indices, values = zip(*self._componentValues.items())
+
+        # TODO: remove when Py2.5 support is gone
+        values = list(values)
+
+        try:
+            return indices[values.index(value, start, stop)]
+
+        except error.PyAsn1Error as exc:
+            raise ValueError(exc)
+
+    def reverse(self):
+        self._componentValues.reverse()
+
+    def sort(self, key=None, reverse=False):
+        self._componentValues = dict(
+            enumerate(sorted(self._componentValues.values(),
+                             key=key, reverse=reverse)))
+
+    def __len__(self):
+        if self._componentValues is noValue or not self._componentValues:
+            return 0
+
+        return max(self._componentValues) + 1
+
+    def __iter__(self):
+        for idx in range(0, len(self)):
+            yield self.getComponentByPosition(idx)
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        for idx, componentValue in self._componentValues.items():
+            if componentValue is not noValue:
+                if isinstance(componentValue, base.ConstructedAsn1Type):
+                    myClone.setComponentByPosition(
+                        idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
+                    )
+                else:
+                    myClone.setComponentByPosition(idx, componentValue.clone())
+
+    def getComponentByPosition(self, idx, default=noValue, instantiate=True):
+        """Return |ASN.1| type component value by position.
+
+        Equivalent to Python sequence subscription operation (e.g. `[]`).
+
+        Parameters
+        ----------
+        idx : :class:`int`
+            Component index (zero-based). Must either refer to an existing
+            component or to N+1 component (if *componentType* is set). In the latter
+            case a new component type gets instantiated and appended to the |ASN.1|
+            sequence.
+
+        Keyword Args
+        ------------
+        default: :class:`object`
+            If set and requested component is a schema object, return the `default`
+            object instead of the requested component.
+
+        instantiate: :class:`bool`
+            If :obj:`True` (default), inner component will be automatically instantiated.
+            If :obj:`False` either existing component or the :class:`NoValue` object will be
+            returned.
+
+        Returns
+        -------
+        : :py:class:`~pyasn1.type.base.PyAsn1Item`
+            Instantiate |ASN.1| component type or return existing component value
+
+        Examples
+        --------
+
+        .. code-block:: python
+
+            # can also be SetOf
+            class MySequenceOf(SequenceOf):
+                componentType = OctetString()
+
+            s = MySequenceOf()
+
+            # returns component #0 with `.isValue` property False
+            s.getComponentByPosition(0)
+
+            # returns None
+            s.getComponentByPosition(0, default=None)
+
+            s.clear()
+
+            # returns noValue
+            s.getComponentByPosition(0, instantiate=False)
+
+            # sets component #0 to OctetString() ASN.1 schema
+            # object and returns it
+            s.getComponentByPosition(0, instantiate=True)
+
+            # sets component #0 to ASN.1 value object
+            s.setComponentByPosition(0, 'ABCD')
+
+            # returns OctetString('ABCD') value object
+            s.getComponentByPosition(0, instantiate=False)
+
+            s.clear()
+
+            # returns noValue
+            s.getComponentByPosition(0, instantiate=False)
+        """
+        if isinstance(idx, slice):
+            indices = tuple(range(len(self)))
+            return [self.getComponentByPosition(subidx, default, instantiate)
+                    for subidx in indices[idx]]
+
+        if idx < 0:
+            idx = len(self) + idx
+            if idx < 0:
+                raise error.PyAsn1Error(
+                    'SequenceOf/SetOf index is out of range')
+
+        try:
+            componentValue = self._componentValues[idx]
+
+        except (KeyError, error.PyAsn1Error):
+            if not instantiate:
+                return default
+
+            self.setComponentByPosition(idx)
+
+            componentValue = self._componentValues[idx]
+
+        if default is noValue or componentValue.isValue:
+            return componentValue
+        else:
+            return default
+
+    def setComponentByPosition(self, idx, value=noValue,
+                               verifyConstraints=True,
+                               matchTags=True,
+                               matchConstraints=True):
+        """Assign |ASN.1| type component by position.
+
+        Equivalent to Python sequence item assignment operation (e.g. `[]`)
+        or list.append() (when idx == len(self)).
+
+        Parameters
+        ----------
+        idx: :class:`int`
+            Component index (zero-based). Must either refer to existing
+            component or to N+1 component. In the latter case a new component
+            type gets instantiated (if *componentType* is set, or given ASN.1
+            object is taken otherwise) and appended to the |ASN.1| sequence.
+
+        Keyword Args
+        ------------
+        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+            A Python value to initialize |ASN.1| component with (if *componentType* is set)
+            or ASN.1 value object to assign to |ASN.1| component.
+            If `value` is not given, schema object will be set as a component.
+
+        verifyConstraints: :class:`bool`
+             If :obj:`False`, skip constraints validation
+
+        matchTags: :class:`bool`
+             If :obj:`False`, skip component tags matching
+
+        matchConstraints: :class:`bool`
+             If :obj:`False`, skip component constraints matching
+
+        Returns
+        -------
+        self
+
+        Raises
+        ------
+        ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+            On constraint violation or bad initializer
+        IndexError
+            When idx > len(self)
+        """
+        if isinstance(idx, slice):
+            indices = tuple(range(len(self)))
+            startIdx = indices and indices[idx][0] or 0
+            for subIdx, subValue in enumerate(value):
+                self.setComponentByPosition(
+                    startIdx + subIdx, subValue, verifyConstraints,
+                    matchTags, matchConstraints)
+            return self
+
+        if idx < 0:
+            idx = len(self) + idx
+            if idx < 0:
+                raise error.PyAsn1Error(
+                    'SequenceOf/SetOf index is out of range')
+
+        componentType = self.componentType
+
+        if self._componentValues is noValue:
+            componentValues = {}
+
+        else:
+            componentValues = self._componentValues
+
+        currentValue = componentValues.get(idx, noValue)
+
+        if value is noValue:
+            if componentType is not None:
+                value = componentType.clone()
+
+            elif currentValue is noValue:
+                raise error.PyAsn1Error('Component type not defined')
+
+        elif not isinstance(value, base.Asn1Item):
+            if (componentType is not None and
+                    isinstance(componentType, base.SimpleAsn1Type)):
+                value = componentType.clone(value=value)
+
+            elif (currentValue is not noValue and
+                    isinstance(currentValue, base.SimpleAsn1Type)):
+                value = currentValue.clone(value=value)
+
+            else:
+                raise error.PyAsn1Error(
+                    'Non-ASN.1 value %r and undefined component'
+                    ' type at %r' % (value, self))
+
+        elif componentType is not None and (matchTags or matchConstraints):
+            subtypeChecker = (
+                    self.strictConstraints and
+                    componentType.isSameTypeWith or
+                    componentType.isSuperTypeOf)
+
+            if not subtypeChecker(value, verifyConstraints and matchTags,
+                                  verifyConstraints and matchConstraints):
+                # TODO: we should wrap componentType with UnnamedType to carry
+                # additional properties associated with componentType
+                if componentType.typeId != Any.typeId:
+                    raise error.PyAsn1Error(
+                        'Component value is tag-incompatible: %r vs '
+                        '%r' % (value, componentType))
+
+        componentValues[idx] = value
+
+        self._componentValues = componentValues
+
+        return self
+
+    @property
+    def componentTagMap(self):
+        if self.componentType is not None:
+            return self.componentType.tagMap
+
+    @property
+    def components(self):
+        return [self._componentValues[idx]
+                for idx in sorted(self._componentValues)]
+
+    def clear(self):
+        """Remove all components and become an empty |ASN.1| value object.
+
+        Has the same effect on |ASN.1| object as it does on :class:`list`
+        built-in.
+        """
+        self._componentValues = {}
+        return self
+
+    def reset(self):
+        """Remove all components and become a |ASN.1| schema object.
+
+        See :meth:`isValue` property for more information on the
+        distinction between value and schema objects.
+        """
+        self._componentValues = noValue
+        return self
+
+    def prettyPrint(self, scope=0):
+        scope += 1
+        representation = self.__class__.__name__ + ':\n'
+
+        if not self.isValue:
+            return representation
+
+        for idx, componentValue in enumerate(self):
+            representation += ' ' * scope
+            if (componentValue is noValue and
+                    self.componentType is not None):
+                representation += '<empty>'
+            else:
+                representation += componentValue.prettyPrint(scope)
+
+        return representation
+
+    def prettyPrintType(self, scope=0):
+        scope += 1
+        representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
+        if self.componentType is not None:
+            representation += ' ' * scope
+            representation += self.componentType.prettyPrintType(scope)
+        return representation + '\n' + ' ' * (scope - 1) + '}'
+
+
+    @property
+    def isValue(self):
+        """Indicate that |ASN.1| object represents ASN.1 value.
+
+        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
+
+        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
+        this object can also be used like a Python built-in object
+        (e.g. :class:`int`, :class:`str`, :class:`dict` etc.).
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`False` if object represents just ASN.1 schema.
+            :obj:`True` if object represents ASN.1 schema and can be used as a normal value.
+
+        Note
+        ----
+        There is an important distinction between PyASN1 schema and value objects.
+        The PyASN1 schema objects can only participate in ASN.1 schema-related
+        operations (e.g. defining or testing the structure of the data). Most
+        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
+        encoding/decoding serialised ASN.1 contents.
+
+        The PyASN1 value objects can **additionally** participate in many operations
+        involving regular Python objects (e.g. arithmetic, comprehension etc).
+        """
+        if self._componentValues is noValue:
+            return False
+
+        if len(self._componentValues) != len(self):
+            return False
+
+        for componentValue in self._componentValues.values():
+            if componentValue is noValue or not componentValue.isValue:
+                return False
+
+        return True
+
+    @property
+    def isInconsistent(self):
+        """Run necessary checks to ensure |ASN.1| object consistency.
+
+        Default action is to verify |ASN.1| object against constraints imposed
+        by `subtypeSpec`.
+
+        Raises
+        ------
+        :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
+        """
+        if self.componentType is noValue or not self.subtypeSpec:
+            return False
+
+        if self._componentValues is noValue:
+            return True
+
+        mapping = {}
+
+        for idx, value in self._componentValues.items():
+            # Absent fields are not in the mapping
+            if value is noValue:
+                continue
+
+            mapping[idx] = value
+
+        try:
+            # Represent SequenceOf/SetOf as a bare dict to constraints chain
+            self.subtypeSpec(mapping)
+
+        except error.PyAsn1Error as exc:
+            return exc
+
+        return False
+
+class SequenceOf(SequenceOfAndSetOfBase):
+    __doc__ = SequenceOfAndSetOfBase.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
+    )
+
+    #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+    #: object representing ASN.1 type allowed within |ASN.1| type
+    componentType = None
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Disambiguation ASN.1 types identification
+    typeId = SequenceOfAndSetOfBase.getTypeId()
+
+
+class SetOf(SequenceOfAndSetOfBase):
+    __doc__ = SequenceOfAndSetOfBase.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
+    )
+
+    #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+    #: object representing ASN.1 type allowed within |ASN.1| type
+    componentType = None
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Disambiguation ASN.1 types identification
+    typeId = SequenceOfAndSetOfBase.getTypeId()
+
+
+class SequenceAndSetBase(base.ConstructedAsn1Type):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
+    its objects are mutable and duck-type Python :class:`dict` objects.
+
+    Keyword Args
+    ------------
+    componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
+        Object holding named ASN.1 types allowed within this collection
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s).  Constraints
+        verification for |ASN.1| type can only occur on explicit
+        `.isInconsistent` call.
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class Description(Sequence):  #  Set is similar
+            '''
+            ASN.1 specification:
+
+            Description ::= SEQUENCE {
+                surname    IA5String,
+                first-name IA5String OPTIONAL,
+                age        INTEGER DEFAULT 40
+            }
+            '''
+            componentType = NamedTypes(
+                NamedType('surname', IA5String()),
+                OptionalNamedType('first-name', IA5String()),
+                DefaultedNamedType('age', Integer(40))
+            )
+
+        descr = Description()
+        descr['surname'] = 'Smith'
+        descr['first-name'] = 'John'
+    """
+    #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes`
+    #: object representing named ASN.1 types allowed within |ASN.1| type
+    componentType = namedtype.NamedTypes()
+
+
+    class DynamicNames(object):
+        """Fields names/positions mapping for component-less objects"""
+        def __init__(self):
+            self._keyToIdxMap = {}
+            self._idxToKeyMap = {}
+
+        def __len__(self):
+            return len(self._keyToIdxMap)
+
+        def __contains__(self, item):
+            return item in self._keyToIdxMap or item in self._idxToKeyMap
+
+        def __iter__(self):
+            return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap)))
+
+        def __getitem__(self, item):
+            try:
+                return self._keyToIdxMap[item]
+
+            except KeyError:
+                return self._idxToKeyMap[item]
+
+        def getNameByPosition(self, idx):
+            try:
+                return self._idxToKeyMap[idx]
+
+            except KeyError:
+                raise error.PyAsn1Error('Type position out of range')
+
+        def getPositionByName(self, name):
+            try:
+                return self._keyToIdxMap[name]
+
+            except KeyError:
+                raise error.PyAsn1Error('Name %s not found' % (name,))
+
+        def addField(self, idx):
+            self._keyToIdxMap['field-%d' % idx] = idx
+            self._idxToKeyMap[idx] = 'field-%d' % idx
+
+
+    def __init__(self, **kwargs):
+        base.ConstructedAsn1Type.__init__(self, **kwargs)
+        self._componentTypeLen = len(self.componentType)
+        if self._componentTypeLen:
+            self._componentValues = []
+        else:
+            self._componentValues = noValue
+        self._dynamicNames = self._componentTypeLen or self.DynamicNames()
+
+    def __getitem__(self, idx):
+        if isinstance(idx, str):
+            try:
+                return self.getComponentByName(idx)
+
+            except error.PyAsn1Error as exc:
+                # duck-typing dict
+                raise KeyError(exc)
+
+        else:
+            try:
+                return self.getComponentByPosition(idx)
+
+            except error.PyAsn1Error as exc:
+                # duck-typing list
+                raise IndexError(exc)
+
+    def __setitem__(self, idx, value):
+        if isinstance(idx, str):
+            try:
+                self.setComponentByName(idx, value)
+
+            except error.PyAsn1Error as exc:
+                # duck-typing dict
+                raise KeyError(exc)
+
+        else:
+            try:
+                self.setComponentByPosition(idx, value)
+
+            except error.PyAsn1Error as exc:
+                # duck-typing list
+                raise IndexError(exc)
+
+    def __contains__(self, key):
+        if self._componentTypeLen:
+            return key in self.componentType
+        else:
+            return key in self._dynamicNames
+
+    def __len__(self):
+        return len(self._componentValues)
+
+    def __iter__(self):
+        return iter(self.componentType or self._dynamicNames)
+
+    # Python dict protocol
+
+    def values(self):
+        for idx in range(self._componentTypeLen or len(self._dynamicNames)):
+            yield self[idx]
+
+    def keys(self):
+        return iter(self)
+
+    def items(self):
+        for idx in range(self._componentTypeLen or len(self._dynamicNames)):
+            if self._componentTypeLen:
+                yield self.componentType[idx].name, self[idx]
+            else:
+                yield self._dynamicNames[idx], self[idx]
+
+    def update(self, *iterValue, **mappingValue):
+        for k, v in iterValue:
+            self[k] = v
+        for k in mappingValue:
+            self[k] = mappingValue[k]
+
+    def clear(self):
+        """Remove all components and become an empty |ASN.1| value object.
+
+        Has the same effect on |ASN.1| object as it does on :class:`dict`
+        built-in.
+        """
+        self._componentValues = []
+        self._dynamicNames = self.DynamicNames()
+        return self
+
+    def reset(self):
+        """Remove all components and become a |ASN.1| schema object.
+
+        See :meth:`isValue` property for more information on the
+        distinction between value and schema objects.
+        """
+        self._componentValues = noValue
+        self._dynamicNames = self.DynamicNames()
+        return self
+
+    @property
+    def components(self):
+        return self._componentValues
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        if self._componentValues is noValue:
+            return
+
+        for idx, componentValue in enumerate(self._componentValues):
+            if componentValue is not noValue:
+                if isinstance(componentValue, base.ConstructedAsn1Type):
+                    myClone.setComponentByPosition(
+                        idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
+                    )
+                else:
+                    myClone.setComponentByPosition(idx, componentValue.clone())
+
+    def getComponentByName(self, name, default=noValue, instantiate=True):
+        """Returns |ASN.1| type component by name.
+
+        Equivalent to Python :class:`dict` subscription operation (e.g. `[]`).
+
+        Parameters
+        ----------
+        name: :class:`str`
+            |ASN.1| type component name
+
+        Keyword Args
+        ------------
+        default: :class:`object`
+            If set and requested component is a schema object, return the `default`
+            object instead of the requested component.
+
+        instantiate: :class:`bool`
+            If :obj:`True` (default), inner component will be automatically
+            instantiated.
+            If :obj:`False` either existing component or the :class:`NoValue`
+            object will be returned.
+
+        Returns
+        -------
+        : :py:class:`~pyasn1.type.base.PyAsn1Item`
+            Instantiate |ASN.1| component type or return existing
+            component value
+        """
+        if self._componentTypeLen:
+            idx = self.componentType.getPositionByName(name)
+        else:
+            try:
+                idx = self._dynamicNames.getPositionByName(name)
+
+            except KeyError:
+                raise error.PyAsn1Error('Name %s not found' % (name,))
+
+        return self.getComponentByPosition(idx, default=default, instantiate=instantiate)
+
+    def setComponentByName(self, name, value=noValue,
+                           verifyConstraints=True,
+                           matchTags=True,
+                           matchConstraints=True):
+        """Assign |ASN.1| type component by name.
+
+        Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`).
+
+        Parameters
+        ----------
+        name: :class:`str`
+            |ASN.1| type component name
+
+        Keyword Args
+        ------------
+        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+            A Python value to initialize |ASN.1| component with (if *componentType* is set)
+            or ASN.1 value object to assign to |ASN.1| component.
+            If `value` is not given, schema object will be set as a component.
+
+        verifyConstraints: :class:`bool`
+             If :obj:`False`, skip constraints validation
+
+        matchTags: :class:`bool`
+             If :obj:`False`, skip component tags matching
+
+        matchConstraints: :class:`bool`
+             If :obj:`False`, skip component constraints matching
+
+        Returns
+        -------
+        self
+        """
+        if self._componentTypeLen:
+            idx = self.componentType.getPositionByName(name)
+        else:
+            try:
+                idx = self._dynamicNames.getPositionByName(name)
+
+            except KeyError:
+                raise error.PyAsn1Error('Name %s not found' % (name,))
+
+        return self.setComponentByPosition(
+            idx, value, verifyConstraints, matchTags, matchConstraints
+        )
+
+    def getComponentByPosition(self, idx, default=noValue, instantiate=True):
+        """Returns |ASN.1| type component by index.
+
+        Equivalent to Python sequence subscription operation (e.g. `[]`).
+
+        Parameters
+        ----------
+        idx: :class:`int`
+            Component index (zero-based). Must either refer to an existing
+            component or (if *componentType* is set) new ASN.1 schema object gets
+            instantiated.
+
+        Keyword Args
+        ------------
+        default: :class:`object`
+            If set and requested component is a schema object, return the `default`
+            object instead of the requested component.
+
+        instantiate: :class:`bool`
+            If :obj:`True` (default), inner component will be automatically
+            instantiated.
+            If :obj:`False` either existing component or the :class:`NoValue`
+            object will be returned.
+
+        Returns
+        -------
+        : :py:class:`~pyasn1.type.base.PyAsn1Item`
+            a PyASN1 object
+
+        Examples
+        --------
+
+        .. code-block:: python
+
+            # can also be Set
+            class MySequence(Sequence):
+                componentType = NamedTypes(
+                    NamedType('id', OctetString())
+                )
+
+            s = MySequence()
+
+            # returns component #0 with `.isValue` property False
+            s.getComponentByPosition(0)
+
+            # returns None
+            s.getComponentByPosition(0, default=None)
+
+            s.clear()
+
+            # returns noValue
+            s.getComponentByPosition(0, instantiate=False)
+
+            # sets component #0 to OctetString() ASN.1 schema
+            # object and returns it
+            s.getComponentByPosition(0, instantiate=True)
+
+            # sets component #0 to ASN.1 value object
+            s.setComponentByPosition(0, 'ABCD')
+
+            # returns OctetString('ABCD') value object
+            s.getComponentByPosition(0, instantiate=False)
+
+            s.clear()
+
+            # returns noValue
+            s.getComponentByPosition(0, instantiate=False)
+        """
+        try:
+            if self._componentValues is noValue:
+                componentValue = noValue
+
+            else:
+                componentValue = self._componentValues[idx]
+
+        except IndexError:
+            componentValue = noValue
+
+        if not instantiate:
+            if componentValue is noValue or not componentValue.isValue:
+                return default
+            else:
+                return componentValue
+
+        if componentValue is noValue:
+            self.setComponentByPosition(idx)
+
+        componentValue = self._componentValues[idx]
+
+        if default is noValue or componentValue.isValue:
+            return componentValue
+        else:
+            return default
+
+    def setComponentByPosition(self, idx, value=noValue,
+                               verifyConstraints=True,
+                               matchTags=True,
+                               matchConstraints=True):
+        """Assign |ASN.1| type component by position.
+
+        Equivalent to Python sequence item assignment operation (e.g. `[]`).
+
+        Parameters
+        ----------
+        idx : :class:`int`
+            Component index (zero-based). Must either refer to existing
+            component (if *componentType* is set) or to N+1 component
+            otherwise. In the latter case a new component of given ASN.1
+            type gets instantiated and appended to |ASN.1| sequence.
+
+        Keyword Args
+        ------------
+        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+            A Python value to initialize |ASN.1| component with (if *componentType* is set)
+            or ASN.1 value object to assign to |ASN.1| component.
+            If `value` is not given, schema object will be set as a component.
+
+        verifyConstraints : :class:`bool`
+             If :obj:`False`, skip constraints validation
+
+        matchTags: :class:`bool`
+             If :obj:`False`, skip component tags matching
+
+        matchConstraints: :class:`bool`
+             If :obj:`False`, skip component constraints matching
+
+        Returns
+        -------
+        self
+        """
+        componentType = self.componentType
+        componentTypeLen = self._componentTypeLen
+
+        if self._componentValues is noValue:
+            componentValues = []
+
+        else:
+            componentValues = self._componentValues
+
+        try:
+            currentValue = componentValues[idx]
+
+        except IndexError:
+            currentValue = noValue
+            if componentTypeLen:
+                if componentTypeLen < idx:
+                    raise error.PyAsn1Error('component index out of range')
+
+                componentValues = [noValue] * componentTypeLen
+
+        if value is noValue:
+            if componentTypeLen:
+                value = componentType.getTypeByPosition(idx)
+                if isinstance(value, base.ConstructedAsn1Type):
+                    value = value.clone(cloneValueFlag=componentType[idx].isDefaulted)
+
+            elif currentValue is noValue:
+                raise error.PyAsn1Error('Component type not defined')
+
+        elif not isinstance(value, base.Asn1Item):
+            if componentTypeLen:
+                subComponentType = componentType.getTypeByPosition(idx)
+                if isinstance(subComponentType, base.SimpleAsn1Type):
+                    value = subComponentType.clone(value=value)
+
+                else:
+                    raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__)
+
+            elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type):
+                value = currentValue.clone(value=value)
+
+            else:
+                raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__)
+
+        elif ((verifyConstraints or matchTags or matchConstraints) and
+              componentTypeLen):
+            subComponentType = componentType.getTypeByPosition(idx)
+            if subComponentType is not noValue:
+                subtypeChecker = (self.strictConstraints and
+                                  subComponentType.isSameTypeWith or
+                                  subComponentType.isSuperTypeOf)
+
+                if not subtypeChecker(value, verifyConstraints and matchTags,
+                                      verifyConstraints and matchConstraints):
+                    if not componentType[idx].openType:
+                        raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
+
+        if componentTypeLen or idx in self._dynamicNames:
+            componentValues[idx] = value
+
+        elif len(componentValues) == idx:
+            componentValues.append(value)
+            self._dynamicNames.addField(idx)
+
+        else:
+            raise error.PyAsn1Error('Component index out of range')
+
+        self._componentValues = componentValues
+
+        return self
+
+    @property
+    def isValue(self):
+        """Indicate that |ASN.1| object represents ASN.1 value.
+
+        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
+
+        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
+        this object can also be used like a Python built-in object (e.g.
+        :class:`int`, :class:`str`, :class:`dict` etc.).
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`False` if object represents just ASN.1 schema.
+            :obj:`True` if object represents ASN.1 schema and can be used as a
+            normal value.
+
+        Note
+        ----
+        There is an important distinction between PyASN1 schema and value objects.
+        The PyASN1 schema objects can only participate in ASN.1 schema-related
+        operations (e.g. defining or testing the structure of the data). Most
+        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
+        encoding/decoding serialised ASN.1 contents.
+
+        The PyASN1 value objects can **additionally** participate in many operations
+        involving regular Python objects (e.g. arithmetic, comprehension etc).
+
+        It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted
+        components being value objects to be considered as a value objects as a whole.
+        In other words, even having one or more optional components not turned into
+        value objects, |ASN.1| object is still considered as a value object. Defaulted
+        components are normally value objects by default.
+        """
+        if self._componentValues is noValue:
+            return False
+
+        componentType = self.componentType
+
+        if componentType:
+            for idx, subComponentType in enumerate(componentType.namedTypes):
+                if subComponentType.isDefaulted or subComponentType.isOptional:
+                    continue
+
+                if not self._componentValues:
+                    return False
+
+                componentValue = self._componentValues[idx]
+                if componentValue is noValue or not componentValue.isValue:
+                    return False
+
+        else:
+            for componentValue in self._componentValues:
+                if componentValue is noValue or not componentValue.isValue:
+                    return False
+
+        return True
+
+    @property
+    def isInconsistent(self):
+        """Run necessary checks to ensure |ASN.1| object consistency.
+
+        Default action is to verify |ASN.1| object against constraints imposed
+        by `subtypeSpec`.
+
+        Raises
+        ------
+        :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found
+        """
+        if self.componentType is noValue or not self.subtypeSpec:
+            return False
+
+        if self._componentValues is noValue:
+            return True
+
+        mapping = {}
+
+        for idx, value in enumerate(self._componentValues):
+            # Absent fields are not in the mapping
+            if value is noValue:
+                continue
+
+            name = self.componentType.getNameByPosition(idx)
+
+            mapping[name] = value
+
+        try:
+            # Represent Sequence/Set as a bare dict to constraints chain
+            self.subtypeSpec(mapping)
+
+        except error.PyAsn1Error as exc:
+            return exc
+
+        return False
+
+    def prettyPrint(self, scope=0):
+        """Return an object representation string.
+
+        Returns
+        -------
+        : :class:`str`
+            Human-friendly object representation.
+        """
+        scope += 1
+        representation = self.__class__.__name__ + ':\n'
+        for idx, componentValue in enumerate(self._componentValues):
+            if componentValue is not noValue and componentValue.isValue:
+                representation += ' ' * scope
+                if self.componentType:
+                    representation += self.componentType.getNameByPosition(idx)
+                else:
+                    representation += self._dynamicNames.getNameByPosition(idx)
+                representation = '%s=%s\n' % (
+                    representation, componentValue.prettyPrint(scope)
+                )
+        return representation
+
+    def prettyPrintType(self, scope=0):
+        scope += 1
+        representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__)
+        for idx, componentType in enumerate(self.componentType.values() or self._componentValues):
+            representation += ' ' * scope
+            if self.componentType:
+                representation += '"%s"' % self.componentType.getNameByPosition(idx)
+            else:
+                representation += '"%s"' % self._dynamicNames.getNameByPosition(idx)
+            representation = '%s = %s\n' % (
+                representation, componentType.prettyPrintType(scope)
+            )
+        return representation + '\n' + ' ' * (scope - 1) + '}'
+
+    # backward compatibility
+
+    def setDefaultComponents(self):
+        return self
+
+    def getComponentType(self):
+        if self._componentTypeLen:
+            return self.componentType
+
+    def getNameByPosition(self, idx):
+        if self._componentTypeLen:
+            return self.componentType[idx].name
+
+class Sequence(SequenceAndSetBase):
+    __doc__ = SequenceAndSetBase.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
+    )
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
+    #: object imposing size constraint on |ASN.1| objects
+    componentType = namedtype.NamedTypes()
+
+    # Disambiguation ASN.1 types identification
+    typeId = SequenceAndSetBase.getTypeId()
+
+    # backward compatibility
+
+    def getComponentTagMapNearPosition(self, idx):
+        if self.componentType:
+            return self.componentType.getTagMapNearPosition(idx)
+
+    def getComponentPositionNearType(self, tagSet, idx):
+        if self.componentType:
+            return self.componentType.getPositionNearType(tagSet, idx)
+        else:
+            return idx
+
+
+class Set(SequenceAndSetBase):
+    __doc__ = SequenceAndSetBase.__doc__
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
+    )
+
+    #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
+    #: object representing ASN.1 type allowed within |ASN.1| type
+    componentType = namedtype.NamedTypes()
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Disambiguation ASN.1 types identification
+    typeId = SequenceAndSetBase.getTypeId()
+
+    def getComponent(self, innerFlag=False):
+        return self
+
+    def getComponentByType(self, tagSet, default=noValue,
+                           instantiate=True, innerFlag=False):
+        """Returns |ASN.1| type component by ASN.1 tag.
+
+        Parameters
+        ----------
+        tagSet : :py:class:`~pyasn1.type.tag.TagSet`
+            Object representing ASN.1 tags to identify one of
+            |ASN.1| object component
+
+        Keyword Args
+        ------------
+        default: :class:`object`
+            If set and requested component is a schema object, return the `default`
+            object instead of the requested component.
+
+        instantiate: :class:`bool`
+            If :obj:`True` (default), inner component will be automatically
+            instantiated.
+            If :obj:`False` either existing component or the :class:`noValue`
+            object will be returned.
+
+        Returns
+        -------
+        : :py:class:`~pyasn1.type.base.PyAsn1Item`
+            a pyasn1 object
+        """
+        componentValue = self.getComponentByPosition(
+            self.componentType.getPositionByType(tagSet),
+            default=default, instantiate=instantiate
+        )
+        if innerFlag and isinstance(componentValue, Set):
+            # get inner component by inner tagSet
+            return componentValue.getComponent(innerFlag=True)
+        else:
+            # get outer component by inner tagSet
+            return componentValue
+
+    def setComponentByType(self, tagSet, value=noValue,
+                           verifyConstraints=True,
+                           matchTags=True,
+                           matchConstraints=True,
+                           innerFlag=False):
+        """Assign |ASN.1| type component by ASN.1 tag.
+
+        Parameters
+        ----------
+        tagSet : :py:class:`~pyasn1.type.tag.TagSet`
+            Object representing ASN.1 tags to identify one of
+            |ASN.1| object component
+
+        Keyword Args
+        ------------
+        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+            A Python value to initialize |ASN.1| component with (if *componentType* is set)
+            or ASN.1 value object to assign to |ASN.1| component.
+            If `value` is not given, schema object will be set as a component.
+
+        verifyConstraints : :class:`bool`
+            If :obj:`False`, skip constraints validation
+
+        matchTags: :class:`bool`
+            If :obj:`False`, skip component tags matching
+
+        matchConstraints: :class:`bool`
+            If :obj:`False`, skip component constraints matching
+
+        innerFlag: :class:`bool`
+            If :obj:`True`, search for matching *tagSet* recursively.
+
+        Returns
+        -------
+        self
+        """
+        idx = self.componentType.getPositionByType(tagSet)
+
+        if innerFlag:  # set inner component by inner tagSet
+            componentType = self.componentType.getTypeByPosition(idx)
+
+            if componentType.tagSet:
+                return self.setComponentByPosition(
+                    idx, value, verifyConstraints, matchTags, matchConstraints
+                )
+            else:
+                componentType = self.getComponentByPosition(idx)
+                return componentType.setComponentByType(
+                    tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag
+                )
+        else:  # set outer component by inner tagSet
+            return self.setComponentByPosition(
+                idx, value, verifyConstraints, matchTags, matchConstraints
+            )
+
+    @property
+    def componentTagMap(self):
+        if self.componentType:
+            return self.componentType.tagMapUnique
+
+
+class Choice(Set):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
+    its objects are mutable and duck-type Python :class:`list` objects.
+
+    Keyword Args
+    ------------
+    componentType: :py:class:`~pyasn1.type.namedtype.NamedType`
+        Object holding named ASN.1 types allowed within this collection
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s).  Constraints
+        verification for |ASN.1| type can only occur on explicit
+        `.isInconsistent` call.
+
+    Examples
+    --------
+
+    .. code-block:: python
+
+        class Afters(Choice):
+            '''
+            ASN.1 specification:
+
+            Afters ::= CHOICE {
+                cheese  [0] IA5String,
+                dessert [1] IA5String
+            }
+            '''
+            componentType = NamedTypes(
+                NamedType('cheese', IA5String().subtype(
+                    implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
+                ),
+                NamedType('dessert', IA5String().subtype(
+                    implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
+                )
+            )
+
+        afters = Afters()
+        afters['cheese'] = 'Mascarpone'
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.TagSet()  # untagged
+
+    #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`)
+    #: object representing ASN.1 type allowed within |ASN.1| type
+    componentType = namedtype.NamedTypes()
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection(
+        constraint.ValueSizeConstraint(1, 1)
+    )
+
+    # Disambiguation ASN.1 types identification
+    typeId = Set.getTypeId()
+
+    _currentIdx = None
+
+    def __eq__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] == other
+        return NotImplemented
+
+    def __ne__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] != other
+        return NotImplemented
+
+    def __lt__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] < other
+        return NotImplemented
+
+    def __le__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] <= other
+        return NotImplemented
+
+    def __gt__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] > other
+        return NotImplemented
+
+    def __ge__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] >= other
+        return NotImplemented
+
+    def __bool__(self):
+        return bool(self._componentValues)
+
+    def __len__(self):
+        return self._currentIdx is not None and 1 or 0
+
+    def __contains__(self, key):
+        if self._currentIdx is None:
+            return False
+        return key == self.componentType[self._currentIdx].getName()
+
+    def __iter__(self):
+        if self._currentIdx is None:
+            raise StopIteration
+        yield self.componentType[self._currentIdx].getName()
+
+    # Python dict protocol
+
+    def values(self):
+        if self._currentIdx is not None:
+            yield self._componentValues[self._currentIdx]
+
+    def keys(self):
+        if self._currentIdx is not None:
+            yield self.componentType[self._currentIdx].getName()
+
+    def items(self):
+        if self._currentIdx is not None:
+            yield self.componentType[self._currentIdx].getName(), self[self._currentIdx]
+
+    def checkConsistency(self):
+        if self._currentIdx is None:
+            raise error.PyAsn1Error('Component not chosen')
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        try:
+            component = self.getComponent()
+        except error.PyAsn1Error:
+            pass
+        else:
+            if isinstance(component, Choice):
+                tagSet = component.effectiveTagSet
+            else:
+                tagSet = component.tagSet
+            if isinstance(component, base.ConstructedAsn1Type):
+                myClone.setComponentByType(
+                    tagSet, component.clone(cloneValueFlag=cloneValueFlag)
+                )
+            else:
+                myClone.setComponentByType(tagSet, component.clone())
+
+    def getComponentByPosition(self, idx, default=noValue, instantiate=True):
+        __doc__ = Set.__doc__
+
+        if self._currentIdx is None or self._currentIdx != idx:
+            return Set.getComponentByPosition(self, idx, default=default,
+                                              instantiate=instantiate)
+
+        return self._componentValues[idx]
+
+    def setComponentByPosition(self, idx, value=noValue,
+                               verifyConstraints=True,
+                               matchTags=True,
+                               matchConstraints=True):
+        """Assign |ASN.1| type component by position.
+
+        Equivalent to Python sequence item assignment operation (e.g. `[]`).
+
+        Parameters
+        ----------
+        idx: :class:`int`
+            Component index (zero-based). Must either refer to existing
+            component or to N+1 component. In the latter case a new component
+            type gets instantiated (if *componentType* is set, or given ASN.1
+            object is taken otherwise) and appended to the |ASN.1| sequence.
+
+        Keyword Args
+        ------------
+        value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
+            A Python value to initialize |ASN.1| component with (if *componentType* is set)
+            or ASN.1 value object to assign to |ASN.1| component. Once a new value is
+            set to *idx* component, previous value is dropped.
+            If `value` is not given, schema object will be set as a component.
+
+        verifyConstraints : :class:`bool`
+            If :obj:`False`, skip constraints validation
+
+        matchTags: :class:`bool`
+            If :obj:`False`, skip component tags matching
+
+        matchConstraints: :class:`bool`
+            If :obj:`False`, skip component constraints matching
+
+        Returns
+        -------
+        self
+        """
+        oldIdx = self._currentIdx
+        Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints)
+        self._currentIdx = idx
+        if oldIdx is not None and oldIdx != idx:
+            self._componentValues[oldIdx] = noValue
+        return self
+
+    @property
+    def effectiveTagSet(self):
+        """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged)."""
+        if self.tagSet:
+            return self.tagSet
+        else:
+            component = self.getComponent()
+            return component.effectiveTagSet
+
+    @property
+    def tagMap(self):
+        """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
+            ASN.1 tags to ASN.1 objects contained within callee.
+        """
+        if self.tagSet:
+            return Set.tagMap.fget(self)
+        else:
+            return self.componentType.tagMapUnique
+
+    def getComponent(self, innerFlag=False):
+        """Return currently assigned component of the |ASN.1| object.
+
+        Returns
+        -------
+        : :py:class:`~pyasn1.type.base.PyAsn1Item`
+            a PyASN1 object
+        """
+        if self._currentIdx is None:
+            raise error.PyAsn1Error('Component not chosen')
+        else:
+            c = self._componentValues[self._currentIdx]
+            if innerFlag and isinstance(c, Choice):
+                return c.getComponent(innerFlag)
+            else:
+                return c
+
+    def getName(self, innerFlag=False):
+        """Return the name of currently assigned component of the |ASN.1| object.
+
+        Returns
+        -------
+        : :py:class:`str`
+            |ASN.1| component name
+        """
+        if self._currentIdx is None:
+            raise error.PyAsn1Error('Component not chosen')
+        else:
+            if innerFlag:
+                c = self._componentValues[self._currentIdx]
+                if isinstance(c, Choice):
+                    return c.getName(innerFlag)
+            return self.componentType.getNameByPosition(self._currentIdx)
+
+    @property
+    def isValue(self):
+        """Indicate that |ASN.1| object represents ASN.1 value.
+
+        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
+
+        If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features,
+        this object can also be used like a Python built-in object (e.g.
+        :class:`int`, :class:`str`, :class:`dict` etc.).
+
+        Returns
+        -------
+        : :class:`bool`
+            :obj:`False` if object represents just ASN.1 schema.
+            :obj:`True` if object represents ASN.1 schema and can be used as a normal
+            value.
+
+        Note
+        ----
+        There is an important distinction between PyASN1 schema and value objects.
+        The PyASN1 schema objects can only participate in ASN.1 schema-related
+        operations (e.g. defining or testing the structure of the data). Most
+        obvious uses of ASN.1 schema is to guide serialisation codecs whilst
+        encoding/decoding serialised ASN.1 contents.
+
+        The PyASN1 value objects can **additionally** participate in many operations
+        involving regular Python objects (e.g. arithmetic, comprehension etc).
+        """
+        if self._currentIdx is None:
+            return False
+
+        componentValue = self._componentValues[self._currentIdx]
+
+        return componentValue is not noValue and componentValue.isValue
+
+    def clear(self):
+        self._currentIdx = None
+        return Set.clear(self)
+
+    # compatibility stubs
+
+    def getMinTagSet(self):
+        return self.minTagSet
+
+
+class Any(OctetString):
+    """Create |ASN.1| schema or value object.
+
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
+    its objects are immutable and duck-type :class:`bytes`.
+    When used in Unicode context, |ASN.1| type assumes
+    "|encoding|" serialisation.
+
+    Keyword Args
+    ------------
+    value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
+        :class:`bytes`, alternatively :class:`str`
+        representing character string to be serialised into octets (note
+        `encoding` parameter) or |ASN.1| object.
+        If `value` is not given, schema object will be created.
+
+    tagSet: :py:class:`~pyasn1.type.tag.TagSet`
+        Object representing non-default ASN.1 tag(s)
+
+    subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
+        Object representing non-default ASN.1 subtype constraint(s). Constraints
+        verification for |ASN.1| type occurs automatically on object
+        instantiation.
+
+    encoding: :py:class:`str`
+        Unicode codec ID to encode/decode
+        :class:`str` the payload when |ASN.1| object is used
+        in text string context.
+
+    binValue: :py:class:`str`
+        Binary string initializer to use instead of the *value*.
+        Example: '10110011'.
+
+    hexValue: :py:class:`str`
+        Hexadecimal string initializer to use instead of the *value*.
+        Example: 'DEADBEEF'.
+
+    Raises
+    ------
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
+        On constraint violation or bad initializer.
+
+    Examples
+    --------
+    .. code-block:: python
+
+        class Error(Sequence):
+            '''
+            ASN.1 specification:
+
+            Error ::= SEQUENCE {
+                code      INTEGER,
+                parameter ANY DEFINED BY code  -- Either INTEGER or REAL
+            }
+            '''
+            componentType=NamedTypes(
+                NamedType('code', Integer()),
+                NamedType('parameter', Any(),
+                          openType=OpenType('code', {1: Integer(),
+                                                     2: Real()}))
+            )
+
+        error = Error()
+        error['code'] = 1
+        error['parameter'] = Integer(1234)
+    """
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
+    #: associated with |ASN.1| type.
+    tagSet = tag.TagSet()  # untagged
+
+    #: Set (on class, not on instance) or return a
+    #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object
+    #: imposing constraints on |ASN.1| type initialization values.
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Disambiguation ASN.1 types identification
+    typeId = OctetString.getTypeId()
+
+    @property
+    def tagMap(self):
+        """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping
+            ASN.1 tags to ASN.1 objects contained within callee.
+        """
+        try:
+            return self._tagMap
+
+        except AttributeError:
+            self._tagMap = tagmap.TagMap(
+                {self.tagSet: self},
+                {eoo.endOfOctets.tagSet: eoo.endOfOctets},
+                self
+            )
+
+            return self._tagMap
+
+# XXX
+# coercion rules?
diff --git a/.venv/lib/python3.12/site-packages/pyasn1/type/useful.py b/.venv/lib/python3.12/site-packages/pyasn1/type/useful.py
new file mode 100644
index 00000000..a8ae8740
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pyasn1/type/useful.py
@@ -0,0 +1,189 @@
+#
+# This file is part of pyasn1 software.
+#
+# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
+# License: https://pyasn1.readthedocs.io/en/latest/license.html
+#
+import datetime
+
+from pyasn1 import error
+from pyasn1.type import char
+from pyasn1.type import tag
+from pyasn1.type import univ
+
+__all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime']
+
+NoValue = univ.NoValue
+noValue = univ.noValue
+
+
+class ObjectDescriptor(char.GraphicString):
+    __doc__ = char.GraphicString.__doc__
+
+    #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects
+    tagSet = char.GraphicString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7)
+    )
+
+    # Optimization for faster codec lookup
+    typeId = char.GraphicString.getTypeId()
+
+
+class TimeMixIn(object):
+
+    _yearsDigits = 4
+    _hasSubsecond = False
+    _optionalMinutes = False
+    _shortTZ = False
+
+    class FixedOffset(datetime.tzinfo):
+        """Fixed offset in minutes east from UTC."""
+
+        # defaulted arguments required
+        # https: // docs.python.org / 2.3 / lib / datetime - tzinfo.html
+        def __init__(self, offset=0, name='UTC'):
+            self.__offset = datetime.timedelta(minutes=offset)
+            self.__name = name
+
+        def utcoffset(self, dt):
+            return self.__offset
+
+        def tzname(self, dt):
+            return self.__name
+
+        def dst(self, dt):
+            return datetime.timedelta(0)
+
+    UTC = FixedOffset()
+
+    @property
+    def asDateTime(self):
+        """Create :py:class:`datetime.datetime` object from a |ASN.1| object.
+
+        Returns
+        -------
+        :
+            new instance of :py:class:`datetime.datetime` object
+        """
+        text = str(self)
+        if text.endswith('Z'):
+            tzinfo = TimeMixIn.UTC
+            text = text[:-1]
+
+        elif '-' in text or '+' in text:
+            if '+' in text:
+                text, plusminus, tz = text.partition('+')
+            else:
+                text, plusminus, tz = text.partition('-')
+
+            if self._shortTZ and len(tz) == 2:
+                tz += '00'
+
+            if len(tz) != 4:
+                raise error.PyAsn1Error('malformed time zone offset %s' % tz)
+
+            try:
+                minutes = int(tz[:2]) * 60 + int(tz[2:])
+                if plusminus == '-':
+                    minutes *= -1
+
+            except ValueError:
+                raise error.PyAsn1Error('unknown time specification %s' % self)
+
+            tzinfo = TimeMixIn.FixedOffset(minutes, '?')
+
+        else:
+            tzinfo = None
+
+        if '.' in text or ',' in text:
+            if '.' in text:
+                text, _, ms = text.partition('.')
+            else:
+                text, _, ms = text.partition(',')
+
+            try:
+                ms = int(ms) * 1000
+
+            except ValueError:
+                raise error.PyAsn1Error('bad sub-second time specification %s' % self)
+
+        else:
+            ms = 0
+
+        if self._optionalMinutes and len(text) - self._yearsDigits == 6:
+            text += '0000'
+        elif len(text) - self._yearsDigits == 8:
+            text += '00'
+
+        try:
+            dt = datetime.datetime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S')
+
+        except ValueError:
+            raise error.PyAsn1Error('malformed datetime format %s' % self)
+
+        return dt.replace(microsecond=ms, tzinfo=tzinfo)
+
+    @classmethod
+    def fromDateTime(cls, dt):
+        """Create |ASN.1| object from a :py:class:`datetime.datetime` object.
+
+        Parameters
+        ----------
+        dt: :py:class:`datetime.datetime` object
+            The `datetime.datetime` object to initialize the |ASN.1| object
+            from
+
+        Returns
+        -------
+        :
+            new instance of |ASN.1| value
+        """
+        text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S')
+        if cls._hasSubsecond:
+            text += '.%d' % (dt.microsecond // 1000)
+
+        if dt.utcoffset():
+            seconds = dt.utcoffset().seconds
+            if seconds < 0:
+                text += '-'
+            else:
+                text += '+'
+            text += '%.2d%.2d' % (seconds // 3600, seconds % 3600)
+        else:
+            text += 'Z'
+
+        return cls(text)
+
+
+class GeneralizedTime(char.VisibleString, TimeMixIn):
+    __doc__ = char.VisibleString.__doc__
+
+    #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects
+    tagSet = char.VisibleString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24)
+    )
+
+    # Optimization for faster codec lookup
+    typeId = char.VideotexString.getTypeId()
+
+    _yearsDigits = 4
+    _hasSubsecond = True
+    _optionalMinutes = True
+    _shortTZ = True
+
+
+class UTCTime(char.VisibleString, TimeMixIn):
+    __doc__ = char.VisibleString.__doc__
+
+    #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects
+    tagSet = char.VisibleString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23)
+    )
+
+    # Optimization for faster codec lookup
+    typeId = char.VideotexString.getTypeId()
+
+    _yearsDigits = 2
+    _hasSubsecond = False
+    _optionalMinutes = False
+    _shortTZ = False