Upgrade python/pyasn1 to v0.4.6

Exempt-From-Owner-Approval: Upgrade library
Test: None
Change-Id: I94305762a92ba908aa8c1f78abdc44bc28e1e53a
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..5fcc7bb
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+custom: http://snmplabs.com/services.html
diff --git a/.travis.yml b/.travis.yml
index 3152686..cb495de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,31 +4,24 @@
   include:
   - os: linux
     dist: trusty
-    sudo: false
     python: '2.6'
   - os: linux
     dist: trusty
-    sudo: false
     python: '2.7'
   - os: linux
     dist: trusty
-    sudo: false
     python: '3.2'
   - os: linux
     dist: trusty
-    sudo: false
     python: '3.3'
   - os: linux
     dist: trusty
-    sudo: false
     python: '3.4'
   - os: linux
     dist: trusty
-    sudo: false
     python: '3.5'
   - os: linux
     dist: trusty
-    sudo: false
     python: '3.6'
   - os: linux
     dist: xenial
@@ -36,15 +29,12 @@
     python: '3.7'
   - os: linux
     dist: trusty
-    sudo: true
     python: 'nightly'
   - os: linux
     dist: trusty
-    sudo: false
     python: 'pypy'
   - os: linux
     dist: trusty
-    sudo: false
     python: 'pypy3'
 install:
   - pip install codecov
@@ -52,6 +42,14 @@
   - pip install -e .
 script:
   - PYTHONPATH=.:$PYTHONPATH python tests/__main__.py
+  - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == '3.3' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == '3.4' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == '3.7' ]]; then (make -C docs html); fi
+  - if [[ $TRAVIS_PYTHON_VERSION == 'nightly' ]]; then (make -C docs html); fi
 after_success:
   - PYTHONPATH=.:$PYTHONPATH coverage run --omit=*test* tests/__main__.py
   - codecov
diff --git a/CHANGES.rst b/CHANGES.rst
index c4084f3..0ca5904 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,4 +1,43 @@
 
+Revision 0.4.6, released 31-07-2019
+-----------------------------------
+
+- Added previously missing `SET OF ANY` construct encoding/decoding support.
+- Added `omitEmptyOptionals` option which is respected by `Sequence`
+  and `Set` encoders. When `omitEmptyOptionals` is set to `True`, empty
+  initialized optional components are not encoded. Default is `False`.
+- New elements to `SequenceOf`/`SetOf` objects can now be added at any
+  position - the requirement for the new elements to reside at the end
+  of the existing ones (i.e. s[len(s)] = 123) is removed.
+- List-like slicing support added to `SequenceOf`/`SetOf` objects.
+- Removed default initializer from `SequenceOf`/`SetOf` types to ensure
+  consistent behaviour with the rest of ASN.1 types. Before this change,
+  `SequenceOf`/`SetOf` instances immediately become value objects behaving
+  like an empty list. With this change, `SequenceOf`/`SetOf` objects
+  remain schema objects unless a component is added or `.clear()` is
+  called.
+  This change can potentially cause incompatibilities with existing
+  pyasn1 objects which assume `SequenceOf`/`SetOf` instances are value
+  objects right upon instantiation.
+  The behaviour of `Sequence`/`Set` types depends on the `componentType`
+  initializer: if on `componentType` is given, the behaviour is the
+  same as `SequenceOf`/`SetOf` have. IF `componentType` is given, but
+  neither optional nor defaulted components are present, the created
+  instance remains schema object, If, however, either optional or
+  defaulted component isi present, the created instance immediately
+  becomes a value object.
+- Added `.reset()` method to all constructed types to turn value object
+  into a schema object.
+- Added `PyAsn1UnicodeDecodeError`/`PyAsn1UnicodeDecodeError` exceptions
+  to help the caller treating unicode errors happening internally
+  to pyasn1 at the upper layers.
+- Added support for subseconds CER/DER encoding edge cases in
+  `GeneralizedTime` codec.
+- Fixed 3-digit fractional seconds value CER/DER encoding of
+  `GeneralizedTime`.
+- Fixed `AnyDecoder` to accept possible `TagMap` as `asn1Spec`
+  to make dumping raw value operational
+
 Revision 0.4.5, released 29-12-2018
 -----------------------------------
 
@@ -619,7 +658,7 @@
 Revision 0.0.4a
 ---------------
 
-* Asn1ItemBase.prettyPrinter() -> \*.prettyPrint()
+* Asn1Type.prettyPrinter() -> \*.prettyPrint()
 
 Revision 0.0.3a
 ---------------
diff --git a/METADATA b/METADATA
index d6b27fa..258fbfd 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,10 @@
     type: GIT
     value: "https://github.com/etingof/pyasn1"
   }
-  version: "v0.4.5"
+  version: "v0.4.6"
   last_upgrade_date {
     year: 2019
-    month: 2
-    day: 1
+    month: 7
+    day: 31
   }
 }
-
diff --git a/devel-requirements.txt b/devel-requirements.txt
index 45da368..f960024 100644
--- a/devel-requirements.txt
+++ b/devel-requirements.txt
@@ -1 +1,2 @@
 sphinx<1.5; python_version < '3.4'
+sphinx; python_version >= '3.4'
diff --git a/docs/source/pyasn1/contents.rst b/docs/source/pyasn1/contents.rst
index 474bbff..eaa7835 100644
--- a/docs/source/pyasn1/contents.rst
+++ b/docs/source/pyasn1/contents.rst
@@ -139,6 +139,7 @@
 .. toctree::
    :maxdepth: 2
 
+   /pyasn1/type/base/contents
    /pyasn1/type/univ/contents
    /pyasn1/type/char/contents
    /pyasn1/type/useful/contents
@@ -212,3 +213,16 @@
    /pyasn1/codec/cer/contents
    /pyasn1/codec/der/contents
    /pyasn1/codec/native/contents
+
+Exceptions
+----------
+
+Operations on PyASN1 schema and value objects might cause errors. These
+errors are manifested to the caller in form of Python exceptions.
+
+The exception hierarchy is as follows (ordered from least specific).
+
+.. toctree::
+   :maxdepth: 2
+
+   /pyasn1/error/contents
diff --git a/docs/source/pyasn1/error/contents.rst b/docs/source/pyasn1/error/contents.rst
new file mode 100644
index 0000000..be8a04c
--- /dev/null
+++ b/docs/source/pyasn1/error/contents.rst
@@ -0,0 +1,60 @@
+
+.. _error.PyAsn1Error:
+
+.. |PyAsn1Error| replace:: PyAsn1Error
+
+|PyAsn1Error|
+-------------
+
+.. autoclass:: pyasn1.error.PyAsn1Error
+   :members:
+
+.. _error.ValueConstraintError:
+
+.. |ValueConstraintError| replace:: ValueConstraintError
+
+|ValueConstraintError|
+----------------------
+
+.. autoclass:: pyasn1.error.ValueConstraintError
+   :members:
+
+.. _error.SubstrateUnderrunError:
+
+.. |SubstrateUnderrunError| replace:: SubstrateUnderrunError
+
+|SubstrateUnderrunError|
+------------------------
+
+.. autoclass:: pyasn1.error.SubstrateUnderrunError
+   :members:
+
+.. _error.PyAsn1UnicodeError:
+
+.. |PyAsn1UnicodeError| replace:: PyAsn1UnicodeError
+
+|PyAsn1UnicodeError|
+--------------------
+
+.. autoclass:: pyasn1.error.PyAsn1UnicodeError
+   :members:
+
+.. _error.PyAsn1UnicodeDecodeError:
+
+.. |PyAsn1UnicodeDecodeError| replace:: PyAsn1UnicodeDecodeError
+
+|PyAsn1UnicodeDecodeError|
+--------------------------
+
+.. autoclass:: pyasn1.error.PyAsn1UnicodeDecodeError
+   :members:
+
+.. _error.PyAsn1UnicodeEncodeError:
+
+.. |PyAsn1UnicodeEncodeError| replace:: PyAsn1UnicodeEncodeError
+
+|PyAsn1UnicodeEncodeError|
+--------------------------
+
+.. autoclass:: pyasn1.error.PyAsn1UnicodeEncodeError
+   :members:
diff --git a/docs/source/pyasn1/type/base/asn1type.rst b/docs/source/pyasn1/type/base/asn1type.rst
new file mode 100644
index 0000000..94fe04d
--- /dev/null
+++ b/docs/source/pyasn1/type/base/asn1type.rst
@@ -0,0 +1,10 @@
+
+.. _base.Asn1Type:
+
+.. |ASN.1| replace:: Asn1Type
+
+|ASN.1| type
+------------
+
+.. autoclass:: pyasn1.type.base.Asn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
+   :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec
diff --git a/docs/source/pyasn1/type/base/constructedasn1type.rst b/docs/source/pyasn1/type/base/constructedasn1type.rst
new file mode 100644
index 0000000..54d828f
--- /dev/null
+++ b/docs/source/pyasn1/type/base/constructedasn1type.rst
@@ -0,0 +1,10 @@
+
+.. _base.ConstructedAsn1Type:
+
+.. |ASN.1| replace:: ConstructedAsn1Type
+
+|ASN.1| type
+------------
+
+.. autoclass:: pyasn1.type.base.ConstructedAsn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection(), componentType=None)
+   :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec
diff --git a/docs/source/pyasn1/type/base/contents.rst b/docs/source/pyasn1/type/base/contents.rst
new file mode 100644
index 0000000..ffb325c
--- /dev/null
+++ b/docs/source/pyasn1/type/base/contents.rst
@@ -0,0 +1,20 @@
+
+.. _type.base:
+
+ASN.1 type system
+-----------------
+
+The ASN.1 language defines a collection of data types such as *INTEGER*
+or *SET*. With pyasn1, ASN.1 types are represented by Python classes.
+The base classes are described in this part of the documentation.
+
+User code might not need to use them directly, except for figuring out
+if given object belongs to ASN.1 type or not.
+
+.. toctree::
+   :maxdepth: 2
+
+   /pyasn1/type/base/asn1type
+   /pyasn1/type/base/simpleasn1type
+   /pyasn1/type/base/constructedasn1type
+   /pyasn1/type/base/novalue
diff --git a/docs/source/pyasn1/type/base/novalue.rst b/docs/source/pyasn1/type/base/novalue.rst
new file mode 100644
index 0000000..6e34792
--- /dev/null
+++ b/docs/source/pyasn1/type/base/novalue.rst
@@ -0,0 +1,6 @@
+.. _type.base.NoValue:
+
+NoValue sentinel
+----------------
+
+.. autoclass:: pyasn1.type.base.NoValue()
diff --git a/docs/source/pyasn1/type/base/simpleasn1type.rst b/docs/source/pyasn1/type/base/simpleasn1type.rst
new file mode 100644
index 0000000..03a960d
--- /dev/null
+++ b/docs/source/pyasn1/type/base/simpleasn1type.rst
@@ -0,0 +1,10 @@
+
+.. _base.SimpleAsn1Type:
+
+.. |ASN.1| replace:: SimpleAsn1Type
+
+|ASN.1| type
+------------
+
+.. autoclass:: pyasn1.type.base.SimpleAsn1Type(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
+   :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec
diff --git a/docs/source/pyasn1/type/opentype/contents.rst b/docs/source/pyasn1/type/opentype/contents.rst
index 9ae10d0..034870b 100644
--- a/docs/source/pyasn1/type/opentype/contents.rst
+++ b/docs/source/pyasn1/type/opentype/contents.rst
@@ -1,16 +1,67 @@
 
 .. _type.opentype:
 
-Untyped fields of constructed types
------------------------------------
+Dynamic or open type
+--------------------
 
-To aid data structures flexibility, ASN.1 allows the designer to
-leave incomplete field type specification in the
-:ref:`Sequence <univ.Sequence>` and :ref:`Set <univ.Set>` types.
+ASN.1 allows data structure designer to leave "holes" in field type
+specification of :ref:`Sequence <univ.Sequence>` or
+:ref:`Set <univ.Set>` types.
 
-To figure out field's type at the run time, a type selector field
-must accompany the open type field. The open type situation can
-be captured by the :ref:`OpenType <opentype.OpenType>` object.
+The idea behind that feature is that there can be times, when the
+exact field type is not known at the design time, or it is anticipated
+that new field types may come up in the future.
+
+This "hole" type is manifested in the data structure by :ref:`Any <univ.Any>`
+type. Technically, the actual type is serialized into an octet stream
+and then put into :ref:`Any <univ.Any>` "container", which is in fact an
+(untagged, by default) specialization of ASN.1
+:ref:`OctetString <univ.OctetString>` type.
+
+.. code-block:: bash
+
+       Algorithm ::= SEQUENCE {
+               algorithm OBJECT IDENTIFIER,
+               parameters ANY DEFINED BY algorithm OPTIONAL
+       }
+
+On the receiving end, to know how to interpret the open type
+serialization, the receiver can rely on the supplied value in
+the other field of the data structure. That other field is
+semantically linked with the open type field. This link
+is expressed in ASN.1 by the *DEFINE BY* clause.
+
+From ASN.1 perspective, it is not an error if the decoder does
+not know a type selector value it receives. In that case pyasn1 decoder
+just leaves serialized blob in the open type field.
+
+.. note::
+
+   By default, ASN.1 ANY type has no tag. That makes it an
+   "invisible" in serialization. However, like any other ASN.1 type,
+   ANY type can be subtyped by :ref:`tagging <type.tag>`.
+
+Besides scalar open type fields, ASN.1 allows using *SET OF*
+or *SEQUENCE OF* containers holding zero or more of *ANY*
+scalars.
+
+.. code-block:: bash
+
+   AttributeTypeAndValues ::= SEQUENCE {
+      type OBJECT IDENTIFIER,
+      values SET OF ANY DEFINED BY type
+   }
+
+.. note::
+
+   A single type selector field is used to guide the decoder
+   of potentially many elements of a *SET OF* or *SEQUENCE OF* container
+   all at once. That implies that all *ANY* elements must be of the same
+   type in any given instance of a data structure.
+
+When expressing ASN.1 type "holes" in pyasn1, the
+:ref:`OpenType <opentype.OpenType>` object should be used to establish
+a semantic link between type selector field and open type field.
 
 .. code-block:: python
 
@@ -24,15 +75,38 @@
        """
        Algorithm ::= SEQUENCE {
                algorithm OBJECT IDENTIFIER,
-               parameters ANY DEFINED BY algorithm OPTIONAL
+               parameters ANY DEFINED BY algorithm
        }
        """
        componentType = NamedTypes(
            NamedType('algorithm', ObjectIdentifier()),
-           OptionalNamedType('parameters', Any(),
+           NamedType('parameters', Any(),
                      openType=OpenType('algorithm', algo_map))
        )
 
+Similarly for `SET OF ANY DEFINED BY` or `SEQUENCE OF ANY DEFINED BY`
+constructs:
+
+.. code-block:: python
+
+   algo_map = {
+       ObjectIdentifier('1.2.840.113549.1.1.1'): rsaEncryption(),
+       ObjectIdentifier('1.2.840.113549.1.1.2'): md2WithRSAEncryption()
+   }
+
+
+   class Algorithm(Sequence):
+       """
+       Algorithm ::= SEQUENCE {
+               algorithm OBJECT IDENTIFIER,
+               parameters SET OF ANY DEFINED BY algorithm
+       }
+       """
+       componentType = NamedTypes(
+           NamedType('algorithm', ObjectIdentifier()),
+           NamedType('parameters', SetOf(componentType=Any()),
+                     openType=OpenType('algorithm', algo_map))
+       )
 
 .. toctree::
    :maxdepth: 2
diff --git a/docs/source/pyasn1/type/opentype/opentype.rst b/docs/source/pyasn1/type/opentype/opentype.rst
index dc2fa47..8ce9303 100644
--- a/docs/source/pyasn1/type/opentype/opentype.rst
+++ b/docs/source/pyasn1/type/opentype/opentype.rst
@@ -9,9 +9,4 @@
 .. autoclass:: pyasn1.type.opentype.OpenType
    :members:
 
-   .. note::
-
-        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` clause. Typically used with :ref:`Any <univ.Any>`
-        type.
+More information on open type use can be found :ref:`here <type.opentype>`.
\ No newline at end of file
diff --git a/docs/source/pyasn1/type/univ/contents.rst b/docs/source/pyasn1/type/univ/contents.rst
index 2a5ba25..d546e1c 100644
--- a/docs/source/pyasn1/type/univ/contents.rst
+++ b/docs/source/pyasn1/type/univ/contents.rst
@@ -32,7 +32,3 @@
    /pyasn1/type/univ/set
    /pyasn1/type/univ/sequence
    /pyasn1/type/univ/choice
-
-.. _univ.noValue:
-
-.. autoclass:: pyasn1.type.univ.NoValue()
diff --git a/docs/source/pyasn1/type/univ/sequence.rst b/docs/source/pyasn1/type/univ/sequence.rst
index 6d2c6b5..0988004 100644
--- a/docs/source/pyasn1/type/univ/sequence.rst
+++ b/docs/source/pyasn1/type/univ/sequence.rst
@@ -6,14 +6,15 @@
 |ASN.1| type
 ------------
 
-.. autoclass:: pyasn1.type.univ.Sequence(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
+.. autoclass:: pyasn1.type.univ.Sequence(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
    :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, getComponentByPosition,
-             setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents
+             setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents,
+             clear, reset
 
    .. note::
 
         The |ASN.1| type models a collection of named ASN.1 components.
         Ordering of the components **is** preserved upon de/serialisation.
 
-   .. automethod:: pyasn1.type.univ.Sequence.clone(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection())
-   .. automethod:: pyasn1.type.univ.Sequence.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.Sequence.clone(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.Sequence.subtype(componentType=NamedTypes(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
diff --git a/docs/source/pyasn1/type/univ/sequenceof.rst b/docs/source/pyasn1/type/univ/sequenceof.rst
index dadef67..6a09b92 100644
--- a/docs/source/pyasn1/type/univ/sequenceof.rst
+++ b/docs/source/pyasn1/type/univ/sequenceof.rst
@@ -6,14 +6,14 @@
 |ASN.1| type
 ------------
 
-.. autoclass:: pyasn1.type.univ.SequenceOf(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
+.. autoclass:: pyasn1.type.univ.SequenceOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
    :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
-             getComponentByPosition, setComponentByPosition
+             getComponentByPosition, setComponentByPosition, clear, reset
 
    .. note::
 
        The |ASN.1| type models a collection of elements of a single ASN.1 type.
        Ordering of the components **is** preserved upon de/serialisation.
         
-   .. automethod:: pyasn1.type.univ.SequenceOf.clone(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
-   .. automethod:: pyasn1.type.univ.SequenceOf.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.SequenceOf.clone(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.SequenceOf.subtype(componentType=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
diff --git a/docs/source/pyasn1/type/univ/set.rst b/docs/source/pyasn1/type/univ/set.rst
index 5c75938..792d2e9 100644
--- a/docs/source/pyasn1/type/univ/set.rst
+++ b/docs/source/pyasn1/type/univ/set.rst
@@ -6,15 +6,15 @@
 |ASN.1| type
 ------------
 
-.. autoclass:: pyasn1.type.univ.Set(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
+.. autoclass:: pyasn1.type.univ.Set(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
    :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
              getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents,
-             getComponentByType, setComponentByType
+             getComponentByType, setComponentByType, clear, reset
 
    .. note::
 
         The |ASN.1| type models a collection of named ASN.1 components.
         Ordering of the components **is not** preserved upon de/serialisation.
 
-   .. automethod:: pyasn1.type.univ.Set.clone(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
-   .. automethod:: pyasn1.type.univ.Set.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.Set.clone(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.Set.subtype(componentType=NamedTypes(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
diff --git a/docs/source/pyasn1/type/univ/setof.rst b/docs/source/pyasn1/type/univ/setof.rst
index 0317f4a..67ef92f 100644
--- a/docs/source/pyasn1/type/univ/setof.rst
+++ b/docs/source/pyasn1/type/univ/setof.rst
@@ -6,14 +6,14 @@
 |ASN.1| type
 ------------
 
-.. autoclass:: pyasn1.type.univ.SetOf(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
+.. autoclass:: pyasn1.type.univ.SetOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
    :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
-             getComponentByPosition, setComponentByPosition
+             getComponentByPosition, setComponentByPosition, clear, reset
 
    .. note::
 
         The |ASN.1| type models a collection of elements of a single ASN.1 type.
         Ordering of the components **is not** preserved upon de/serialisation.
 
-   .. automethod:: pyasn1.type.univ.SetOf.clone(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
-   .. automethod:: pyasn1.type.univ.SetOf.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.SetOf.clone(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
+   .. automethod:: pyasn1.type.univ.SetOf.subtype(componentType=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
diff --git a/pyasn1/__init__.py b/pyasn1/__init__.py
index 68db4f1..d780df2 100644
--- a/pyasn1/__init__.py
+++ b/pyasn1/__init__.py
@@ -1,7 +1,7 @@
 import sys
 
 # https://www.python.org/dev/peps/pep-0396/
-__version__ = '0.4.5'
+__version__ = '0.4.6'
 
 if sys.version_info[:2] < (2, 4):
     raise RuntimeError('PyASN1 requires Python 2.4 or later')
diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
index 591bbc4..3f2d180 100644
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -567,6 +567,7 @@
             return asn1Object, tail
 
         asn1Object = asn1Spec.clone()
+        asn1Object.clear()
 
         if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
 
@@ -670,18 +671,35 @@
                                 LOG('resolved open type %r by governing '
                                     'value %r' % (openType, governingValue))
 
-                            component, rest = decodeFun(
-                                asn1Object.getComponentByPosition(idx).asOctets(),
-                                asn1Spec=openType
-                            )
+                            containerValue = asn1Object.getComponentByPosition(idx)
 
-                            asn1Object.setComponentByPosition(idx, component)
+                            if containerValue.typeId in (
+                                    univ.SetOf.typeId, univ.SequenceOf.typeId):
+
+                                for pos, containerElement in enumerate(
+                                        containerValue):
+
+                                    component, rest = decodeFun(
+                                        containerValue[pos].asOctets(),
+                                        asn1Spec=openType, **options
+                                    )
+
+                                    containerValue[pos] = component
+
+                            else:
+                                component, rest = decodeFun(
+                                    asn1Object.getComponentByPosition(idx).asOctets(),
+                                    asn1Spec=openType, **options
+                                )
+
+                                asn1Object.setComponentByPosition(idx, component)
 
             else:
                 asn1Object.verifySizeSpec()
 
         else:
             asn1Object = asn1Spec.clone()
+            asn1Object.clear()
 
             componentType = asn1Spec.componentType
 
@@ -723,10 +741,12 @@
 
         if asn1Spec is None:
             return self._decodeComponents(
-                substrate, tagSet=tagSet, decodeFun=decodeFun, allowEoo=True, **options
+                substrate, tagSet=tagSet, decodeFun=decodeFun,
+                **dict(options, allowEoo=True)
             )
 
         asn1Object = asn1Spec.clone()
+        asn1Object.clear()
 
         if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
 
@@ -796,7 +816,7 @@
                 if not namedTypes.requiredComponents.issubset(seenIndices):
                     raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
 
-                if  namedTypes.hasOpenTypes:
+                if namedTypes.hasOpenTypes:
 
                     openTypes = options.get('openTypes', {})
 
@@ -834,19 +854,36 @@
                                 LOG('resolved open type %r by governing '
                                     'value %r' % (openType, governingValue))
 
-                            component, rest = decodeFun(
-                                asn1Object.getComponentByPosition(idx).asOctets(),
-                                asn1Spec=openType, allowEoo=True
-                            )
+                            containerValue = asn1Object.getComponentByPosition(idx)
 
-                            if component is not eoo.endOfOctets:
-                                asn1Object.setComponentByPosition(idx, component)
+                            if containerValue.typeId in (
+                                    univ.SetOf.typeId, univ.SequenceOf.typeId):
+
+                                for pos, containerElement in enumerate(
+                                        containerValue):
+
+                                    component, rest = decodeFun(
+                                        containerValue[pos].asOctets(),
+                                        asn1Spec=openType, **dict(options, allowEoo=True)
+                                    )
+
+                                    containerValue[pos] = component
+
+                            else:
+                                component, rest = decodeFun(
+                                    asn1Object.getComponentByPosition(idx).asOctets(),
+                                    asn1Spec=openType, **dict(options, allowEoo=True)
+                                )
+
+                                if component is not eoo.endOfOctets:
+                                    asn1Object.setComponentByPosition(idx, component)
 
                 else:
                     asn1Object.verifySizeSpec()
 
         else:
             asn1Object = asn1Spec.clone()
+            asn1Object.clear()
 
             componentType = asn1Spec.componentType
 
@@ -1012,7 +1049,16 @@
                      tagSet=None, length=None, state=None,
                      decodeFun=None, substrateFun=None,
                      **options):
-        if asn1Spec is None or asn1Spec is not None and tagSet != asn1Spec.tagSet:
+        if asn1Spec is None:
+            isUntagged = True
+
+        elif asn1Spec.__class__ is tagmap.TagMap:
+            isUntagged = tagSet not in asn1Spec.tagMap
+
+        else:
+            isUntagged = tagSet != asn1Spec.tagSet
+
+        if isUntagged:
             fullSubstrate = options['fullSubstrate']
 
             # untagged Any container, recover inner header substrate
@@ -1034,7 +1080,16 @@
                              tagSet=None, length=None, state=None,
                              decodeFun=None, substrateFun=None,
                              **options):
-        if asn1Spec is not None and tagSet == asn1Spec.tagSet:
+        if asn1Spec is None:
+            isTagged = False
+
+        elif asn1Spec.__class__ is tagmap.TagMap:
+            isTagged = tagSet in asn1Spec.tagMap
+
+        else:
+            isTagged = tagSet == asn1Spec.tagSet
+
+        if isTagged:
             # tagged Any type -- consume header substrate
             header = null
 
@@ -1204,7 +1259,7 @@
 
 class Decoder(object):
     defaultErrorState = stErrorCondition
-    #    defaultErrorState = stDumpRawValue
+    #defaultErrorState = stDumpRawValue
     defaultRawDecoder = AnyDecoder()
     supportIndefLength = True
 
@@ -1505,7 +1560,9 @@
                 break
 
             if state is stTryAsExplicitTag:
-                if tagSet and tagSet[0].tagFormat == tag.tagFormatConstructed and tagSet[0].tagClass != tag.tagClassUniversal:
+                if (tagSet and
+                        tagSet[0].tagFormat == tag.tagFormatConstructed and
+                        tagSet[0].tagClass != tag.tagClassUniversal):
                     # Assume explicit tagging
                     concreteDecoder = explicitTagDecoder
                     state = stDecodeValue
@@ -1563,7 +1620,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError
 #:     On decoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py
index 65b8514..a5d5fd3 100644
--- a/pyasn1/codec/ber/encoder.py
+++ b/pyasn1/codec/ber/encoder.py
@@ -4,6 +4,8 @@
 # Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
 # License: http://snmplabs.com/pyasn1/license.html
 #
+import sys
+
 from pyasn1 import debug
 from pyasn1 import error
 from pyasn1.codec.ber import eoo
@@ -87,15 +89,23 @@
 
         defMode = options.get('defMode', True)
 
+        substrate = null
+
         for idx, singleTag in enumerate(tagSet.superTags):
 
             defModeOverride = defMode
 
             # base tag?
             if not idx:
-                substrate, isConstructed, isOctets = self.encodeValue(
-                    value, asn1Spec, encodeFun, **options
-                )
+                try:
+                    substrate, isConstructed, isOctets = self.encodeValue(
+                        value, asn1Spec, encodeFun, **options
+                    )
+
+                except error.PyAsn1Error:
+                    exc = sys.exc_info()
+                    raise error.PyAsn1Error(
+                        'Error encoding %r: %s' % (value, exc[1]))
 
                 if LOG:
                     LOG('encoded %svalue %s into %s' % (
@@ -518,6 +528,13 @@
 
         substrate = null
 
+        omitEmptyOptionals = options.get(
+            'omitEmptyOptionals', self.omitEmptyOptionals)
+
+        if LOG:
+            LOG('%sencoding empty OPTIONAL components' % (
+                    omitEmptyOptionals and 'not ' or ''))
+
         if asn1Spec is None:
             # instance of ASN.1 schema
             value.verifySizeSpec()
@@ -538,21 +555,35 @@
                             LOG('not encoding DEFAULT component %r' % (namedType,))
                         continue
 
-                    if self.omitEmptyOptionals:
+                    if omitEmptyOptionals:
                         options.update(ifNotEmpty=namedType.isOptional)
 
-                chunk = encodeFun(component, asn1Spec, **options)
-
                 # wrap open type blob if needed
                 if namedTypes and namedType.openType:
+
                     wrapType = namedType.asn1Object
-                    if wrapType.tagSet and not wrapType.isSameTypeWith(component):
-                        chunk = encodeFun(chunk, wrapType, **options)
 
-                        if LOG:
-                            LOG('wrapped open type with wrap type %r' % (wrapType,))
+                    if wrapType.typeId in (
+                            univ.SetOf.typeId, univ.SequenceOf.typeId):
 
-                substrate += chunk
+                        substrate += encodeFun(
+                                component, asn1Spec,
+                                **dict(options, wrapType=wrapType.componentType))
+
+                    else:
+                        chunk = encodeFun(component, asn1Spec, **options)
+
+                        if wrapType.isSameTypeWith(component):
+                            substrate += chunk
+
+                        else:
+                            substrate += encodeFun(chunk, wrapType, **options)
+
+                            if LOG:
+                                LOG('wrapped with wrap type %r' % (wrapType,))
+
+                else:
+                    substrate += encodeFun(component, asn1Spec, **options)
 
         else:
             # bare Python value + ASN.1 schema
@@ -575,38 +606,72 @@
                         LOG('not encoding DEFAULT component %r' % (namedType,))
                     continue
 
-                if self.omitEmptyOptionals:
+                if omitEmptyOptionals:
                     options.update(ifNotEmpty=namedType.isOptional)
 
-                chunk = encodeFun(component, asn1Spec[idx], **options)
+                componentSpec = namedType.asn1Object
 
                 # wrap open type blob if needed
                 if namedType.openType:
-                    wrapType = namedType.asn1Object
-                    if wrapType.tagSet and not wrapType.isSameTypeWith(component):
-                        chunk = encodeFun(chunk, wrapType, **options)
 
-                        if LOG:
-                            LOG('wrapped open type with wrap type %r' % (wrapType,))
+                    if componentSpec.typeId in (
+                            univ.SetOf.typeId, univ.SequenceOf.typeId):
 
-                substrate += chunk
+                        substrate += encodeFun(
+                                component, componentSpec,
+                                **dict(options, wrapType=componentSpec.componentType))
+
+                    else:
+                        chunk = encodeFun(component, componentSpec, **options)
+
+                        if componentSpec.isSameTypeWith(component):
+                            substrate += chunk
+
+                        else:
+                            substrate += encodeFun(chunk, componentSpec, **options)
+
+                            if LOG:
+                                LOG('wrapped with wrap type %r' % (componentSpec,))
+
+                else:
+                    substrate += encodeFun(component, componentSpec, **options)
 
         return substrate, True, True
 
 
 class SequenceOfEncoder(AbstractItemEncoder):
-    def encodeValue(self, value, asn1Spec, encodeFun, **options):
+    def _encodeComponents(self, value, asn1Spec, encodeFun, **options):
+
         if asn1Spec is None:
             value.verifySizeSpec()
+
         else:
             asn1Spec = asn1Spec.componentType
 
-        substrate = null
+        chunks = []
+
+        wrapType = options.pop('wrapType', None)
 
         for idx, component in enumerate(value):
-            substrate += encodeFun(value[idx], asn1Spec, **options)
+            chunk = encodeFun(component, asn1Spec, **options)
 
-        return substrate, True, True
+            if (wrapType is not None and
+                    not wrapType.isSameTypeWith(component)):
+                # wrap encoded value with wrapper container (e.g. ANY)
+                chunk = encodeFun(chunk, wrapType, **options)
+
+                if LOG:
+                    LOG('wrapped with wrap type %r' % (wrapType,))
+
+            chunks.append(chunk)
+
+        return chunks
+
+    def encodeValue(self, value, asn1Spec, encodeFun, **options):
+        chunks = self._encodeComponents(
+            value, asn1Spec, encodeFun, **options)
+
+        return null.join(chunks), True, True
 
 
 class ChoiceEncoder(AbstractItemEncoder):
@@ -784,7 +849,7 @@
 #:     Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
 #:
 #: defMode: :py:class:`bool`
-#:     If `False`, produces indefinite length encoding
+#:     If :obj:`False`, produces indefinite length encoding
 #:
 #: maxChunkSize: :py:class:`int`
 #:     Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
@@ -796,7 +861,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error
 #:     On encoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/ber/eoo.py b/pyasn1/codec/ber/eoo.py
index b613b53..48eb859 100644
--- a/pyasn1/codec/ber/eoo.py
+++ b/pyasn1/codec/ber/eoo.py
@@ -10,7 +10,7 @@
 __all__ = ['endOfOctets']
 
 
-class EndOfOctets(base.AbstractSimpleAsn1Item):
+class EndOfOctets(base.SimpleAsn1Type):
     defaultValue = 0
     tagSet = tag.initTagSet(
         tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x00)
diff --git a/pyasn1/codec/cer/decoder.py b/pyasn1/codec/cer/decoder.py
index 5099e3c..3e86fd0 100644
--- a/pyasn1/codec/cer/decoder.py
+++ b/pyasn1/codec/cer/decoder.py
@@ -87,7 +87,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError
 #:     On decoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py
index 788567f..6a9db97 100644
--- a/pyasn1/codec/cer/encoder.py
+++ b/pyasn1/codec/cer/encoder.py
@@ -31,17 +31,20 @@
 # specialized GeneralStringEncoder here
 
 class TimeEncoderMixIn(object):
-    zchar, = str2octs('Z')
-    pluschar, = str2octs('+')
-    minuschar, = str2octs('-')
-    commachar, = str2octs(',')
-    minLength = 12
-    maxLength = 19
+    Z_CHAR = ord('Z')
+    PLUS_CHAR = ord('+')
+    MINUS_CHAR = ord('-')
+    COMMA_CHAR = ord(',')
+    DOT_CHAR = ord('.')
+    ZERO_CHAR = ord('0')
+
+    MIN_LENGTH = 12
+    MAX_LENGTH = 19
 
     def encodeValue(self, value, asn1Spec, encodeFun, **options):
-        # Encoding constraints:
+        # CER encoding constraints:
         # - minutes are mandatory, seconds are optional
-        # - sub-seconds must NOT be zero
+        # - sub-seconds must NOT be zero / no meaningless zeros
         # - no hanging fraction dot
         # - time in UTC (Z)
         # - only dot is allowed for fractions
@@ -49,20 +52,46 @@
         if asn1Spec is not None:
             value = asn1Spec.clone(value)
 
-        octets = value.asOctets()
+        numbers = value.asNumbers()
 
-        if not self.minLength < len(octets) < self.maxLength:
-            raise error.PyAsn1Error('Length constraint violated: %r' % value)
+        if self.PLUS_CHAR in numbers or self.MINUS_CHAR in numbers:
+            raise error.PyAsn1Error('Must be UTC time: %r' % value)
 
-        if self.pluschar in octets or self.minuschar in octets:
-            raise error.PyAsn1Error('Must be UTC time: %r' % octets)
+        if numbers[-1] != self.Z_CHAR:
+            raise error.PyAsn1Error('Missing "Z" time zone specifier: %r' % value)
 
-        if octets[-1] != self.zchar:
-            raise error.PyAsn1Error('Missing "Z" time zone specifier: %r' % octets)
-
-        if self.commachar in octets:
+        if self.COMMA_CHAR in numbers:
             raise error.PyAsn1Error('Comma in fractions disallowed: %r' % value)
 
+        if self.DOT_CHAR in numbers:
+
+            isModified = False
+
+            numbers = list(numbers)
+
+            searchIndex = min(numbers.index(self.DOT_CHAR) + 4, len(numbers) - 1)
+
+            while numbers[searchIndex] != self.DOT_CHAR:
+                if numbers[searchIndex] == self.ZERO_CHAR:
+                    del numbers[searchIndex]
+                    isModified = True
+
+                searchIndex -= 1
+
+            searchIndex += 1
+
+            if searchIndex < len(numbers):
+                if numbers[searchIndex] == self.Z_CHAR:
+                    # drop hanging comma
+                    del numbers[searchIndex - 1]
+                    isModified = True
+
+            if isModified:
+                value = value.clone(numbers)
+
+        if not self.MIN_LENGTH < len(numbers) < self.MAX_LENGTH:
+            raise error.PyAsn1Error('Length constraint violated: %r' % value)
+
         options.update(maxChunkSize=1000)
 
         return encoder.OctetStringEncoder.encodeValue(
@@ -71,13 +100,44 @@
 
 
 class GeneralizedTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
-    minLength = 12
-    maxLength = 19
+    MIN_LENGTH = 12
+    MAX_LENGTH = 20
 
 
 class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
-    minLength = 10
-    maxLength = 14
+    MIN_LENGTH = 10
+    MAX_LENGTH = 14
+
+
+class SetOfEncoder(encoder.SequenceOfEncoder):
+    def encodeValue(self, value, asn1Spec, encodeFun, **options):
+        chunks = self._encodeComponents(
+            value, asn1Spec, encodeFun, **options)
+
+        # sort by serialised and padded components
+        if len(chunks) > 1:
+            zero = str2octs('\x00')
+            maxLen = max(map(len, chunks))
+            paddedChunks = [
+                (x.ljust(maxLen, zero), x) for x in chunks
+            ]
+            paddedChunks.sort(key=lambda x: x[0])
+
+            chunks = [x[1] for x in paddedChunks]
+
+        return null.join(chunks), True, True
+
+
+class SequenceOfEncoder(encoder.SequenceOfEncoder):
+    def encodeValue(self, value, asn1Spec, encodeFun, **options):
+
+        if options.get('ifNotEmpty', False) and not len(value):
+            return null, True, True
+
+        chunks = self._encodeComponents(
+            value, asn1Spec, encodeFun, **options)
+
+        return null.join(chunks), True, True
 
 
 class SetEncoder(encoder.SequenceEncoder):
@@ -168,55 +228,10 @@
         return substrate, True, True
 
 
-class SetOfEncoder(encoder.SequenceOfEncoder):
-    def encodeValue(self, value, asn1Spec, encodeFun, **options):
-        if asn1Spec is None:
-            value.verifySizeSpec()
-        else:
-            asn1Spec = asn1Spec.componentType
-
-        components = [encodeFun(x, asn1Spec, **options)
-                      for x in value]
-
-        # sort by serialised and padded components
-        if len(components) > 1:
-            zero = str2octs('\x00')
-            maxLen = max(map(len, components))
-            paddedComponents = [
-                (x.ljust(maxLen, zero), x) for x in components
-                ]
-            paddedComponents.sort(key=lambda x: x[0])
-
-            components = [x[1] for x in paddedComponents]
-
-        substrate = null.join(components)
-
-        return substrate, True, True
-
-
 class SequenceEncoder(encoder.SequenceEncoder):
     omitEmptyOptionals = True
 
 
-class SequenceOfEncoder(encoder.SequenceOfEncoder):
-    def encodeValue(self, value, asn1Spec, encodeFun, **options):
-
-        if options.get('ifNotEmpty', False) and not len(value):
-            return null, True, True
-
-        if asn1Spec is None:
-            value.verifySizeSpec()
-        else:
-            asn1Spec = asn1Spec.componentType
-
-        substrate = null
-
-        for idx, component in enumerate(value):
-            substrate += encodeFun(value[idx], asn1Spec, **options)
-
-        return substrate, True, True
-
-
 tagMap = encoder.tagMap.copy()
 tagMap.update({
     univ.Boolean.tagSet: BooleanEncoder(),
@@ -269,7 +284,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error
 #:     On encoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/der/decoder.py b/pyasn1/codec/der/decoder.py
index 261bab8..1a13fdb 100644
--- a/pyasn1/codec/der/decoder.py
+++ b/pyasn1/codec/der/decoder.py
@@ -67,7 +67,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError
 #:     On decoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/der/encoder.py b/pyasn1/codec/der/encoder.py
index 5e3c571..90e982d 100644
--- a/pyasn1/codec/der/encoder.py
+++ b/pyasn1/codec/der/encoder.py
@@ -82,7 +82,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error
 #:     On encoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/native/decoder.py b/pyasn1/codec/native/decoder.py
index 10e2015..104b92e 100644
--- a/pyasn1/codec/native/decoder.py
+++ b/pyasn1/codec/native/decoder.py
@@ -195,7 +195,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error
 #:     On decoding errors
 #:
 #: Examples
diff --git a/pyasn1/codec/native/encoder.py b/pyasn1/codec/native/encoder.py
index 50caa53..4c5908d 100644
--- a/pyasn1/codec/native/encoder.py
+++ b/pyasn1/codec/native/encoder.py
@@ -235,7 +235,7 @@
 #:
 #: Raises
 #: ------
-#: :py:class:`~pyasn1.error.PyAsn1Error`
+#: ~pyasn1.error.PyAsn1Error
 #:     On encoding errors
 #:
 #: Examples
diff --git a/pyasn1/error.py b/pyasn1/error.py
index 7f606bb..4f48db2 100644
--- a/pyasn1/error.py
+++ b/pyasn1/error.py
@@ -7,23 +7,69 @@
 
 
 class PyAsn1Error(Exception):
-    """Create pyasn1 exception object
+    """Base pyasn1 exception
 
-    The `PyAsn1Error` exception represents generic, usually fatal, error.
+    `PyAsn1Error` is the base exception class (based on
+    :class:`Exception`) that represents all possible ASN.1 related
+    errors.
     """
 
 
 class ValueConstraintError(PyAsn1Error):
-    """Create pyasn1 exception object
+    """ASN.1 type constraints violation exception
 
     The `ValueConstraintError` exception indicates an ASN.1 value
     constraint violation.
+
+    It might happen on value object instantiation (for scalar types) or on
+    serialization (for constructed types).
     """
 
 
 class SubstrateUnderrunError(PyAsn1Error):
-    """Create pyasn1 exception object
+    """ASN.1 data structure deserialization error
 
     The `SubstrateUnderrunError` exception indicates insufficient serialised
-    data on input of a de-serialization routine.
+    data on input of a de-serialization codec.
     """
+
+
+class PyAsn1UnicodeError(PyAsn1Error, UnicodeError):
+    """Unicode text processing error
+
+    The `PyAsn1UnicodeError` exception is a base class for errors relating to
+    unicode text de/serialization.
+
+    Apart from inheriting from :class:`PyAsn1Error`, it also inherits from
+    :class:`UnicodeError` to help the caller catching unicode-related errors.
+    """
+    def __init__(self, message, unicode_error=None):
+        if isinstance(unicode_error, UnicodeError):
+            UnicodeError.__init__(self, *unicode_error.args)
+        PyAsn1Error.__init__(self, message)
+
+
+class PyAsn1UnicodeDecodeError(PyAsn1UnicodeError, UnicodeDecodeError):
+    """Unicode text decoding error
+
+    The `PyAsn1UnicodeDecodeError` exception represents a failure to
+    deserialize unicode text.
+
+    Apart from inheriting from :class:`PyAsn1UnicodeError`, it also inherits
+    from :class:`UnicodeDecodeError` to help the caller catching unicode-related
+    errors.
+    """
+
+
+class PyAsn1UnicodeEncodeError(PyAsn1UnicodeError, UnicodeEncodeError):
+    """Unicode text encoding error
+
+    The `PyAsn1UnicodeEncodeError` exception represents a failure to
+    serialize unicode text.
+
+    Apart from inheriting from :class:`PyAsn1UnicodeError`, it also inherits
+    from :class:`UnicodeEncodeError` to help the caller catching
+    unicode-related errors.
+    """
+
+
diff --git a/pyasn1/type/base.py b/pyasn1/type/base.py
index 7995118..21e4041 100644
--- a/pyasn1/type/base.py
+++ b/pyasn1/type/base.py
@@ -12,7 +12,8 @@
 from pyasn1.type import tag
 from pyasn1.type import tagmap
 
-__all__ = ['Asn1Item', 'Asn1ItemBase', 'AbstractSimpleAsn1Item', 'AbstractConstructedAsn1Item']
+__all__ = ['Asn1Item', 'Asn1Type', 'SimpleAsn1Type',
+           'ConstructedAsn1Type']
 
 
 class Asn1Item(object):
@@ -25,7 +26,17 @@
         return Asn1Item._typeCounter
 
 
-class Asn1ItemBase(Asn1Item):
+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()
@@ -91,8 +102,8 @@
         Returns
         -------
         : :class:`bool`
-            :class:`True` if *other* is |ASN.1| type,
-            :class:`False` otherwise.
+            :obj:`True` if *other* is |ASN.1| type,
+            :obj:`False` otherwise.
         """
         return (self is other or
                 (not matchTags or self.tagSet == other.tagSet) and
@@ -115,8 +126,8 @@
         Returns
         -------
             : :class:`bool`
-                :class:`True` if *other* is a subtype of |ASN.1| type,
-                :class:`False` otherwise.
+                :obj:`True` if *other* is a subtype of |ASN.1| type,
+                :obj:`False` otherwise.
         """
         return (not matchTags or
                 (self.tagSet.isSuperTagSetOf(other.tagSet)) and
@@ -146,9 +157,13 @@
     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.
@@ -221,19 +236,31 @@
         raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr)
 
     def __repr__(self):
-        return '<%s object at 0x%x>' % (self.__class__.__name__, id(self))
+        return '<%s object>' % self.__class__.__name__
 
 
 noValue = NoValue()
 
 
-# Base class for "simple" ASN.1 objects. These are immutable.
-class AbstractSimpleAsn1Item(Asn1ItemBase):
+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):
-        Asn1ItemBase.__init__(self, **kwargs)
+        Asn1Type.__init__(self, **kwargs)
         if value is noValue:
             value = self.defaultValue
         else:
@@ -248,19 +275,18 @@
         self._value = value
 
     def __repr__(self):
-        representation = '%s %s object at 0x%x' % (
-            self.__class__.__name__, self.isValue and 'value' or 'schema', id(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)
+                representation += ', %s %s' % (attr, value)
 
         if self.isValue:
             value = self.prettyPrint()
             if len(value) > 32:
                 value = value[:16] + '...' + value[-16:]
-            representation += ' payload [%s]' % value
+            representation += ', payload [%s]' % value
 
         return '<%s>' % representation
 
@@ -296,17 +322,18 @@
     def isValue(self):
         """Indicate that |ASN.1| object represents ASN.1 value.
 
-        If *isValue* is `False` then this object represents just ASN.1 schema.
+        If *isValue* is :obj:`False` then this object represents just
+        ASN.1 schema.
 
-        If *isValue* is `True` then, in addition to its ASN.1 schema features,
-        this object can also be used like a Python built-in object (e.g. `int`,
-        `str`, `dict` etc.).
+        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`
-            :class:`False` if object represents just ASN.1 schema.
-            :class:`True` if object represents ASN.1 schema and can be used as a normal value.
+            :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
         ----
@@ -425,10 +452,12 @@
     def prettyPrint(self, scope=0):
         return self.prettyOut(self._value)
 
-    # noinspection PyUnusedLocal
     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
@@ -449,9 +478,22 @@
 #
 
 
-class AbstractConstructedAsn1Item(Asn1ItemBase):
+class ConstructedAsn1Type(Asn1Type):
+    """Base class for all constructed classes representing ASN.1 types.
 
-    #: If `True`, requires exact component type matching,
+    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
 
@@ -465,51 +507,51 @@
         }
         readOnly.update(kwargs)
 
-        Asn1ItemBase.__init__(self, **readOnly)
-
-        self._componentValues = []
+        Asn1Type.__init__(self, **readOnly)
 
     def __repr__(self):
-        representation = '%s %s object at 0x%x' % (
-            self.__class__.__name__, self.isValue and 'value' or 'schema', id(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)
+                representation += ', %s=%r' % (attr, value)
 
-        if self.isValue and self._componentValues:
-            representation += ' payload [%s]' % ', '.join([repr(x) for x in self._componentValues])
+        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 and True or self._componentValues == other
+        return self is other or self.components == other
 
     def __ne__(self, other):
-        return self._componentValues != other
+        return self.components != other
 
     def __lt__(self, other):
-        return self._componentValues < other
+        return self.components < other
 
     def __le__(self, other):
-        return self._componentValues <= other
+        return self.components <= other
 
     def __gt__(self, other):
-        return self._componentValues > other
+        return self.components > other
 
     def __ge__(self, other):
-        return self._componentValues >= other
+        return self.components >= other
 
     if sys.version_info[0] <= 2:
         def __nonzero__(self):
-            return self._componentValues and True or False
+            return bool(self.components)
     else:
         def __bool__(self):
-            return self._componentValues and True or False
+            return bool(self.components)
 
-    def __len__(self):
-        return len(self._componentValues)
+    @property
+    def components(self):
+        raise error.PyAsn1Error('Method not implemented')
 
     def _cloneComponentValues(self, myClone, cloneValueFlag):
         pass
@@ -535,8 +577,7 @@
         Note
         ----
         Due to the mutable nature of the |ASN.1| object, even if no arguments
-        are supplied, new |ASN.1| object will always be created as a shallow
-        copy of `self`.
+        are supplied, a new |ASN.1| object will be created and returned.
         """
         cloneValueFlag = kwargs.pop('cloneValueFlag', False)
 
@@ -588,9 +629,8 @@
 
         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.
+        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()
@@ -631,9 +671,6 @@
             self[k] = kwargs[k]
         return self
 
-    def clear(self):
-        self._componentValues = []
-
     # backward compatibility
 
     def setDefaultComponents(self):
@@ -641,3 +678,6 @@
 
     def getComponentType(self):
         return self.componentType
+
+# Backward compatibility
+AbstractConstructedAsn1Item = ConstructedAsn1Type
diff --git a/pyasn1/type/char.py b/pyasn1/type/char.py
index 617b98d..3f8c444 100644
--- a/pyasn1/type/char.py
+++ b/pyasn1/type/char.py
@@ -21,15 +21,19 @@
 class AbstractCharacterString(univ.OctetString):
     """Creates |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python 2 :class:`unicode` or Python 3 :class:`str`.
-    When used in octet-stream context, |ASN.1| type assumes "|encoding|" encoding.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
+    its objects are immutable and duck-type Python 2 :class:`str` or Python 3
+    :class:`bytes`. When used in octet-stream context, |ASN.1| type assumes
+    "|encoding|" encoding.
 
     Keyword Args
     ------------
     value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
-        unicode object (Python 2) or string (Python 3), alternatively string
-        (Python 2) or bytes (Python 3) representing octet-stream of serialised
-        unicode string (note `encoding` parameter) or |ASN.1| class instance.
+        :class:`unicode` object (Python 2) or :class:`str` (Python 3),
+        alternatively :class:`str` (Python 2) or :class:`bytes` (Python 3)
+        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)
@@ -44,7 +48,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
     """
 
@@ -55,8 +59,10 @@
                 return self._value.encode(self.encoding)
 
             except UnicodeEncodeError:
-                raise error.PyAsn1Error(
-                    "Can't encode string '%s' with codec %s" % (self._value, self.encoding)
+                exc = sys.exc_info()[1]
+                raise error.PyAsn1UnicodeEncodeError(
+                    "Can't encode string '%s' with codec "
+                    "%s" % (self._value, self.encoding), exc
                 )
 
         def __unicode__(self):
@@ -76,8 +82,10 @@
                     return unicode(value)
 
             except (UnicodeDecodeError, LookupError):
-                raise error.PyAsn1Error(
-                    "Can't decode string '%s' with codec %s" % (value, self.encoding)
+                exc = sys.exc_info()[1]
+                raise error.PyAsn1UnicodeDecodeError(
+                    "Can't decode string '%s' with codec "
+                    "%s" % (value, self.encoding), exc
                 )
 
         def asOctets(self, padding=True):
@@ -95,8 +103,10 @@
             try:
                 return self._value.encode(self.encoding)
             except UnicodeEncodeError:
-                raise error.PyAsn1Error(
-                    "Can't encode string '%s' with codec %s" % (self._value, self.encoding)
+                exc = sys.exc_info()[1]
+                raise error.PyAsn1UnicodeEncodeError(
+                    "Can't encode string '%s' with codec "
+                    "%s" % (self._value, self.encoding), exc
                 )
 
         def prettyIn(self, value):
@@ -113,8 +123,10 @@
                     return str(value)
 
             except (UnicodeDecodeError, LookupError):
-                raise error.PyAsn1Error(
-                    "Can't decode string '%s' with codec %s" % (value, self.encoding)
+                exc = sys.exc_info()[1]
+                raise error.PyAsn1UnicodeDecodeError(
+                    "Can't decode string '%s' with codec "
+                    "%s" % (value, self.encoding), exc
                 )
 
         def asOctets(self, padding=True):
diff --git a/pyasn1/type/constraint.py b/pyasn1/type/constraint.py
index 9d8883d..807c827 100644
--- a/pyasn1/type/constraint.py
+++ b/pyasn1/type/constraint.py
@@ -37,10 +37,11 @@
             )
 
     def __repr__(self):
-        representation = '%s object at 0x%x' % (self.__class__.__name__, id(self))
+        representation = '%s object' % (self.__class__.__name__)
 
         if self._values:
-            representation += ' consts %s' % ', '.join([repr(x) for x in self._values])
+            representation += ', consts %s' % ', '.join(
+                [repr(x) for x in self._values])
 
         return '<%s>' % representation
 
@@ -107,7 +108,7 @@
 
     Parameters
     ----------
-    \*values: :class:`int`
+    *values: :class:`int`
         Full set of values permitted by this constraint object.
 
     Examples
@@ -149,7 +150,7 @@
 
     Parameters
     ----------
-    \*values:
+    *values:
         Full set of values and constraint objects permitted
         by this constraint object.
 
@@ -310,7 +311,7 @@
 
     Parameters
     ----------
-    \*alphabet: :class:`str`
+    *alphabet: :class:`str`
         Full set of characters permitted by this constraint object.
 
     Examples
@@ -467,7 +468,7 @@
 
     Parameters
     ----------
-    \*constraints:
+    *constraints:
         Constraint or logic operator objects.
 
     Examples
@@ -511,7 +512,7 @@
 
     Parameters
     ----------
-    \*constraints:
+    *constraints:
         Constraint or logic operator objects.
 
     Examples
diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py
index 71f5f11..cbc1429 100644
--- a/pyasn1/type/namedtype.py
+++ b/pyasn1/type/namedtype.py
@@ -49,9 +49,10 @@
         representation = '%s=%r' % (self.name, self.asn1Object)
 
         if self.openType:
-            representation += ' openType: %r' % self.openType
+            representation += ', open type %r' % self.openType
 
-        return '<%s object at 0x%x type %s>' % (self.__class__.__name__, id(self), representation)
+        return '<%s object, type %s>' % (
+            self.__class__.__name__, representation)
 
     def __eq__(self, other):
         return self.__nameAndType == other
@@ -173,7 +174,8 @@
 
     def __repr__(self):
         representation = ', '.join(['%r' % x for x in self.__namedTypes])
-        return '<%s object at 0x%x types %s>' % (self.__class__.__name__, id(self), representation)
+        return '<%s object, types %s>' % (
+            self.__class__.__name__, representation)
 
     def __eq__(self, other):
         return self.__namedTypes == other
@@ -293,7 +295,7 @@
 
         Raises
         ------
-        : :class:`~pyasn1.error.PyAsn1Error`
+        ~pyasn1.error.PyAsn1Error
             If given position is out of fields range
         """
         try:
@@ -317,7 +319,7 @@
 
         Raises
         ------
-        : :class:`~pyasn1.error.PyAsn1Error`
+        ~pyasn1.error.PyAsn1Error
             If *tagSet* is not present or ASN.1 types are not unique within callee *NamedTypes*
         """
         try:
@@ -341,7 +343,7 @@
 
         Raises
         ------
-        : :class:`~pyasn1.error.PyAsn1Error`
+        ~pyasn1.error.PyAsn1Error
             If given field name is not present in callee *NamedTypes*
         """
         try:
@@ -365,7 +367,7 @@
 
         Raises
         ------
-        : :class:`~pyasn1.error.PyAsn1Error`
+        ~pyasn1.error.PyAsn1Error
             If *name* is not present or not unique within callee *NamedTypes*
         """
         try:
@@ -394,7 +396,7 @@
 
         Raises
         ------
-        : :class:`~pyasn1.error.PyAsn1Error`
+        ~pyasn1.error.PyAsn1Error
             If given position is out of fields range
         """
         try:
@@ -426,7 +428,7 @@
 
         Raises
         ------
-        : :class:`~pyasn1.error.PyAsn1Error`
+        ~pyasn1.error.PyAsn1Error
             If *tagSet* is not present or not unique within callee *NamedTypes*
             or *idx* is out of fields range
         """
diff --git a/pyasn1/type/namedval.py b/pyasn1/type/namedval.py
index 2233aaf..4247597 100644
--- a/pyasn1/type/namedval.py
+++ b/pyasn1/type/namedval.py
@@ -23,7 +23,7 @@
 
     Parameters
     ----------
-    \*args: variable number of two-element :py:class:`tuple`
+    *args: variable number of two-element :py:class:`tuple`
 
         name: :py:class:`str`
             Value label
@@ -109,7 +109,8 @@
         if len(representation) > 64:
             representation = representation[:32] + '...' + representation[-32:]
 
-        return '<%s object 0x%x enums %s>' % (self.__class__.__name__, id(self), representation)
+        return '<%s object, enums %s>' % (
+            self.__class__.__name__, representation)
 
     def __eq__(self, other):
         return dict(self) == other
diff --git a/pyasn1/type/opentype.py b/pyasn1/type/opentype.py
index d37a533..29645f0 100644
--- a/pyasn1/type/opentype.py
+++ b/pyasn1/type/opentype.py
@@ -11,11 +11,22 @@
 class OpenType(object):
     """Create ASN.1 type map indexed by a value
 
-    The *DefinedBy* object models the ASN.1 *DEFINED BY* clause which maps
-    values to ASN.1 types in the context of the ASN.1 SEQUENCE/SET type.
+    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 are duck-type a read-only Python :class:`dict` objects,
-    however the passed `typeMap` is stored by reference.
+    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
     ----------
@@ -28,12 +39,14 @@
 
     Examples
     --------
+
+    For untyped scalars:
+
     .. code-block:: python
 
         openType = OpenType(
-            'id',
-            {1: Integer(),
-             2: OctetString()}
+            'id', {1: Integer(),
+                   2: OctetString()}
         )
         Sequence(
             componentType=NamedTypes(
@@ -41,6 +54,22 @@
                 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):
diff --git a/pyasn1/type/tag.py b/pyasn1/type/tag.py
index b46f491..b88a734 100644
--- a/pyasn1/type/tag.py
+++ b/pyasn1/type/tag.py
@@ -64,8 +64,10 @@
         self.__hash = hash(self.__tagClassId)
 
     def __repr__(self):
-        representation = '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
-        return '<%s object at 0x%x tag %s>' % (self.__class__.__name__, id(self), representation)
+        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
@@ -199,7 +201,7 @@
         else:
             representation = 'untagged'
 
-        return '<%s object at 0x%x %s>' % (self.__class__.__name__, id(self), representation)
+        return '<%s object, %s>' % (self.__class__.__name__, representation)
 
     def __add__(self, superTag):
         return self.__class__(self.__baseTag, *self.__superTags + (superTag,))
@@ -318,7 +320,7 @@
         Returns
         -------
         : :py:class:`bool`
-            `True` if callee is a supertype of *tagSet*
+            :obj:`True` if callee is a supertype of *tagSet*
         """
         if len(tagSet) < self.__lenOfSuperTags:
             return False
diff --git a/pyasn1/type/tagmap.py b/pyasn1/type/tagmap.py
index e53a14d..6f5163b 100644
--- a/pyasn1/type/tagmap.py
+++ b/pyasn1/type/tagmap.py
@@ -56,16 +56,16 @@
         return iter(self.__presentTypes)
 
     def __repr__(self):
-        representation = '%s object at 0x%x' % (self.__class__.__name__, id(self))
+        representation = '%s object' % self.__class__.__name__
 
         if self.__presentTypes:
-            representation += ' present %s' % repr(self.__presentTypes)
+            representation += ', present %s' % repr(self.__presentTypes)
 
         if self.__skipTypes:
-            representation += ' skip %s' % repr(self.__skipTypes)
+            representation += ', skip %s' % repr(self.__skipTypes)
 
         if self.__defaultType is not None:
-            representation += ' default %s' % repr(self.__defaultType)
+            representation += ', default %s' % repr(self.__defaultType)
 
         return '<%s>' % representation
 
diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py
index 7fab69f..b39c533 100644
--- a/pyasn1/type/univ.py
+++ b/pyasn1/type/univ.py
@@ -31,15 +31,17 @@
 # "Simple" ASN.1 types (yet incomplete)
 
 
-class Integer(base.AbstractSimpleAsn1Item):
-    """Create |ASN.1| type or object.
+class Integer(base.SimpleAsn1Type):
+    """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python :class:`int` objects.
+    |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 integer or string literal or |ASN.1| class instance.
+        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)
@@ -52,7 +54,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -94,13 +96,13 @@
     namedValues = namedval.NamedValues()
 
     # Optimization for faster codec lookup
-    typeId = base.AbstractSimpleAsn1Item.getTypeId()
+    typeId = base.SimpleAsn1Type.getTypeId()
 
     def __init__(self, value=noValue, **kwargs):
         if 'namedValues' not in kwargs:
             kwargs['namedValues'] = self.namedValues
 
-        base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs)
+        base.SimpleAsn1Type.__init__(self, value, **kwargs)
 
     def __and__(self, value):
         return self.clone(self._value & value)
@@ -187,7 +189,7 @@
         def __rdivmod__(self, value):
             return self.clone(divmod(value, self._value))
 
-        __hash__ = base.AbstractSimpleAsn1Item.__hash__
+        __hash__ = base.SimpleAsn1Type.__hash__
 
     def __int__(self):
         return int(self._value)
@@ -276,14 +278,16 @@
 
 
 class Boolean(Integer):
-    """Create |ASN.1| type or object.
+    """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python :class:`int` objects.
+    |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 integer or boolean or string literal or |ASN.1| class instance.
+        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)
@@ -296,7 +300,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -355,17 +359,19 @@
         return self.bitLength
 
 
-class BitString(base.AbstractSimpleAsn1Item):
+class BitString(base.SimpleAsn1Type):
     """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type both Python :class:`tuple` (as a tuple
+    |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 integer or string literal representing binary or hexadecimal
-        number or sequence of integer bits 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)
@@ -386,7 +392,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -432,7 +438,7 @@
     namedValues = namedval.NamedValues()
 
     # Optimization for faster codec lookup
-    typeId = base.AbstractSimpleAsn1Item.getTypeId()
+    typeId = base.SimpleAsn1Type.getTypeId()
 
     defaultBinValue = defaultHexValue = noValue
 
@@ -461,7 +467,7 @@
         if 'namedValues' not in kwargs:
             kwargs['namedValues'] = self.namedValues
 
-        base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs)
+        base.SimpleAsn1Type.__init__(self, value, **kwargs)
 
     def __str__(self):
         return self.asBinary()
@@ -720,18 +726,22 @@
         return True
 
 
-class OctetString(base.AbstractSimpleAsn1Item):
+class OctetString(base.SimpleAsn1Type):
     """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python 2 :class:`str` or Python 3 :class:`bytes`.
-    When used in Unicode context, |ASN.1| type assumes "|encoding|" serialisation.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its
+    objects are immutable and duck-type Python 2 :class:`str` or
+    Python 3 :class:`bytes`. When used in Unicode context, |ASN.1| type
+    assumes "|encoding|" serialisation.
 
     Keyword Args
     ------------
-    value: :class:`str`, :class:`bytes` or |ASN.1| object
-        string (Python 2) or bytes (Python 3), alternatively unicode object
-        (Python 2) or string (Python 3) representing character string to be
-        serialised into octets (note `encoding` parameter) or |ASN.1| object.
+    value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
+        class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
+        class:`unicode` object (Python 2) or :class:`str` (Python 3)
+        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)
@@ -754,7 +764,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -786,7 +796,7 @@
     subtypeSpec = constraint.ConstraintsIntersection()
 
     # Optimization for faster codec lookup
-    typeId = base.AbstractSimpleAsn1Item.getTypeId()
+    typeId = base.SimpleAsn1Type.getTypeId()
 
     defaultBinValue = defaultHexValue = noValue
     encoding = 'iso-8859-1'
@@ -816,26 +826,33 @@
         if 'encoding' not in kwargs:
             kwargs['encoding'] = self.encoding
 
-        base.AbstractSimpleAsn1Item.__init__(self, value, **kwargs)
+        base.SimpleAsn1Type.__init__(self, value, **kwargs)
 
     if sys.version_info[0] <= 2:
         def prettyIn(self, value):
             if isinstance(value, str):
                 return value
+
             elif isinstance(value, unicode):
                 try:
                     return value.encode(self.encoding)
+
                 except (LookupError, UnicodeEncodeError):
-                    raise error.PyAsn1Error(
-                        "Can't encode string '%s' with codec %s" % (value, self.encoding)
+                    exc = sys.exc_info()[1]
+                    raise error.PyAsn1UnicodeEncodeError(
+                        "Can't encode string '%s' with codec "
+                        "%s" % (value, self.encoding), exc
                     )
+
             elif isinstance(value, (tuple, list)):
                 try:
                     return ''.join([chr(x) for x in value])
+
                 except ValueError:
                     raise error.PyAsn1Error(
                         "Bad %s initializer '%s'" % (self.__class__.__name__, value)
                     )
+
             else:
                 return str(value)
 
@@ -847,8 +864,10 @@
                 return self._value.decode(self.encoding)
 
             except UnicodeDecodeError:
-                raise error.PyAsn1Error(
-                    "Can't decode string '%s' with codec %s" % (self._value, self.encoding)
+                exc = sys.exc_info()[1]
+                raise error.PyAsn1UnicodeDecodeError(
+                    "Can't decode string '%s' with codec "
+                    "%s" % (self._value, self.encoding), exc
                 )
 
         def asOctets(self):
@@ -861,19 +880,26 @@
         def prettyIn(self, value):
             if isinstance(value, bytes):
                 return value
+
             elif isinstance(value, str):
                 try:
                     return value.encode(self.encoding)
+
                 except UnicodeEncodeError:
-                    raise error.PyAsn1Error(
-                        "Can't encode string '%s' with '%s' codec" % (value, self.encoding)
+                    exc = sys.exc_info()[1]
+                    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.AbstractSimpleAsn1Item):  # this mostly targets Integer objects
+
+            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)
 
@@ -882,8 +908,11 @@
                 return self._value.decode(self.encoding)
 
             except UnicodeDecodeError:
-                raise error.PyAsn1Error(
-                    "Can't decode string '%s' with '%s' codec at '%s'" % (self._value, self.encoding, self.__class__.__name__)
+                exc = sys.exc_info()[1]
+                raise error.PyAsn1UnicodeDecodeError(
+                    "Can't decode string '%s' with '%s' codec at "
+                    "'%s'" % (self._value, self.encoding,
+                              self.__class__.__name__), exc
                 )
 
         def __bytes__(self):
@@ -1028,19 +1057,22 @@
 class Null(OctetString):
     """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python :class:`str` objects (always empty).
+    |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 :py:class:`~pyasn1.type.univ.Null` object
-        Python empty string literal or any object that evaluates to `False`
+    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
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -1081,15 +1113,18 @@
 numericTypes = intTypes + (float,)
 
 
-class ObjectIdentifier(base.AbstractSimpleAsn1Item):
+class ObjectIdentifier(base.SimpleAsn1Type):
     """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python :class:`tuple` objects (tuple of non-negative integers).
+    |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 string literal 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)
@@ -1099,7 +1134,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -1131,7 +1166,7 @@
     subtypeSpec = constraint.ConstraintsIntersection()
 
     # Optimization for faster codec lookup
-    typeId = base.AbstractSimpleAsn1Item.getTypeId()
+    typeId = base.SimpleAsn1Type.getTypeId()
 
     def __add__(self, other):
         return self.clone(self._value + other)
@@ -1173,8 +1208,8 @@
         Returns
         -------
         : :class:`bool`
-            :class:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object
-            or :class:`False` otherwise.
+            :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):
@@ -1214,10 +1249,11 @@
         return '.'.join([str(x) for x in value])
 
 
-class Real(base.AbstractSimpleAsn1Item):
+class Real(base.SimpleAsn1Type):
     """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python :class:`float` objects.
+    |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.
 
@@ -1225,7 +1261,8 @@
     ------------
     value: :class:`tuple`, :class:`float` or |ASN.1| object
         Python sequence of :class:`int` (representing mantissa, base and
-        exponent) or float instance or *Real* class instance.
+        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)
@@ -1235,7 +1272,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -1278,7 +1315,7 @@
     subtypeSpec = constraint.ConstraintsIntersection()
 
     # Optimization for faster codec lookup
-    typeId = base.AbstractSimpleAsn1Item.getTypeId()
+    typeId = base.SimpleAsn1Type.getTypeId()
 
     @staticmethod
     def __normalizeBase10(value):
@@ -1342,8 +1379,8 @@
         Returns
         -------
         : :class:`bool`
-            :class:`True` if calling object represents plus infinity
-            or :class:`False` otherwise.
+            :obj:`True` if calling object represents plus infinity
+            or :obj:`False` otherwise.
 
         """
         return self._value == self._plusInf
@@ -1355,8 +1392,8 @@
         Returns
         -------
         : :class:`bool`
-            :class:`True` if calling object represents minus infinity
-            or :class:`False` otherwise.
+            :obj:`True` if calling object represents minus infinity
+            or :obj:`False` otherwise.
         """
         return self._value == self._minusInf
 
@@ -1479,7 +1516,7 @@
         def __bool__(self):
             return bool(float(self))
 
-        __hash__ = base.AbstractSimpleAsn1Item.__hash__
+        __hash__ = base.SimpleAsn1Type.__hash__
 
     def __getitem__(self, idx):
         if self._value in self._inf:
@@ -1500,14 +1537,16 @@
 
 
 class Enumerated(Integer):
-    """Create |ASN.1| type or object.
+    """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python :class:`int` objects.
+    |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 integer or string literal or |ASN.1| class instance.
+        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)
@@ -1520,7 +1559,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
@@ -1566,10 +1605,11 @@
 
 # "Structured" ASN.1 types
 
-class SequenceOfAndSetOfBase(base.AbstractConstructedAsn1Item):
-    """Create |ASN.1| type.
+class SequenceOfAndSetOfBase(base.ConstructedAsn1Type):
+    """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are mutable and duck-type Python :class:`list` objects.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
+    its objects are mutable and duck-type Python :class:`list` objects.
 
     Keyword Args
     ------------
@@ -1610,7 +1650,9 @@
                     raise error.PyAsn1Error('Conflicting positional and keyword params!')
                 kwargs['componentType'] = value
 
-        base.AbstractConstructedAsn1Item.__init__(self, **kwargs)
+        self._componentValues = noValue
+
+        base.ConstructedAsn1Type.__init__(self, **kwargs)
 
     # Python list protocol
 
@@ -1628,24 +1670,36 @@
         except error.PyAsn1Error:
             raise IndexError(sys.exc_info()[1])
 
-    def clear(self):
-        self._componentValues = []
-
     def append(self, value):
-        self[len(self)] = value
+        if self._componentValues is noValue:
+            pos = 0
+
+        else:
+            pos = len(self._componentValues)
+
+        self[pos] = value
 
     def count(self, value):
-        return self._componentValues.count(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 self._componentValues.index(value, start, stop)
+            return indices[values.index(value, start, stop)]
 
         except error.PyAsn1Error:
             raise ValueError(sys.exc_info()[1])
@@ -1654,15 +1708,24 @@
         self._componentValues.reverse()
 
     def sort(self, key=None, reverse=False):
-        self._componentValues.sort(key=key, reverse=reverse)
+        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):
-        return iter(self._componentValues)
+        for idx in range(0, len(self)):
+            yield self.getComponentByPosition(idx)
 
     def _cloneComponentValues(self, myClone, cloneValueFlag):
-        for idx, componentValue in enumerate(self._componentValues):
+        for idx, componentValue in self._componentValues.items():
             if componentValue is not noValue:
-                if isinstance(componentValue, base.AbstractConstructedAsn1Item):
+                if isinstance(componentValue, base.ConstructedAsn1Type):
                     myClone.setComponentByPosition(
                         idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
                     )
@@ -1689,8 +1752,8 @@
             object instead of the requested component.
 
         instantiate: :class:`bool`
-            If `True` (default), inner component will be automatically instantiated.
-            If 'False' either existing component or the `noValue` object will be
+            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
@@ -1735,10 +1798,21 @@
             # 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 IndexError:
+        except (KeyError, error.PyAsn1Error):
             if not instantiate:
                 return default
 
@@ -1773,15 +1847,16 @@
         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 `False`, skip constraints validation
+             If :obj:`False`, skip constraints validation
 
         matchTags: :class:`bool`
-             If `False`, skip component tags matching
+             If :obj:`False`, skip component tags matching
 
         matchConstraints: :class:`bool`
-             If `False`, skip component constraints matching
+             If :obj:`False`, skip component constraints matching
 
         Returns
         -------
@@ -1789,38 +1864,77 @@
 
         Raises
         ------
-        IndexError:
+        ~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
 
-        try:
-            currentValue = self._componentValues[idx]
-        except IndexError:
-            currentValue = noValue
+        if self._componentValues is noValue:
+            componentValues = {}
 
-            if len(self._componentValues) < idx:
-                raise error.PyAsn1Error('Component index out of range')
+        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.AbstractSimpleAsn1Item):
+            if (componentType is not None and
+                    isinstance(componentType, base.SimpleAsn1Type)):
                 value = componentType.clone(value=value)
-            elif currentValue is not noValue and isinstance(currentValue, base.AbstractSimpleAsn1Item):
+
+            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:
-            if self.strictConstraints:
-                if not componentType.isSameTypeWith(value, matchTags, matchConstraints):
-                    raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
+                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, matchTags, 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))
+
             else:
-                if not componentType.isSuperTypeOf(value, matchTags, matchConstraints):
-                    raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
+                if not componentType.isSuperTypeOf(
+                        value, matchTags, matchConstraints):
+                    raise error.PyAsn1Error(
+                        'Component value is tag-incompatible: '
+                        '%r vs %r' % (value, componentType))
 
         if verifyConstraints and value.isValue:
             try:
@@ -1830,10 +1944,9 @@
                 exType, exValue, exTb = sys.exc_info()
                 raise exType('%s at %s' % (exValue, self.__class__.__name__))
 
-        if currentValue is noValue:
-            self._componentValues.append(value)
-        else:
-            self._componentValues[idx] = value
+        componentValues[idx] = value
+
+        self._componentValues = componentValues
 
         return self
 
@@ -1842,16 +1955,44 @@
         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'
-        for idx, componentValue in enumerate(self._componentValues):
+
+        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):
@@ -1867,17 +2008,17 @@
     def isValue(self):
         """Indicate that |ASN.1| object represents ASN.1 value.
 
-        If *isValue* is `False` then this object represents just ASN.1 schema.
+        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
 
-        If *isValue* is `True` then, in addition to its ASN.1 schema features,
-        this object can also be used like a Python built-in object (e.g. `int`,
-        `str`, `dict` etc.).
+        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`
-            :class:`False` if object represents just ASN.1 schema.
-            :class:`True` if object represents ASN.1 schema and can be used as a normal value.
+            :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
         ----
@@ -1890,7 +2031,13 @@
         The PyASN1 value objects can **additionally** participate in many operations
         involving regular Python objects (e.g. arithmetic, comprehension etc).
         """
-        for componentValue in self._componentValues:
+        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
 
@@ -1951,10 +2098,11 @@
     typeId = SequenceOfAndSetOfBase.getTypeId()
 
 
-class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
-    """Create |ASN.1| type.
+class SequenceAndSetBase(base.ConstructedAsn1Type):
+    """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are mutable and duck-type Python :class:`dict` objects.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
+    its objects are mutable and duck-type Python :class:`dict` objects.
 
     Keyword Args
     ------------
@@ -2042,8 +2190,12 @@
 
 
     def __init__(self, **kwargs):
-        base.AbstractConstructedAsn1Item.__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):
@@ -2086,6 +2238,9 @@
         else:
             return key in self._dynamicNames
 
+    def __len__(self):
+        return len(self._componentValues)
+
     def __iter__(self):
         return iter(self.componentType or self._dynamicNames)
 
@@ -2112,13 +2267,36 @@
             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.AbstractConstructedAsn1Item):
+                if isinstance(componentValue, base.ConstructedAsn1Type):
                     myClone.setComponentByPosition(
                         idx, componentValue.clone(cloneValueFlag=cloneValueFlag)
                     )
@@ -2142,14 +2320,16 @@
             object instead of the requested component.
 
         instantiate: :class:`bool`
-            If `True` (default), inner component will be automatically instantiated.
-            If 'False' either existing component or the `noValue` object will be
-            returned.
+            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
+            Instantiate |ASN.1| component type or return existing
+            component value
         """
         if self._componentTypeLen:
             idx = self.componentType.getPositionByName(name)
@@ -2180,15 +2360,16 @@
         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 `False`, skip constraints validation
+             If :obj:`False`, skip constraints validation
 
         matchTags: :class:`bool`
-             If `False`, skip component tags matching
+             If :obj:`False`, skip component tags matching
 
         matchConstraints: :class:`bool`
-             If `False`, skip component constraints matching
+             If :obj:`False`, skip component constraints matching
 
         Returns
         -------
@@ -2226,9 +2407,10 @@
             object instead of the requested component.
 
         instantiate: :class:`bool`
-            If `True` (default), inner component will be automatically instantiated.
-            If 'False' either existing component or the `noValue` object will be
-            returned.
+            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
         -------
@@ -2275,7 +2457,11 @@
             s.getComponentByPosition(0, instantiate=False)
         """
         try:
-            componentValue = self._componentValues[idx]
+            if self._componentValues is noValue:
+                componentValue = noValue
+
+            else:
+                componentValue = self._componentValues[idx]
 
         except IndexError:
             componentValue = noValue
@@ -2317,15 +2503,16 @@
         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 `False`, skip constraints validation
+             If :obj:`False`, skip constraints validation
 
         matchTags: :class:`bool`
-             If `False`, skip component tags matching
+             If :obj:`False`, skip component tags matching
 
         matchConstraints: :class:`bool`
-             If `False`, skip component constraints matching
+             If :obj:`False`, skip component constraints matching
 
         Returns
         -------
@@ -2334,8 +2521,14 @@
         componentType = self.componentType
         componentTypeLen = self._componentTypeLen
 
+        if self._componentValues is noValue:
+            componentValues = []
+
+        else:
+            componentValues = self._componentValues
+
         try:
-            currentValue = self._componentValues[idx]
+            currentValue = componentValues[idx]
 
         except IndexError:
             currentValue = noValue
@@ -2343,12 +2536,12 @@
                 if componentTypeLen < idx:
                     raise error.PyAsn1Error('component index out of range')
 
-                self._componentValues = [noValue] * componentTypeLen
+                componentValues = [noValue] * componentTypeLen
 
         if value is noValue:
             if componentTypeLen:
                 value = componentType.getTypeByPosition(idx)
-                if isinstance(value, base.AbstractConstructedAsn1Item):
+                if isinstance(value, base.ConstructedAsn1Type):
                     value = value.clone(cloneValueFlag=componentType[idx].isDefaulted)
 
             elif currentValue is noValue:
@@ -2357,13 +2550,13 @@
         elif not isinstance(value, base.Asn1Item):
             if componentTypeLen:
                 subComponentType = componentType.getTypeByPosition(idx)
-                if isinstance(subComponentType, base.AbstractSimpleAsn1Item):
+                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.AbstractSimpleAsn1Item):
+            elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type):
                 value = currentValue.clone(value=value)
 
             else:
@@ -2389,32 +2582,35 @@
                 raise exType('%s at %s' % (exValue, self.__class__.__name__))
 
         if componentTypeLen or idx in self._dynamicNames:
-            self._componentValues[idx] = value
+            componentValues[idx] = value
 
-        elif len(self._componentValues) == idx:
-            self._componentValues.append(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 `False` then this object represents just ASN.1 schema.
+        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
 
-        If *isValue* is `True` then, in addition to its ASN.1 schema features,
-        this object can also be used like a Python built-in object (e.g. `int`,
-        `str`, `dict` etc.).
+        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`
-            :class:`False` if object represents just ASN.1 schema.
-            :class:`True` if object represents ASN.1 schema and can be used as a normal value.
+            :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
         ----
@@ -2426,7 +2622,16 @@
 
         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:
@@ -2497,7 +2702,6 @@
         if self._componentTypeLen:
             return self.componentType[idx].name
 
-
 class Sequence(SequenceAndSetBase):
     __doc__ = SequenceAndSetBase.__doc__
 
@@ -2583,9 +2787,10 @@
             object instead of the requested component.
 
         instantiate: :class:`bool`
-            If `True` (default), inner component will be automatically instantiated.
-            If 'False' either existing component or the `noValue` object will be
-            returned.
+            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
         -------
@@ -2621,18 +2826,19 @@
         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 `False`, skip constraints validation
+            If :obj:`False`, skip constraints validation
 
         matchTags: :class:`bool`
-            If `False`, skip component tags matching
+            If :obj:`False`, skip component tags matching
 
         matchConstraints: :class:`bool`
-            If `False`, skip component constraints matching
+            If :obj:`False`, skip component constraints matching
 
         innerFlag: :class:`bool`
-            If `True`, search for matching *tagSet* recursively.
+            If :obj:`True`, search for matching *tagSet* recursively.
 
         Returns
         -------
@@ -2664,9 +2870,10 @@
 
 
 class Choice(Set):
-    """Create |ASN.1| type.
+    """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are mutable and duck-type Python :class:`dict` objects.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`,
+    its objects are mutable and duck-type Python :class:`list` objects.
 
     Keyword Args
     ------------
@@ -2811,7 +3018,7 @@
                 tagSet = component.effectiveTagSet
             else:
                 tagSet = component.tagSet
-            if isinstance(component, base.AbstractConstructedAsn1Item):
+            if isinstance(component, base.ConstructedAsn1Type):
                 myClone.setComponentByType(
                     tagSet, component.clone(cloneValueFlag=cloneValueFlag)
                 )
@@ -2849,15 +3056,16 @@
             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 `False`, skip constraints validation
+            If :obj:`False`, skip constraints validation
 
         matchTags: :class:`bool`
-            If `False`, skip component tags matching
+            If :obj:`False`, skip component tags matching
 
         matchConstraints: :class:`bool`
-            If `False`, skip component constraints matching
+            If :obj:`False`, skip component constraints matching
 
         Returns
         -------
@@ -2927,17 +3135,18 @@
     def isValue(self):
         """Indicate that |ASN.1| object represents ASN.1 value.
 
-        If *isValue* is `False` then this object represents just ASN.1 schema.
+        If *isValue* is :obj:`False` then this object represents just ASN.1 schema.
 
-        If *isValue* is `True` then, in addition to its ASN.1 schema features,
-        this object can also be used like a Python built-in object (e.g. `int`,
-        `str`, `dict` etc.).
+        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`
-            :class:`False` if object represents just ASN.1 schema.
-            :class:`True` if object represents ASN.1 schema and can be used as a normal value.
+            :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
         ----
@@ -2959,7 +3168,7 @@
 
     def clear(self):
         self._currentIdx = None
-        Set.clear(self)
+        return Set.clear(self)
 
     # compatibility stubs
 
@@ -2970,16 +3179,19 @@
 class Any(OctetString):
     """Create |ASN.1| schema or value object.
 
-    |ASN.1| objects are immutable and duck-type Python 2 :class:`str` or Python 3
-    :class:`bytes`. When used in Unicode context, |ASN.1| type assumes "|encoding|"
-    serialisation.
+    |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
+    its objects are immutable and duck-type Python 2 :class:`str` or Python 3
+    :class:`bytes`. When used in Unicode context, |ASN.1| type assumes
+    "|encoding|" serialisation.
 
     Keyword Args
     ------------
-    value: :class:`str`, :class:`bytes` or |ASN.1| object
-        string (Python 2) or bytes (Python 3), alternatively unicode object
-        (Python 2) or string (Python 3) representing character string to be
-        serialised into octets (note `encoding` parameter) or |ASN.1| object.
+    value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
+        :class:`str` (Python 2) or :class:`bytes` (Python 3), alternatively
+        :class:`unicode` object (Python 2) or :class:`str` (Python 3)
+        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)
@@ -3002,7 +3214,7 @@
 
     Raises
     ------
-    :py:class:`~pyasn1.error.PyAsn1Error`
+    ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
         On constraint violation or bad initializer.
 
     Examples
diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py
index 8b6d590..089f0f3 100644
--- a/tests/codec/ber/test_decoder.py
+++ b/tests/codec/ber/test_decoder.py
@@ -835,7 +835,7 @@
         ) == (self.s, null)
 
 
-class SequenceDecoderWithUnaggedOpenTypesTestCase(BaseTestCase):
+class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase):
     def setUp(self):
         openType = opentype.OpenType(
             'id',
@@ -972,6 +972,159 @@
         assert s[1] == univ.OctetString(hexValue='02010C')
 
 
+class SequenceDecoderWithUnaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()),
+                                    openType=openType)
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99,
+                       107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1][0] == univ.OctetString('quick brown')
+
+    def testDecodeOpenTypesUnknownType(self):
+        try:
+            s, r = decoder.decode(
+                ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s,
+                decodeOpenTypes=True
+            )
+
+        except PyAsn1Error:
+            pass
+
+        else:
+            assert False, 'unknown open type tolerated'
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 3, 49, 3, 2, 1, 12)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010c')
+
+    def testDontDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == ints2octs((2, 1, 12))
+
+    def testDontDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99,
+                       107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1][0] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114,
+                                     111, 119, 110))
+
+
+class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.SetOf(
+                        componentType=univ.Any().subtype(
+                            implicitTag=tag.Tag(
+                                tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.SetOf(
+                        componentType=univ.Any().subtype(
+                            explicitTag=tag.Tag(
+                                tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010C')
+
+
 class SetDecoderTestCase(BaseTestCase):
     def setUp(self):
         BaseTestCase.setUp(self)
@@ -1429,6 +1582,38 @@
         assert self.s == s
 
 
+class ErrorOnDecodingTestCase(BaseTestCase):
+
+    def testErrorCondition(self):
+        decode = decoder.Decoder(decoder.tagMap, decoder.typeMap)
+
+        try:
+            asn1Object, rest = decode(str2octs('abc'))
+
+        except PyAsn1Error:
+            exc = sys.exc_info()[1]
+            assert isinstance(exc, PyAsn1Error), (
+                'Unexpected exception raised %r' % (exc,))
+
+        else:
+            assert False, 'Unexpected decoder result %r' % (asn1Object,)
+
+    def testRawDump(self):
+        decode = decoder.Decoder(decoder.tagMap, decoder.typeMap)
+
+        decode.defaultErrorState = decoder.stDumpRawValue
+
+        asn1Object, rest = decode(ints2octs(
+            (31, 8, 2, 1, 1, 131, 3, 2, 1, 12)))
+
+        assert isinstance(asn1Object, univ.Any), (
+            'Unexpected raw dump type %r' % (asn1Object,))
+        assert asn1Object.asNumbers() == (31, 8, 2, 1, 1), (
+            'Unexpected raw dump value %r' % (asn1Object,))
+        assert rest == ints2octs((131, 3, 2, 1, 12)), (
+            'Unexpected rest of substrate after raw dump %r' % rest)
+
+
 suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
 
 if __name__ == '__main__':
diff --git a/tests/codec/ber/test_encoder.py b/tests/codec/ber/test_encoder.py
index 26819bd..38d75c0 100644
--- a/tests/codec/ber/test_encoder.py
+++ b/tests/codec/ber/test_encoder.py
@@ -476,6 +476,7 @@
 class SequenceOfEncoderTestCase(BaseTestCase):
     def testEmpty(self):
         s = univ.SequenceOf()
+        s.clear()
         assert encoder.encode(s) == ints2octs((48, 0))
 
     def testDefMode(self):
@@ -570,6 +571,7 @@
 class SetOfEncoderTestCase(BaseTestCase):
     def testEmpty(self):
         s = univ.SetOf()
+        s.clear()
         assert encoder.encode(s) == ints2octs((49, 0))
 
     def testDefMode(self):
@@ -760,7 +762,7 @@
         self.s[1] = univ.Integer(12)
 
         assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
-            (48, 6, 2, 1, 1, 2, 1, 12)
+            (48, 5, 2, 1, 1, 49, 50)
         )
 
     def testEncodeOpenTypeChoiceTwo(self):
@@ -770,7 +772,7 @@
         self.s[1] = univ.OctetString('quick brown')
 
         assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
-            (48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)
+            (48, 14, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)
         )
 
     def testEncodeOpenTypeUnknownId(self):
@@ -821,7 +823,7 @@
         self.s[1] = univ.Integer(12)
 
         assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
-            (48, 8, 2, 1, 1, 131, 3, 2, 1, 12)
+            (48, 9, 2, 1, 1, 131, 4, 131, 2, 49, 50)
         )
 
 
@@ -848,7 +850,131 @@
         self.s[1] = univ.Integer(12)
 
         assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
-            (48, 8, 2, 1, 1, 163, 3, 2, 1, 12)
+            (48, 9, 2, 1, 1, 163, 4, 163, 2, 49, 50)
+    )
+
+
+class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any()), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 7, 2, 1, 1, 49, 2, 49, 50)
+        )
+
+    def testEncodeOpenTypeChoiceTwo(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.OctetString('quick brown'))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 16, 2, 1, 2, 49, 11, 113, 117, 105, 99, 107, 32, 98, 114,
+             111, 119, 110)
+        )
+
+    def testEncodeOpenTypeUnknownId(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.ObjectIdentifier('1.3.6'))
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+    def testEncodeOpenTypeIncompatibleType(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.ObjectIdentifier('1.3.6'))
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+
+class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any().subtype(
+                        implicitTag=tag.Tag(
+                            tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 11, 2, 1, 1, 49, 6, 131, 4, 131, 2, 49, 50)
+        )
+
+
+class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any().subtype(
+                        explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 11, 2, 1, 1, 49, 6, 163, 4, 163, 2, 49, 50)
         )
 
 
diff --git a/tests/codec/cer/test_decoder.py b/tests/codec/cer/test_decoder.py
index d4e00ab..bb5ce93 100644
--- a/tests/codec/cer/test_decoder.py
+++ b/tests/codec/cer/test_decoder.py
@@ -13,6 +13,10 @@
 
 from tests.base import BaseTestCase
 
+from pyasn1.type import tag
+from pyasn1.type import namedtype
+from pyasn1.type import opentype
+from pyasn1.type import univ
 from pyasn1.codec.cer import decoder
 from pyasn1.compat.octets import ints2octs, str2octs, null
 from pyasn1.error import PyAsn1Error
@@ -65,6 +69,304 @@
     # TODO: test failures on short chunked and long unchunked substrate samples
 
 
+class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any(), openType=openType)
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)),
+            asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == 12
+
+    def testDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98,
+                114, 111, 119, 110, 0, 0)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1] == univ.OctetString('quick brown')
+
+    def testDecodeOpenTypesUnknownType(self):
+        try:
+            s, r = decoder.decode(
+                ints2octs((48, 128, 6, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s,
+                decodeOpenTypes=True
+            )
+
+        except PyAsn1Error:
+            pass
+
+        else:
+            assert False, 'unknown open type tolerated'
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 3, 6, 1, 12, 0, 0)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1] == univ.OctetString(hexValue='06010c')
+
+    def testDontDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == ints2octs((2, 1, 12))
+
+    def testDontDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98,
+                114, 111, 119, 110, 0, 0)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110))
+
+
+class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 1, 163, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 3, 163, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 1, 163, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 3, 163, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()),
+                                    openType=openType)
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 2, 49, 128, 4, 11, 113, 117, 105, 99,
+                       107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1][0] == univ.OctetString('quick brown')
+
+    def testDecodeOpenTypesUnknownType(self):
+        try:
+            s, r = decoder.decode(
+                ints2octs((48, 128, 6, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)),
+                asn1Spec=self.s, decodeOpenTypes=True
+            )
+
+        except PyAsn1Error:
+            pass
+
+        else:
+            assert False, 'unknown open type tolerated'
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 3, 49, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010c')
+
+    def testDontDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)),
+            asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == ints2octs((2, 1, 12))
+
+    def testDontDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 128, 2, 1, 2, 49, 128, 4, 11, 113, 117, 105, 99, 107, 32,
+                98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1][0] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114,
+                                     111, 119, 110))
+
+
+class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.SetOf(
+                        componentType=univ.Any().subtype(
+                            implicitTag=tag.Tag(
+                                tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.SetOf(
+                        componentType=univ.Any().subtype(
+                            explicitTag=tag.Tag(
+                                tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010C')
+
+
 suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
 
 if __name__ == '__main__':
diff --git a/tests/codec/cer/test_encoder.py b/tests/codec/cer/test_encoder.py
index d9d9212..e155571 100644
--- a/tests/codec/cer/test_encoder.py
+++ b/tests/codec/cer/test_encoder.py
@@ -15,6 +15,7 @@
 
 from pyasn1.type import tag
 from pyasn1.type import namedtype
+from pyasn1.type import opentype
 from pyasn1.type import univ
 from pyasn1.type import useful
 from pyasn1.codec.cer import encoder
@@ -87,7 +88,7 @@
     def testDecimalCommaPoint(self):
         try:
             assert encoder.encode(
-                    useful.GeneralizedTime('20150501120112,1Z')
+                useful.GeneralizedTime('20150501120112,1Z')
              )
         except PyAsn1Error:
             pass
@@ -96,9 +97,29 @@
 
     def testWithSubseconds(self):
         assert encoder.encode(
-                    useful.GeneralizedTime('20170801120112.59Z')
+                useful.GeneralizedTime('20170801120112.59Z')
              ) == ints2octs((24, 18, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 53, 57, 90))
 
+    def testWithSubsecondsWithZeros(self):
+        assert encoder.encode(
+                useful.GeneralizedTime('20170801120112.099Z')
+             ) == ints2octs((24, 18, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 57, 57, 90))
+
+    def testWithSubsecondsMax(self):
+        assert encoder.encode(
+                useful.GeneralizedTime('20170801120112.999Z')
+             ) == ints2octs((24, 19, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 57, 57, 57, 90))
+
+    def testWithSubsecondsMin(self):
+        assert encoder.encode(
+                useful.GeneralizedTime('20170801120112.000Z')
+             ) == ints2octs((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90))
+
+    def testWithSubsecondsDanglingDot(self):
+        assert encoder.encode(
+                useful.GeneralizedTime('20170801120112.Z')
+             ) == ints2octs((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90))
+
     def testWithSeconds(self):
         assert encoder.encode(
                     useful.GeneralizedTime('20170801120112Z')
@@ -155,6 +176,7 @@
 class SequenceOfEncoderTestCase(BaseTestCase):
     def testEmpty(self):
         s = univ.SequenceOf()
+        s.clear()
         assert encoder.encode(s) == ints2octs((48, 128, 0, 0))
 
     def testDefMode1(self):
@@ -219,6 +241,7 @@
 class SetOfEncoderTestCase(BaseTestCase):
     def testEmpty(self):
         s = univ.SetOf()
+        s.clear()
         assert encoder.encode(s) == ints2octs((49, 128, 0, 0))
 
     def testDefMode1(self):
@@ -363,7 +386,7 @@
         ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
 
 
-class SetWithChoiceWithSchemaEncoderTestCase(BaseTestCase):
+class SetEncoderWithChoiceWithSchemaEncoderTestCase(BaseTestCase):
     def setUp(self):
         BaseTestCase.setUp(self)
         c = univ.Choice(componentType=namedtype.NamedTypes(
@@ -381,7 +404,7 @@
         assert encoder.encode(self.s) == ints2octs((49, 128, 1, 1, 255, 5, 0, 0, 0))
 
 
-class SetWithTaggedChoiceEncoderTestCase(BaseTestCase):
+class SetEncoderWithTaggedChoiceEncoderTestCase(BaseTestCase):
 
     def testWithUntaggedChoice(self):
 
@@ -424,33 +447,6 @@
         assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 65, 167, 128, 1, 1, 255, 0, 0, 0, 0))
 
 
-class SetEncoderTestCase(BaseTestCase):
-    def setUp(self):
-        BaseTestCase.setUp(self)
-        self.s = univ.Set()
-        self.s.setComponentByPosition(0, univ.Null(''))
-        self.s.setComponentByPosition(1, univ.OctetString('quick brown'))
-        self.s.setComponentByPosition(2, univ.Integer(1))
-
-    def testIndefMode(self):
-        assert encoder.encode(self.s) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
-
-    def testWithOptionalIndefMode(self):
-        assert encoder.encode(
-            self.s
-        ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
-
-    def testWithDefaultedIndefMode(self):
-        assert encoder.encode(
-            self.s
-        ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
-
-    def testWithOptionalAndDefaultedIndefMode(self):
-        assert encoder.encode(
-            self.s
-        ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
-
-
 class SequenceEncoderTestCase(BaseTestCase):
     def setUp(self):
         BaseTestCase.setUp(self)
@@ -532,6 +528,248 @@
         ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0))
 
 
+class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any(), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1] = univ.Integer(12)
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 1, 49, 50, 0, 0)
+        )
+
+    def testEncodeOpenTypeChoiceTwo(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1] = univ.OctetString('quick brown')
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114,
+             111, 119, 110, 0, 0)
+        )
+
+    def testEncodeOpenTypeUnknownId(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1] = univ.ObjectIdentifier('1.3.6')
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+    def testEncodeOpenTypeIncompatibleType(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1] = univ.ObjectIdentifier('1.3.6')
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+
+class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1] = univ.Integer(12)
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 1, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0)
+        )
+
+
+class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1] = univ.Integer(12)
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 1, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0)
+        )
+
+
+class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any()), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 1, 49, 128, 49, 50, 0, 0, 0, 0)
+        )
+
+    def testEncodeOpenTypeChoiceTwo(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.OctetString('quick brown'))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 2, 49, 128, 113, 117, 105, 99, 107, 32, 98, 114,
+             111, 119, 110, 0, 0, 0, 0)
+        )
+
+    def testEncodeOpenTypeUnknownId(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.ObjectIdentifier('1.3.6'))
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+    def testEncodeOpenTypeIncompatibleType(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.ObjectIdentifier('1.3.6'))
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+
+class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any().subtype(
+                        implicitTag=tag.Tag(
+                            tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 1, 49, 128, 163, 128, 163, 128, 49, 50, 0, 0,
+             0, 0, 0, 0, 0, 0)
+        )
+
+
+class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any().subtype(
+                        explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 128, 2, 1, 1, 49, 128, 163, 128, 163, 128, 49, 50, 0, 0,
+             0, 0, 0, 0, 0, 0)
+        )
+
+
 class NestedOptionalSequenceEncoderTestCase(BaseTestCase):
     def setUp(self):
         BaseTestCase.setUp(self)
diff --git a/tests/codec/der/test_decoder.py b/tests/codec/der/test_decoder.py
index a76c435..51ce296 100644
--- a/tests/codec/der/test_decoder.py
+++ b/tests/codec/der/test_decoder.py
@@ -14,6 +14,10 @@
 
 from tests.base import BaseTestCase
 
+from pyasn1.type import tag
+from pyasn1.type import namedtype
+from pyasn1.type import opentype
+from pyasn1.type import univ
 from pyasn1.codec.der import decoder
 from pyasn1.compat.octets import ints2octs, null
 from pyasn1.error import PyAsn1Error
@@ -73,6 +77,296 @@
             assert 0, 'chunked encoding tolerated'
 
 
+class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any(), openType=openType)
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == 12
+
+    def testDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1] == univ.OctetString('quick brown')
+
+    def testDecodeOpenTypesUnknownType(self):
+        try:
+            s, r = decoder.decode(
+                ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s,
+                decodeOpenTypes=True
+            )
+
+        except PyAsn1Error:
+            pass
+
+        else:
+            assert False, 'unknown open type tolerated'
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 6, 2, 1, 3, 6, 1, 39)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1] == univ.OctetString(hexValue='060127')
+
+    def testDontDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == ints2octs((2, 1, 12))
+
+    def testDontDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110))
+
+
+class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 1, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 3, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 1, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 3, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithUnaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()),
+                                    openType=openType)
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99,
+                       107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1][0] == univ.OctetString('quick brown')
+
+    def testDecodeOpenTypesUnknownType(self):
+        try:
+            s, r = decoder.decode(
+                ints2octs((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s,
+                decodeOpenTypes=True
+            )
+
+        except PyAsn1Error:
+            pass
+
+        else:
+            assert False, 'unknown open type tolerated'
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 3, 49, 3, 2, 1, 12)), asn1Spec=self.s,
+            decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010c')
+
+    def testDontDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == ints2octs((2, 1, 12))
+
+    def testDontDecodeOpenTypesChoiceTwo(self):
+        s, r = decoder.decode(
+            ints2octs((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99,
+                       107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s
+        )
+        assert not r
+        assert s[0] == 2
+        assert s[1][0] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114,
+                                     111, 119, 110))
+
+
+class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.SetOf(
+                        componentType=univ.Any().subtype(
+                            implicitTag=tag.Tag(
+                                tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010C')
+
+
+class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType(
+                    'blob', univ.SetOf(
+                        componentType=univ.Any().subtype(
+                            explicitTag=tag.Tag(
+                                tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType
+                )
+            )
+        )
+
+    def testDecodeOpenTypesChoiceOne(self):
+        s, r = decoder.decode(
+            ints2octs((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 1
+        assert s[1][0] == 12
+
+    def testDecodeOpenTypesUnknownId(self):
+        s, r = decoder.decode(
+            ints2octs( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)),
+            asn1Spec=self.s, decodeOpenTypes=True
+        )
+        assert not r
+        assert s[0] == 3
+        assert s[1][0] == univ.OctetString(hexValue='02010C')
+
+
 suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
 
 if __name__ == '__main__':
diff --git a/tests/codec/der/test_encoder.py b/tests/codec/der/test_encoder.py
index 75835f2..912e32c 100644
--- a/tests/codec/der/test_encoder.py
+++ b/tests/codec/der/test_encoder.py
@@ -16,6 +16,7 @@
 
 from pyasn1.type import tag
 from pyasn1.type import namedtype
+from pyasn1.type import opentype
 from pyasn1.type import univ
 from pyasn1.codec.der import encoder
 from pyasn1.compat.octets import ints2octs
@@ -148,6 +149,246 @@
         assert encoder.encode(s) == ints2octs((49, 8, 4, 1, 65, 167, 3, 1, 1, 255))
 
 
+class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any(), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1] = univ.Integer(12)
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 5, 2, 1, 1, 49, 50)
+        )
+
+    def testEncodeOpenTypeChoiceTwo(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1] = univ.OctetString('quick brown')
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 14, 2, 1, 2, 113, 117, 105, 99, 107, 32,
+             98, 114, 111, 119, 110)
+        )
+
+    def testEncodeOpenTypeUnknownId(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1] = univ.ObjectIdentifier('1.3.6')
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+    def testEncodeOpenTypeIncompatibleType(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1] = univ.ObjectIdentifier('1.3.6')
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+
+class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1] = univ.Integer(12)
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 9, 2, 1, 1, 131, 4, 131, 2, 49, 50)
+        )
+
+
+class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1] = univ.Integer(12)
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 9, 2, 1, 1, 163, 4, 163, 2, 49, 50)
+        )
+
+
+class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any()), openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 7, 2, 1, 1, 49, 2, 49, 50)
+        )
+
+    def testEncodeOpenTypeChoiceTwo(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.OctetString('quick brown'))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 16, 2, 1, 2, 49, 11, 113, 117, 105, 99, 107, 32, 98, 114,
+             111, 119, 110)
+        )
+
+    def testEncodeOpenTypeUnknownId(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.ObjectIdentifier('1.3.6'))
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+    def testEncodeOpenTypeIncompatibleType(self):
+        self.s.clear()
+
+        self.s[0] = 2
+        self.s[1].append(univ.ObjectIdentifier('1.3.6'))
+
+        try:
+            encoder.encode(self.s, asn1Spec=self.s)
+
+        except PyAsn1Error:
+            assert False, 'incompatible open type tolerated'
+
+
+class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any().subtype(
+                        implicitTag=tag.Tag(
+                            tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 11, 2, 1, 1, 49, 6, 131, 4, 131, 2, 49, 50)
+        )
+
+
+class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase):
+    def setUp(self):
+        BaseTestCase.setUp(self)
+
+        openType = opentype.OpenType(
+            'id',
+            {1: univ.Integer(),
+             2: univ.OctetString()}
+        )
+        self.s = univ.Sequence(
+            componentType=namedtype.NamedTypes(
+                namedtype.NamedType('id', univ.Integer()),
+                namedtype.NamedType('blob', univ.SetOf(
+                    componentType=univ.Any().subtype(
+                        explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
+                    openType=openType)
+            )
+        )
+
+    def testEncodeOpenTypeChoiceOne(self):
+        self.s.clear()
+
+        self.s[0] = 1
+        self.s[1].append(univ.Integer(12))
+
+        assert encoder.encode(self.s, asn1Spec=self.s) == ints2octs(
+            (48, 11, 2, 1, 1, 49, 6, 163, 4, 163, 2, 49, 50)
+        )
+
+
 class NestedOptionalSequenceEncoderTestCase(BaseTestCase):
     def setUp(self):
         BaseTestCase.setUp(self)
diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py
index a44f82a..0092588 100644
--- a/tests/type/test_univ.py
+++ b/tests/type/test_univ.py
@@ -22,8 +22,9 @@
 from pyasn1.type import namedtype
 from pyasn1.type import namedval
 from pyasn1.type import error
-from pyasn1.compat.octets import str2octs, ints2octs, octs2ints
+from pyasn1.compat.octets import str2octs, ints2octs, octs2ints, octs2str
 from pyasn1.error import PyAsn1Error
+from pyasn1.error import PyAsn1UnicodeEncodeError, PyAsn1UnicodeDecodeError
 
 
 class NoValueTestCase(BaseTestCase):
@@ -149,13 +150,18 @@
         try:
             if hasattr(sys, 'getsizeof'):
                 sys.getsizeof(univ.noValue)
-            else:
+
+            # TODO: remove when Py2.5 support is gone
+            elif sys.version_info > (2, 6):
                 raise unittest.SkipTest("no sys.getsizeof() method")
 
         except PyAsn1Error:
             assert False, 'sizeof failed for NoValue object'
+
         except TypeError:
-            raise unittest.SkipTest("sys.getsizeof() raises TypeError")
+            # TODO: remove when Py2.5 support is gone
+            if sys.version_info > (2, 6):
+                raise unittest.SkipTest("sys.getsizeof() raises TypeError")
 
 
 class IntegerTestCase(BaseTestCase):
@@ -543,6 +549,36 @@
     encoding = 'us-ascii'
 
 
+class OctetStringUnicodeErrorTestCase(BaseTestCase):
+    def testEncodeError(self):
+        text = octs2str(ints2octs((0xff, 0xfe)))
+
+        try:
+            univ.OctetString(text, encoding='us-ascii')
+
+        except PyAsn1UnicodeEncodeError:
+            pass
+
+        # TODO: remove when Py2.5 support is gone
+        else:
+            if sys.version_info > (2, 6):
+                assert False, 'Unicode encoding error not caught'
+
+    def testDecodeError(self):
+        serialized = ints2octs((0xff, 0xfe))
+
+        try:
+            str(univ.OctetString(serialized, encoding='us-ascii'))
+
+        except PyAsn1UnicodeDecodeError:
+            pass
+
+        # TODO: remove when Py2.5 support is gone
+        else:
+            if sys.version_info > (2, 6):
+                assert False, 'Unicode decoding error not caught'
+
+
 class OctetStringWithUtf8TestCase(OctetStringWithUnicodeMixIn, BaseTestCase):
     initializer = (208, 176, 208, 177, 208, 178)
     encoding = 'utf-8'
@@ -1027,21 +1063,25 @@
         }
 
     def testSubtype(self):
-        self.s1.clear()
-        assert self.s1.subtype(
+        subtype = self.s1.subtype(
             implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2),
             subtypeSpec=constraint.SingleValueConstraint(1, 3),
             sizeSpec=constraint.ValueSizeConstraint(0, 1)
-        ) == self.s1.clone(
+        )
+        subtype.clear()
+        clone = self.s1.clone(
             tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate,
                                       tag.tagFormatSimple, 2)),
             subtypeSpec=constraint.ConstraintsIntersection(constraint.SingleValueConstraint(1, 3)),
             sizeSpec=constraint.ValueSizeConstraint(0, 1)
         )
+        clone.clear()
+        assert clone == subtype
 
     def testClone(self):
         self.s1.setComponentByPosition(0, univ.OctetString('abc'))
         s = self.s1.clone()
+        s.clear()
         assert len(s) == 0
         s = self.s1.clone(cloneValueFlag=1)
         assert len(s) == 1
@@ -1056,31 +1096,32 @@
         s.append('xxx')
         assert s[0]
 
-        try:
-            s[2]
-
-        except IndexError:
-            pass
-
-        else:
-            assert False, 'IndexError not raised'
-
         # this is a deviation from standard sequence protocol
-        assert not s[1]
+        assert not s[2]
+
+    def testGetItemSlice(self):
+        s = self.s1.clone()
+        s.extend(['xxx', 'yyy', 'zzz'])
+        assert s[:1] == [str2octs('xxx')]
+        assert s[-2:] == [str2octs('yyy'), str2octs('zzz')]
+        assert s[1:2] == [str2octs('yyy')]
 
     def testSetItem(self):
         s = self.s1.clone()
         s.append('xxx')
+        s[2] = 'yyy'
+        assert len(s) == 3
+        assert s[1] == str2octs('')
 
-        try:
-
-            s[2] = 'xxx'
-
-        except IndexError:
-            pass
-
-        else:
-            assert False, 'IndexError not raised'
+    def testSetItemSlice(self):
+        s = self.s1.clone()
+        s[:1] = ['xxx']
+        assert s == [str2octs('xxx')]
+        s[-2:] = ['yyy', 'zzz']
+        assert s == [str2octs('yyy'), str2octs('zzz')]
+        s[1:2] = ['yyy']
+        assert s == [str2octs('yyy'), str2octs('yyy')]
+        assert len(s) == 2
 
     def testAppend(self):
         self.s1.clear()
@@ -1132,6 +1173,15 @@
         assert len(s) == 1
         assert s == [str2octs('abc')]
 
+    def testUntyped(self):
+        n = univ.SequenceOf()
+
+        assert not n.isValue
+
+        n[0] = univ.OctetString('fox')
+
+        assert n.isValue
+
     def testLegacyInitializer(self):
         n = univ.SequenceOf(
             componentType=univ.OctetString()
@@ -1174,6 +1224,39 @@
         s.clear()
         assert s.getComponentByPosition(0, instantiate=False) is univ.noValue
 
+    def testClear(self):
+
+        class SequenceOf(univ.SequenceOf):
+            componentType = univ.OctetString()
+
+        s = SequenceOf()
+        s.setComponentByPosition(0, 'test')
+
+        assert s.getComponentByPosition(0) == str2octs('test')
+        assert len(s) == 1
+        assert s.isValue
+
+        s.clear()
+
+        assert len(s) == 0
+        assert s == []
+        assert s.isValue
+
+    def testReset(self):
+
+        class SequenceOf(univ.SequenceOf):
+            componentType = univ.OctetString()
+
+        s = SequenceOf()
+        s.setComponentByPosition(0, 'test')
+
+        assert s.getComponentByPosition(0) == str2octs('test')
+        assert s.isValue
+
+        s.reset()
+
+        assert not s.isValue
+
 
 class SequenceOfPicklingTestCase(unittest.TestCase):
 
@@ -1441,6 +1524,75 @@
         s.clear()
         assert s.getComponentByPosition(1, instantiate=False) is univ.noValue
 
+    def testSchemaWithComponents(self):
+
+        class Sequence(univ.Sequence):
+            componentType = namedtype.NamedTypes(
+                namedtype.NamedType('name', univ.OctetString())
+            )
+
+        s = Sequence()
+
+        assert not s.isValue
+
+        s[0] = 'test'
+
+        assert s.isValue
+
+        s.clear()
+
+        assert not s.isValue
+
+        s.reset()
+
+        assert not s.isValue
+
+    def testSchemaWithOptionalComponents(self):
+
+        class Sequence(univ.Sequence):
+            componentType = namedtype.NamedTypes(
+                namedtype.OptionalNamedType('name', univ.OctetString())
+            )
+
+        s = Sequence()
+
+        assert s.isValue
+
+        s[0] = 'test'
+
+        assert s.isValue
+
+        s.clear()
+
+        assert s.isValue
+
+        s.reset()
+
+        assert not s.isValue
+
+    def testSchemaWithOptionalComponents(self):
+
+        class Sequence(univ.Sequence):
+            componentType = namedtype.NamedTypes(
+                namedtype.DefaultedNamedType('name', univ.OctetString(''))
+            )
+
+        s = Sequence()
+
+        assert s.isValue
+
+        s[0] = 'test'
+
+        assert s.isValue
+
+        s.clear()
+
+        assert s.isValue
+
+        s.reset()
+
+        assert not s.isValue
+
 
 class SequenceWithoutSchema(BaseTestCase):
 
@@ -1500,7 +1652,7 @@
         assert list(s.items()) == [('field-0', str2octs('abc')), ('field-1', 123)]
 
     def testUpdate(self):
-        s = univ.Sequence()
+        s = univ.Sequence().clear()
         assert not s
         s.setComponentByPosition(0, univ.OctetString('abc'))
         s.setComponentByPosition(1, univ.Integer(123))
@@ -1522,6 +1674,27 @@
         s.clear()
         assert 'field-0' not in s
 
+    def testSchema(self):
+
+        class Sequence(univ.Sequence):
+            pass
+
+        s = Sequence()
+
+        assert not s.isValue
+
+        s[0] = univ.OctetString('test')
+
+        assert s.isValue
+
+        s.clear()
+
+        assert s.isValue
+
+        s.reset()
+
+        assert not s.isValue
+
 
 class SequencePicklingTestCase(unittest.TestCase):
 
@@ -1633,7 +1806,7 @@
 
     def testGetTagMap(self):
         assert self.s1.tagMap.presentTypes == {
-            univ.Set.tagSet: univ.Set()
+            univ.Set.tagSet: univ.Set().clear()
         }
 
     def testGetComponentTagMap(self):