diff --git a/ci/build.sh b/ci/build.sh index 52846487..8b455d7d 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -26,6 +26,12 @@ if [ x"$FLAKE" = "xyes" ]; then fi fi +python -m mypy . +MYPY_RES=$? +if [ $MYPY_RES -ne 0 ]; then + exit $MYPY_RES +fi + # always build in-place so that Sphinx can find the modules python setup.py build_ext --inplace $EXTRA_BUILDEXT BUILD_RES=$? diff --git a/docs-requirements.txt b/docs-requirements.txt index 0e60f68f..a2223745 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -1,3 +1,4 @@ Sphinx >= 1.3.1 +sphinx-autoapi sphinx-rtd-theme >= 0.2.5b1 recommonmark >= 0.4.0 diff --git a/docs/source/conf.py b/docs/source/conf.py index 485aa7a0..4688d998 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,7 +11,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys, os, re # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -30,7 +30,20 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', "sphinx.ext.napoleon", 'gssapi_find_missing', 'requires_rfc'] +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.viewcode', + 'sphinx.ext.napoleon', + 'autoapi.extension', + 'gssapi_find_missing', + 'requires_rfc', +] + +autoapi_generate_api_docs = False +autoapi_type = 'python' +autoapi_dirs = ['../../gssapi'] +autoapi_file_patterns = ['*.pyi'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -56,11 +69,55 @@ # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. -# +# https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions +setup_py_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'setup.py')) +version_pattern = re.compile(r""" +^\s*version=['|\"](?P + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?P(a|b|c|rc|alpha|beta|pre|preview))
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+)['|\"],?\s*$
+""", re.VERBOSE | re.IGNORECASE)
+
 # The short X.Y version.
-version = '1.7.2'
+version = ''
 # The full version, including alpha/beta/rc tags.
-release = '1.7.2'
+release = ''
+
+with open(setup_py_path, mode='r') as fd:
+    for line in fd:
+        version_match = version_pattern.match(line)
+        if version_match:
+            version = version_match.group('release')
+            release = version_match.group('full_version')
+            break
+
+if not version or not release:
+    raise Exception("Failed to find version in setup.py")
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/source/gssapi.raw.rst b/docs/source/gssapi.raw.rst
index 970955a9..912c5364 100644
--- a/docs/source/gssapi.raw.rst
+++ b/docs/source/gssapi.raw.rst
@@ -25,44 +25,44 @@ Names
     Instead, they are a special form of name specific to
     a given mechanism.
 
-.. automodule:: gssapi.raw.names
+.. autoapimodule:: gssapi.raw.names
     :members:
     :undoc-members:
 
 Credentials
 ~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.creds
+.. autoapimodule:: gssapi.raw.creds
     :members:
     :undoc-members:
 
 Security Contexts
 ~~~~~~~~~~~~~~~~~
 
-.. automodule::  gssapi.raw.sec_contexts
+.. autoapimodule::  gssapi.raw.sec_contexts
     :members:
     :undoc-members:
 
-.. automodule:: gssapi.raw.message
+.. autoapimodule:: gssapi.raw.message
     :members:
     :undoc-members:
 
 Misc
 ~~~~
 
-.. automodule:: gssapi.raw.oids
+.. autoapimodule:: gssapi.raw.oids
     :members:
     :undoc-members:
 
-.. automodule:: gssapi.raw.misc
+.. autoapimodule:: gssapi.raw.misc
     :members:
     :undoc-members:
 
-.. automodule:: gssapi.raw.types
+.. autoapimodule:: gssapi.raw.types
     :members:
     :undoc-members:
 
-.. automodule:: gssapi.raw.chan_bindings
+.. autoapimodule:: gssapi.raw.chan_bindings
     :members:
     :undoc-members:
 
@@ -80,116 +80,116 @@ The following is a list of GSSAPI extensions supported by the low-level API.
 :rfc:`4178` (GSS-API Negotiation Mechanism)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_rfc4178
+.. autoapimodule:: gssapi.raw.ext_rfc4178
     :members:
     :undoc-members:
 
 :rfc:`5587` (GSS-API Extension for Mech Attributes)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_rfc5587
+.. autoapimodule:: gssapi.raw.ext_rfc5587
     :members:
     :undoc-members:
 
 :rfc:`5588` (GSS-API Extension for Storing Delegated Credentials)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_rfc5588
+.. autoapimodule:: gssapi.raw.ext_rfc5588
     :members:
     :undoc-members:
 
 :rfc:`5801` (GSS-API SASL Extensions)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_rfc5801
+.. autoapimodule:: gssapi.raw.ext_rfc5801
     :members:
     :undoc-members:
 
 Credential Store Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_cred_store
+.. autoapimodule:: gssapi.raw.ext_cred_store
     :members:
     :undoc-members:
 
 :rfc:`6680` (GSS-API Naming Extensions)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_rfc6680
-    :members:
-    :undoc-members:
-
-.. automodule:: gssapi.raw.ext_rfc6680_comp_oid
+.. autoapimodule:: gssapi.raw.ext_rfc6680
     :members:
     :undoc-members:
 
 Credentials Import-Export Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_cred_imp_exp
+.. autoapimodule:: gssapi.raw.ext_cred_imp_exp
     :members:
     :undoc-members:
 
 DCE (IOV/AEAD) Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_dce
+.. autoapimodule:: gssapi.raw.ext_dce
     :members:
     :undoc-members:
 
-.. automodule:: gssapi.raw.ext_dce_aead
-    :members:
-    :undoc-members:
+..
+    gssapi.raw.ext_dce_aead is imported with ext_dce so no need to double up.
+
 
 IOV MIC Extensions
 ~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_iov_mic
+.. autoapimodule:: gssapi.raw.ext_iov_mic
     :members:
     :undoc-members:
 
 Global Grid Forum (GGF) Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_ggf
+.. autoapimodule:: gssapi.raw.ext_ggf
     :members:
     :undoc-members:
 
 Services4User Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_s4u
+.. autoapimodule:: gssapi.raw.ext_s4u
     :members:
     :undoc-members:
 
 Acquiring Credentials With a Password Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_password
+.. autoapimodule:: gssapi.raw.ext_password
     :members:
     :undoc-members:
 
-.. automodule:: gssapi.raw.ext_password_add
+.. autoapimodule:: gssapi.raw.ext_password_add
     :members:
     :undoc-members:
 
 Kerberos Specific Extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_krb5
+.. autoapimodule:: gssapi.raw.ext_krb5
     :members:
     :undoc-members:
 
 Other Extensions
 ~~~~~~~~~~~~~~~~
 
-.. automodule:: gssapi.raw.ext_set_cred_opt
+.. autoapimodule:: gssapi.raw.ext_set_cred_opt
     :members:
     :undoc-members:
 
 Results
 -------
 
+..
+    Use autoapimodule once
+    https://github.com/readthedocs/sphinx-autoapi/issues/323 is resolved.
+
 .. automodule:: gssapi.raw.named_tuples
     :members:
     :undoc-members:
@@ -197,7 +197,7 @@ Results
 Exceptions
 ----------
 
-.. automodule:: gssapi.raw.exceptions
+.. autoapimodule:: gssapi.raw.exceptions
     :members:
     :undoc-members:
     :show-inheritance:
diff --git a/gssapi/_utils.py b/gssapi/_utils.py
index d2da9e81..0a2d8132 100644
--- a/gssapi/_utils.py
+++ b/gssapi/_utils.py
@@ -1,14 +1,18 @@
 import sys
 import types
+import typing as t
 
 import decorator as deco
 
-from typing import Optional
-
 from gssapi.raw.misc import GSSError
 
+if t.TYPE_CHECKING:
+    from gssapi.sec_contexts import SecurityContext
+
 
-def import_gssapi_extension(name):
+def import_gssapi_extension(
+    name: str,
+) -> t.Optional[types.ModuleType]:
     """Import a GSSAPI extension module
 
     This method imports a GSSAPI extension module based
@@ -31,20 +35,10 @@ def import_gssapi_extension(name):
         return None
 
 
-def flag_property(flag):
-    def setter(self, val):
-        if val:
-            self.flags.add(flag)
-        else:
-            self.flags.discard(flag)
-
-    def getter(self):
-        return flag in self.flags
-
-    return property(getter, setter)
-
-
-def inquire_property(name: str, doc: Optional[str] = None):
+def inquire_property(
+    name: str,
+    doc: t.Optional[str] = None
+) -> property:
     """Creates a property based on an inquire result
 
     This method creates a property that calls the
@@ -58,7 +52,7 @@ def inquire_property(name: str, doc: Optional[str] = None):
         property: the created property
     """
 
-    def inquire_property(self):
+    def inquire_property(self: "SecurityContext") -> t.Any:
         if not self._started:
             msg = (f"Cannot read {name} from a security context whose "
                    "establishment has not yet been started.")
@@ -73,7 +67,7 @@ def inquire_property(self):
 _ENCODING = 'UTF-8'
 
 
-def _get_encoding():
+def _get_encoding() -> str:
     """Gets the current encoding used for strings.
 
     This value is used to encode and decode string
@@ -85,7 +79,9 @@ def _get_encoding():
     return _ENCODING
 
 
-def set_encoding(enc):
+def set_encoding(
+    enc: str,
+) -> None:
     """Sets the current encoding used for strings
 
     This value is used to encode and decode string
@@ -99,9 +95,11 @@ def set_encoding(enc):
     _ENCODING = enc
 
 
-def _encode_dict(d):
+def _encode_dict(
+    d: t.Dict[t.Union[bytes, str], t.Union[bytes, str]],
+) -> t.Dict[bytes, bytes]:
     """Encodes any relevant strings in a dict"""
-    def enc(x):
+    def enc(x: t.Union[bytes, str]) -> bytes:
         if isinstance(x, str):
             return x.encode(_ENCODING)
         else:
@@ -112,7 +110,12 @@ def enc(x):
 
 # in case of Python 3, just use exception chaining
 @deco.decorator
-def catch_and_return_token(func, self, *args, **kwargs):
+def catch_and_return_token(
+    func: t.Callable,
+    self: "SecurityContext",
+    *args: t.Any,
+    **kwargs: t.Any,
+) -> t.Optional[bytes]:
     """Optionally defer exceptions and return a token instead
 
     When `__DEFER_STEP_ERRORS__` is set on the implementing class
@@ -127,10 +130,12 @@ def catch_and_return_token(func, self, *args, **kwargs):
     try:
         return func(self, *args, **kwargs)
     except GSSError as e:
-        if e.token is not None and self.__DEFER_STEP_ERRORS__:
+        defer_step_errors = getattr(self, '__DEFER_STEP_ERRORS__', False)
+        if e.token is not None and defer_step_errors:
             self._last_err = e
             # skip the "return func" line above in the traceback
-            self._last_err.__traceback__ = e.__traceback__.tb_next
+            tb = e.__traceback__.tb_next  # type: ignore[union-attr]
+            self._last_err.__traceback__ = tb
 
             return e.token
         else:
@@ -138,7 +143,12 @@ def catch_and_return_token(func, self, *args, **kwargs):
 
 
 @deco.decorator
-def check_last_err(func, self, *args, **kwargs):
+def check_last_err(
+    func: t.Callable,
+    self: "SecurityContext",
+    *args: t.Any,
+    **kwargs: t.Any,
+) -> t.Any:
     """Check and raise deferred errors before running the function
 
     This method checks :python:`_last_err` before running the wrapped
@@ -154,16 +164,6 @@ def check_last_err(func, self, *args, **kwargs):
     else:
         return func(self, *args, **kwargs)
 
-    @deco.decorator
-    def check_last_err(func, self, *args, **kwargs):
-        if self._last_err is not None:
-            try:
-                raise self._last_err
-            finally:
-                self._last_err = None
-        else:
-            return func(self, *args, **kwargs)
-
 
 class CheckLastError(type):
     """Check for a deferred error on all methods
@@ -174,7 +174,12 @@ class CheckLastError(type):
     Additionally, it enabled `__DEFER_STEP_ERRORS__` by default.
     """
 
-    def __new__(cls, name, parents, attrs):
+    def __new__(
+        cls,
+        name: str,
+        parents: t.Tuple[t.Type],
+        attrs: t.Dict[str, t.Any],
+    ) -> "CheckLastError":
         attrs['__DEFER_STEP_ERRORS__'] = True
 
         for attr_name in attrs:
diff --git a/gssapi/_win_config.py b/gssapi/_win_config.py
index 9b765b20..1ef0a581 100644
--- a/gssapi/_win_config.py
+++ b/gssapi/_win_config.py
@@ -19,21 +19,32 @@
 #: Download location for KfW
 KFW_DL = "https://web.mit.edu/KERBEROS/dist"
 
+# Mypy needs to run on both Win and non-Win so the missing attribute will fire
+# on non-Win and Win will fire with unused ignore. Instead just cache the attr
+# by name and use it as needed.
+ADD_DLL_DIR = getattr(os, "add_dll_directory", None)
+CTYPES_WIN_DLL = getattr(ctypes, "WinDLL", ctypes.CDLL)
 
-def kfw_available():
+
+def _add_dll_directory(path: str) -> None:
+    if ADD_DLL_DIR:
+        ADD_DLL_DIR(path)
+
+
+def kfw_available() -> bool:
     """Return if the main GSSAPI DLL for KfW can be loaded"""
     try:  # to load the main GSSAPI DLL
         if sys.maxsize > 2**32:
-            ctypes.WinDLL('gssapi64.dll')
+            CTYPES_WIN_DLL('gssapi64.dll')
         else:
-            ctypes.WinDLL('gssapi32.dll')
+            CTYPES_WIN_DLL('gssapi32.dll')
     except OSError:  # DLL is not in PATH
         return False
     else:  # DLL is in PATH, everything should work
         return True
 
 
-def error_not_found():
+def error_not_found() -> None:
     """Raise an OSError detailing that KfW is missing and how to get it"""
     raise OSError(
         "Could not find KfW installation. Please download and install "
@@ -43,7 +54,7 @@ def error_not_found():
     )
 
 
-def configure_windows():
+def configure_windows() -> None:
     """
     Validate that KfW appears to be installed correctly and add it to the
     DLL directories/PATH if necessary. In the case that it can't be located,
@@ -54,7 +65,7 @@ def configure_windows():
 
     if os.path.exists(KFW_BIN):  # In standard location
         try:  # to use Python 3.8's DLL handling
-            os.add_dll_directory(KFW_BIN)
+            _add_dll_directory(KFW_BIN)
         except AttributeError:  # <3.8, use PATH
             os.environ['PATH'] += os.pathsep + KFW_BIN
         if kfw_available():
@@ -64,7 +75,7 @@ def configure_windows():
     kinit_path = shutil.which('kinit')  # KfW provided binary
     if kinit_path:  # Non-standard install location
         try:  # Most likely >=3.8, otherwise it would have been found already
-            os.add_dll_directory(os.path.dirname(kinit_path))
+            _add_dll_directory(os.path.dirname(kinit_path))
         except AttributeError:  # <3.8, corrupted installation?
             pass
         else:
diff --git a/gssapi/creds.py b/gssapi/creds.py
index 888fea50..0141c648 100644
--- a/gssapi/creds.py
+++ b/gssapi/creds.py
@@ -1,5 +1,9 @@
+import typing as t
+
 from gssapi.raw import creds as rcreds
 from gssapi.raw import named_tuples as tuples
+from gssapi.raw import names as rnames
+from gssapi.raw import oids as roids
 from gssapi._utils import import_gssapi_extension, _encode_dict
 
 from gssapi import names
@@ -26,7 +30,7 @@ class Credentials(rcreds.Creds):
     credentials.
 
     If the `base` argument is used, an existing
-    :class:`~gssapi.raw.creds.Cred` object from the low-level API is
+    :class:`~gssapi.raw.creds.Creds` object from the low-level API is
     converted into a high-level object.
 
     If the `token` argument is used, the credentials
@@ -46,8 +50,18 @@ class Credentials(rcreds.Creds):
 
     __slots__ = ()
 
-    def __new__(cls, base=None, token=None, name=None, lifetime=None,
-                mechs=None, usage='both', store=None):
+    def __new__(
+        cls,
+        base: t.Optional[rcreds.Creds] = None,
+        token: t.Optional[bytes] = None,
+        name: t.Optional[rnames.Name] = None,
+        lifetime: t.Optional[int] = None,
+        mechs: t.Optional[t.Iterable[roids.OID]] = None,
+        usage: str = 'both',
+        store: t.Optional[
+            t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+        ] = None,
+    ) -> "Credentials":
         # TODO(directxman12): this is missing support for password
         #                     (non-RFC method)
         if base is not None:
@@ -64,35 +78,48 @@ def __new__(cls, base=None, token=None, name=None, lifetime=None,
                               store=store)
             base_creds = res.creds
 
-        return super(Credentials, cls).__new__(cls, base_creds)
+        return t.cast("Credentials",
+                      super(Credentials, cls).__new__(cls, base_creds))
 
     @property
-    def name(self):
+    def name(self) -> rnames.Name:
         """Get the name associated with these credentials"""
-        return self.inquire(name=True, lifetime=False,
-                            usage=False, mechs=False).name
+        return t.cast(rnames.Name,
+                      self.inquire(name=True, lifetime=False, usage=False,
+                                   mechs=False).name)
 
     @property
-    def lifetime(self):
+    def lifetime(self) -> int:
         """Get the remaining lifetime of these credentials"""
-        return self.inquire(name=False, lifetime=True,
-                            usage=False, mechs=False).lifetime
+        return t.cast(int,
+                      self.inquire(name=False, lifetime=True,
+                                   usage=False, mechs=False).lifetime)
 
     @property
-    def mechs(self):
+    def mechs(self) -> t.Set[roids.OID]:
         """Get the mechanisms for these credentials"""
-        return self.inquire(name=False, lifetime=False,
-                            usage=False, mechs=True).mechs
+        return t.cast(t.Set[roids.OID],
+                      self.inquire(name=False, lifetime=False,
+                                   usage=False, mechs=True).mechs)
 
     @property
-    def usage(self):
+    def usage(self) -> str:
         """Get the usage (initiate, accept, or both) of these credentials"""
-        return self.inquire(name=False, lifetime=False,
-                            usage=True, mechs=False).usage
+        return t.cast(str,
+                      self.inquire(name=False, lifetime=False,
+                                   usage=True, mechs=False).usage)
 
     @classmethod
-    def acquire(cls, name=None, lifetime=None, mechs=None, usage='both',
-                store=None):
+    def acquire(
+        cls,
+        name: t.Optional[rnames.Name] = None,
+        lifetime: t.Optional[int] = None,
+        mechs: t.Optional[t.Iterable[roids.OID]] = None,
+        usage: str = 'both',
+        store: t.Optional[
+            t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+        ] = None,
+    ) -> tuples.AcquireCredResult:
         """Acquire GSSAPI credentials
 
         This method acquires credentials.  If the `store` argument is
@@ -122,7 +149,7 @@ def acquire(cls, name=None, lifetime=None, mechs=None, usage='both',
 
         Returns:
             AcquireCredResult: the acquired credentials and information about
-                them
+            them
 
         Raises:
             ~gssapi.exceptions.BadMechanismError
@@ -141,17 +168,25 @@ def acquire(cls, name=None, lifetime=None, mechs=None, usage='both',
                                           "not have support for manipulating "
                                           "credential stores")
 
-            store = _encode_dict(store)
+            b_store = _encode_dict(store)
 
-            res = rcred_cred_store.acquire_cred_from(store, name,
+            res = rcred_cred_store.acquire_cred_from(b_store, name,
                                                      lifetime, mechs,
                                                      usage)
 
         return tuples.AcquireCredResult(cls(base=res.creds), res.mechs,
                                         res.lifetime)
 
-    def store(self, store=None, usage='both', mech=None,
-              overwrite=False, set_default=False):
+    def store(
+        self,
+        store: t.Optional[
+            t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+        ] = None,
+        usage: str = 'both',
+        mech: t.Optional[roids.OID] = None,
+        overwrite: bool = False,
+        set_default: bool = False,
+    ) -> tuples.StoreCredResult:
         """Store these credentials into the given store
 
         This method stores the current credentials into the specified
@@ -197,13 +232,18 @@ def store(self, store=None, usage='both', mech=None,
                                           "not have support for manipulating "
                                           "credential stores directly")
 
-            store = _encode_dict(store)
+            b_store = _encode_dict(store)
 
-            return rcred_cred_store.store_cred_into(store, self, usage, mech,
+            return rcred_cred_store.store_cred_into(b_store, self, usage, mech,
                                                     overwrite, set_default)
 
-    def impersonate(self, name=None, lifetime=None, mechs=None,
-                    usage='initiate'):
+    def impersonate(
+        self,
+        name: t.Optional[rnames.Name] = None,
+        lifetime: t.Optional[int] = None,
+        mechs: t.Optional[t.Iterable[roids.OID]] = None,
+        usage: str = 'initiate',
+    ) -> "Credentials":
         """Impersonate a name using the current credentials
 
         This method acquires credentials by impersonating another
@@ -235,7 +275,13 @@ def impersonate(self, name=None, lifetime=None, mechs=None,
 
         return type(self)(base=res.creds)
 
-    def inquire(self, name=True, lifetime=True, usage=True, mechs=True):
+    def inquire(
+        self,
+        name: bool = True,
+        lifetime: bool = True,
+        usage: bool = True,
+        mechs: bool = True,
+    ) -> tuples.InquireCredResult:
         """Inspect these credentials for information
 
         This method inspects these credentials for information about them.
@@ -248,7 +294,7 @@ def inquire(self, name=True, lifetime=True, usage=True, mechs=True):
 
         Returns:
             InquireCredResult: the information about the credentials,
-                with None used when the corresponding argument was False
+            with None used when the corresponding argument was False
 
         Raises:
             ~gssapi.exceptions.MissingCredentialsError
@@ -266,8 +312,14 @@ def inquire(self, name=True, lifetime=True, usage=True, mechs=True):
         return tuples.InquireCredResult(res_name, res.lifetime,
                                         res.usage, res.mechs)
 
-    def inquire_by_mech(self, mech, name=True, init_lifetime=True,
-                        accept_lifetime=True, usage=True):
+    def inquire_by_mech(
+        self,
+        mech: roids.OID,
+        name: bool = True,
+        init_lifetime: bool = True,
+        accept_lifetime: bool = True,
+        usage: bool = True,
+    ) -> tuples.InquireCredByMechResult:
         """Inspect these credentials for per-mechanism information
 
         This method inspects these credentials for per-mechanism information
@@ -285,7 +337,7 @@ def inquire_by_mech(self, mech, name=True, init_lifetime=True,
 
         Returns:
             InquireCredByMechResult: the information about the credentials,
-                with None used when the corresponding argument was False
+            with None used when the corresponding argument was False
         """
 
         res = rcreds.inquire_cred_by_mech(self, mech, name, init_lifetime,
@@ -301,9 +353,18 @@ def inquire_by_mech(self, mech, name=True, init_lifetime=True,
                                               res.accept_lifetime,
                                               res.usage)
 
-    def add(self, name, mech, usage='both',
-            init_lifetime=None, accept_lifetime=None, impersonator=None,
-            store=None):
+    def add(
+        self,
+        name: rnames.Name,
+        mech: roids.OID,
+        usage: str = 'both',
+        init_lifetime: t.Optional[int] = None,
+        accept_lifetime: t.Optional[int] = None,
+        impersonator: t.Optional[rcreds.Creds] = None,
+        store: t.Optional[
+            t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+        ] = None,
+    ) -> "Credentials":
         """Acquire more credentials to add to the current set
 
         This method works like :meth:`acquire`, except that it adds the
@@ -347,7 +408,7 @@ def add(self, name, mech, usage='both',
 
         Returns:
             Credentials: the credentials set containing the current credentials
-                and the newly acquired ones.
+            and the newly acquired ones.
 
         Raises:
             ~gssapi.exceptions.BadMechanismError
@@ -367,9 +428,9 @@ def add(self, name, mech, usage='both',
                 raise NotImplementedError("Your GSSAPI implementation does "
                                           "not have support for manipulating "
                                           "credential stores")
-            store = _encode_dict(store)
+            b_store = _encode_dict(store)
 
-            res = rcred_cred_store.add_cred_from(store, self, name, mech,
+            res = rcred_cred_store.add_cred_from(b_store, self, name, mech,
                                                  usage, init_lifetime,
                                                  accept_lifetime)
         elif impersonator is not None:
@@ -386,7 +447,7 @@ def add(self, name, mech, usage='both',
 
         return Credentials(res.creds)
 
-    def export(self):
+    def export(self) -> bytes:
         """Export these credentials into a token
 
         This method exports the current credentials to a token that can
@@ -408,6 +469,8 @@ def export(self):
         return rcred_imp_exp.export_cred(self)
 
     # pickle protocol support
-    def __reduce__(self):
+    def __reduce__(
+        self,
+    ) -> t.Tuple[t.Type["Credentials"], t.Tuple[None, bytes]]:
         # the unpickle arguments to new are (base=None, token=self.export())
         return (type(self), (None, self.export()))
diff --git a/gssapi/exceptions.py b/gssapi/exceptions.py
index 332a2bf3..4775bfe1 100644
--- a/gssapi/exceptions.py
+++ b/gssapi/exceptions.py
@@ -1,3 +1,5 @@
+import typing as t
+
 from gssapi.raw.exceptions import *  # noqa
 from gssapi.raw.misc import GSSError  # noqa
 
@@ -15,7 +17,11 @@ class GeneralError(Exception):
     MAJOR_MESSAGE = "General error"
     FMT_STR = "{maj}: {min}."
 
-    def __init__(self, minor_message, **kwargs):
+    def __init__(
+        self,
+        minor_message: str,
+        **kwargs: str,
+    ) -> None:
         maj_str = self.MAJOR_MESSAGE.format(**kwargs)
         err_str = self.FMT_STR.format(maj=maj_str, min=minor_message)
         super(GeneralError, self).__init__(err_str)
@@ -30,7 +36,12 @@ class EncryptionNotUsed(GeneralError):
     """An Error indicating that encryption was requested, but not used"""
     MAJOR_MESSAGE = "Confidentiality was requested, but not used"
 
-    def __init__(self, minor_message, unwrapped_message=None, **kwargs):
+    def __init__(
+        self,
+        minor_message: str,
+        unwrapped_message: t.Optional[bytes] = None,
+        **kwargs: str,
+    ) -> None:
         super(EncryptionNotUsed, self).__init__(minor_message, **kwargs)
 
         self.unwrapped_message = unwrapped_message
diff --git a/gssapi/mechs.py b/gssapi/mechs.py
index f22819da..a6d7d18c 100644
--- a/gssapi/mechs.py
+++ b/gssapi/mechs.py
@@ -1,6 +1,10 @@
-from gssapi.raw import oids as roids
+import typing as t
+
 from gssapi._utils import import_gssapi_extension
+from gssapi.raw import oids as roids
 from gssapi.raw import misc as rmisc
+from gssapi.raw import named_tuples as tuples
+from gssapi.raw import names as rnames
 from gssapi import _utils
 
 rfc5587 = import_gssapi_extension('rfc5587')
@@ -17,39 +21,44 @@ class Mechanism(roids.OID):
     It inherits from the low-level GSSAPI :class:`~gssapi.raw.oids.OID` class,
     and thus can be used with both low-level and high-level API calls.
     """
-    def __new__(cls, cpy=None, elements=None):
-        return super(Mechanism, cls).__new__(cls, cpy, elements)
+    def __new__(
+        cls,
+        cpy: t.Optional[roids.OID] = None,
+        elements: t.Optional[bytes] = None,
+    ) -> "Mechanism":
+        return t.cast("Mechanism",
+                      super(Mechanism, cls).__new__(cls, cpy, elements))
 
     @property
-    def name_types(self):
+    def name_types(self) -> t.Set[roids.OID]:
         """
         Get the set of name types supported by this mechanism.
         """
         return rmisc.inquire_names_for_mech(self)
 
     @property
-    def _saslname(self):
+    def _saslname(self) -> tuples.InquireSASLNameResult:
         if rfc5801 is None:
             raise NotImplementedError("Your GSSAPI implementation does not "
                                       "have support for RFC 5801")
         return rfc5801.inquire_saslname_for_mech(self)
 
     @property
-    def _attrs(self):
+    def _attrs(self) -> tuples.InquireAttrsResult:
         if rfc5587 is None:
             raise NotImplementedError("Your GSSAPI implementation does not "
                                       "have support for RFC 5587")
 
         return rfc5587.inquire_attrs_for_mech(self)
 
-    def __str__(self):
+    def __str__(self) -> str:
         return self._bytes_desc().decode(_utils._get_encoding())
 
-    def __unicode__(self):
+    def __unicode__(self) -> str:
         return self._bytes_desc().decode(_utils._get_encoding())
 
-    def _bytes_desc(self):
-        base = self.dotted_form
+    def _bytes_desc(self) -> bytes:
+        base: t.Union[bytes, str] = self.dotted_form
         if rfc5801 is not None and self._saslname and self._saslname.mech_name:
             base = self._saslname.mech_name
 
@@ -58,7 +67,7 @@ def _bytes_desc(self):
 
         return base
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         """
         Get a name representing the mechanism; always safe to call
         """
@@ -72,7 +81,7 @@ def __repr__(self):
         return base
 
     @property
-    def sasl_name(self):
+    def sasl_name(self) -> str:
         """
         Get the SASL name for the mechanism
 
@@ -81,7 +90,7 @@ def sasl_name(self):
         return self._saslname.sasl_mech_name.decode('UTF-8')
 
     @property
-    def description(self):
+    def description(self) -> str:
         """
         Get the description of the mechanism
 
@@ -90,7 +99,7 @@ def description(self):
         return self._saslname.mech_description.decode('UTF-8')
 
     @property
-    def known_attrs(self):
+    def known_attrs(self) -> t.Set[roids.OID]:
         """
         Get the known attributes of the mechanism; returns a set of OIDs
         ([OID])
@@ -100,7 +109,7 @@ def known_attrs(self):
         return self._attrs.known_mech_attrs
 
     @property
-    def attrs(self):
+    def attrs(self) -> t.Set[roids.OID]:
         """
         Get the attributes of the mechanism; returns a set of OIDs ([OID])
 
@@ -109,14 +118,17 @@ def attrs(self):
         return self._attrs.mech_attrs
 
     @classmethod
-    def all_mechs(cls):
+    def all_mechs(cls) -> t.Iterator["Mechanism"]:
         """
         Get a generator of all mechanisms supported by GSSAPI
         """
         return (cls(mech) for mech in rmisc.indicate_mechs())
 
     @classmethod
-    def from_name(cls, name=None):
+    def from_name(
+        cls,
+        name: rnames.Name,
+    ) -> t.Iterator["Mechanism"]:
         """
         Get a generator of mechanisms that may be able to process the name
 
@@ -132,7 +144,10 @@ def from_name(cls, name=None):
         return (cls(mech) for mech in rmisc.inquire_mechs_for_name(name))
 
     @classmethod
-    def from_sasl_name(cls, name=None):
+    def from_sasl_name(
+        cls,
+        name: t.Optional[t.Union[bytes, str]] = None,
+    ) -> "Mechanism":
         """
         Create a Mechanism from its SASL name
 
@@ -158,8 +173,18 @@ def from_sasl_name(cls, name=None):
         return cls(m)
 
     @classmethod
-    def from_attrs(cls, desired_attrs=None, except_attrs=None,
-                   critical_attrs=None):
+    def from_attrs(
+        cls,
+        desired_attrs: t.Optional[
+            t.Union[roids.OID, t.Iterable[roids.OID]]
+        ] = None,
+        except_attrs: t.Optional[
+            t.Union[roids.OID, t.Iterable[roids.OID]]
+        ] = None,
+        critical_attrs: t.Optional[
+            t.Union[roids.OID, t.Iterable[roids.OID]]
+        ] = None,
+    ) -> t.Iterator["Mechanism"]:
         """
         Get a generator of mechanisms supporting the specified attributes. See
         RFC 5587's :func:`indicate_mechs_by_attrs` for more information.
diff --git a/gssapi/names.py b/gssapi/names.py
index 3cb2ff4b..0f6201c6 100644
--- a/gssapi/names.py
+++ b/gssapi/names.py
@@ -1,11 +1,14 @@
+
+import typing as t
+
 from gssapi.raw import names as rname
 from gssapi.raw import NameType
 from gssapi.raw import named_tuples as tuples
+from gssapi.raw import oids as roids
 from gssapi import _utils
 
 from collections.abc import MutableMapping, Iterable
 
-
 rname_rfc6680 = _utils.import_gssapi_extension('rfc6680')
 rname_rfc6680_comp_oid = _utils.import_gssapi_extension('rfc6680_comp_oid')
 
@@ -35,8 +38,13 @@ class Name(rname.Name):
 
     __slots__ = ('_attr_obj')
 
-    def __new__(cls, base=None, name_type=None, token=None,
-                composite=False):
+    def __new__(
+        cls,
+        base: t.Optional[t.Union[rname.Name, bytes, str]] = None,
+        name_type: t.Optional[roids.OID] = None,
+        token: t.Optional[bytes] = None,
+        composite: bool = False,
+    ) -> "Name":
         if token is not None:
             if composite:
                 if rname_rfc6680 is None:
@@ -67,11 +75,19 @@ def __new__(cls, base=None, name_type=None, token=None,
             if isinstance(base, str):
                 base = base.encode(_utils._get_encoding())
 
-            base_name = rname.import_name(base, name_type)
+            base_name = rname.import_name(
+                base,  # type: ignore[arg-type]
+                name_type)
 
-        return super(Name, cls).__new__(cls, base_name)
+        return t.cast("Name", super(Name, cls).__new__(cls, base_name))
 
-    def __init__(self, base=None, name_type=None, token=None, composite=False):
+    def __init__(
+        self,
+        base: t.Optional[t.Union[rname.Name, bytes, str]] = None,
+        name_type: t.Optional[roids.OID] = None,
+        token: t.Optional[bytes] = None,
+        composite: bool = False,
+    ) -> None:
         """
         The constructor can be used to "import" a name from a human readable
         representation, or from a token, and can also be used to convert a
@@ -96,28 +112,34 @@ def __init__(self, base=None, name_type=None, token=None, composite=False):
             ~gssapi.exceptions.BadMechanismError
         """
 
+        self._attr_obj: t.Optional[_NameAttributeMapping]
+
         if rname_rfc6680 is not None:
             self._attr_obj = _NameAttributeMapping(self)
         else:
             self._attr_obj = None
 
-    def __str__(self):
+    def __str__(self) -> str:
         return bytes(self).decode(_utils._get_encoding())
 
-    def __unicode__(self):
+    def __unicode__(self) -> str:
         # Python 2 -- someone asked for unicode
         return self.__bytes__().decode(_utils._get_encoding())
 
-    def __bytes__(self):
+    def __bytes__(self) -> bytes:
         # Python 3 -- someone asked for bytes
         return rname.display_name(self, name_type=False).name
 
-    def display_as(self, name_type):
+    def display_as(
+        self,
+        name_type: roids.OID,
+    ) -> str:
         """
         Display this name as the given name type.
 
         This method attempts to display the current :class:`Name`
-        using the syntax of the given :class:`NameType`, if possible.
+        using the syntax of the given :class:`~gssapi.raw.types.NameType`, if
+        possible.
 
         Warning:
 
@@ -137,8 +159,8 @@ def display_as(self, name_type):
         :requires-ext:`rfc6680`
 
         Args:
-            name_type (~gssapi.OID): the :class:`NameType` to use to display
-                the given name
+            name_type (~gssapi.OID): the :class:`~gssapi.raw.types.NameType` to
+                use to display the given name
 
         Returns:
             str: the displayed name
@@ -155,11 +177,14 @@ def display_as(self, name_type):
             _utils._get_encoding())
 
     @property
-    def name_type(self):
-        """The :class:`NameType` of this name"""
+    def name_type(self) -> t.Optional[roids.OID]:
+        """The :class:`~gssapi.raw.types.NameType` of this name"""
         return rname.display_name(self, name_type=True).name_type
 
-    def __eq__(self, other):
+    def __eq__(
+        self,
+        other: object,
+    ) -> bool:
         if not isinstance(other, rname.Name):
             # maybe something else can compare this
             # to other classes, but we certainly can't
@@ -167,15 +192,21 @@ def __eq__(self, other):
         else:
             return rname.compare_name(self, other)
 
-    def __ne__(self, other):
+    def __ne__(
+        self,
+        other: object,
+    ) -> bool:
         return not self.__eq__(other)
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         disp_res = rname.display_name(self, name_type=True)
-        return "Name({name}, {name_type})".format(name=disp_res.name,
-                                                  name_type=disp_res.name_type)
+        return "Name({name!r}, {name_type})".format(
+            name=disp_res.name, name_type=disp_res.name_type)
 
-    def export(self, composite=False):
+    def export(
+        self,
+        composite: bool = False,
+    ) -> bytes:
         """Export this name as a token.
 
         This method exports the name into a byte string which can then be
@@ -204,7 +235,10 @@ def export(self, composite=False):
         else:
             return rname.export_name(self)
 
-    def canonicalize(self, mech):
+    def canonicalize(
+        self,
+        mech: roids.OID
+    ) -> "Name":
         """Canonicalize a name with respect to a mechanism.
 
         This method returns a new :class:`Name` that is canonicalized according
@@ -224,13 +258,19 @@ def canonicalize(self, mech):
 
         return type(self)(rname.canonicalize_name(self, mech))
 
-    def __copy__(self):
+    def __copy__(self) -> "Name":
         return type(self)(rname.duplicate_name(self))
 
-    def __deepcopy__(self, memo):
+    def __deepcopy__(
+        self,
+        memo: t.Dict,
+    ) -> "Name":
         return type(self)(rname.duplicate_name(self))
 
-    def _inquire(self, **kwargs):
+    def _inquire(
+        self,
+        **kwargs: t.Any,
+    ) -> tuples.InquireNameResult:
         """Inspect this name for information.
 
         This method inspects the name for information.
@@ -269,20 +309,20 @@ def _inquire(self, **kwargs):
                                           attrs=attrs)
 
     @property
-    def is_mech_name(self):
+    def is_mech_name(self) -> bool:
         """Whether or not this name is a mechanism name
         (:requires-ext:`rfc6680`)
         """
         return self._inquire(mech_name=True).is_mech_name
 
     @property
-    def mech(self):
+    def mech(self) -> roids.OID:
         """The mechanism associated with this name (:requires-ext:`rfc6680`)
         """
         return self._inquire(mech_name=True).mech
 
     @property
-    def attributes(self):
+    def attributes(self) -> t.Optional["_NameAttributeMapping"]:
         """The attributes of this name (:requires-ext:`rfc6680`)
 
         The attributes are presenting in the form of a
@@ -310,31 +350,48 @@ def attributes(self):
 class _NameAttributeMapping(MutableMapping):
 
     """Provides dict-like access to RFC 6680 Name attributes."""
-    def __init__(self, name):
+    def __init__(
+        self,
+        name: Name,
+    ) -> None:
         self._name = name
 
-    def __getitem__(self, key):
+    def __getitem__(
+        self,
+        key: t.Union[bytes, str],
+    ) -> tuples.GetNameAttributeResult:
         if isinstance(key, str):
             key = key.encode(_utils._get_encoding())
 
-        res = rname_rfc6680.get_name_attribute(self._name, key)
-        return tuples.GetNameAttributeResult(frozenset(res.values),
-                                             frozenset(res.display_values),
+        res = rname_rfc6680.get_name_attribute(  # type: ignore[union-attr]
+            self._name, key)
+        res = t.cast(tuples.GetNameAttributeResult, res)
+
+        return tuples.GetNameAttributeResult(list(res.values),
+                                             list(res.display_values),
                                              res.authenticated,
                                              res.complete)
 
-    def __setitem__(self, key, value):
+    def __setitem__(
+        self,
+        key: t.Union[bytes, str],
+        value: t.Union[
+            tuples.GetNameAttributeResult, t.Tuple[bytes, bool], bytes
+        ],
+    ) -> None:
         if isinstance(key, str):
             key = key.encode(_utils._get_encoding())
 
-        rname_rfc6680.delete_name_attribute(self._name, key)
+        rname_rfc6680.delete_name_attribute(  # type: ignore[union-attr]
+            self._name, key)
 
+        attr_value: t.List[bytes]
         if isinstance(value, tuples.GetNameAttributeResult):
             complete = value.complete
-            value = value.values
+            attr_value = value.values
         elif isinstance(value, tuple) and len(value) == 2:
-            complete = value[1]
-            value = value[0]
+            complete = t.cast(bool, value[1])
+            attr_value = [t.cast(bytes, value[0])]
         else:
             complete = False
 
@@ -342,19 +399,23 @@ def __setitem__(self, key, value):
                 not isinstance(value, Iterable)):
             # NB(directxman12): this allows us to easily assign a single
             # value, since that's a common case
-            value = [value]
+            attr_value = [value]
 
-            rname_rfc6680.set_name_attribute(self._name, key, value,
-                                             complete=complete)
+        rname_rfc6680.set_name_attribute(  # type: ignore[union-attr]
+            self._name, key, attr_value, complete=complete)
 
-    def __delitem__(self, key):
+    def __delitem__(
+        self,
+        key: t.Union[bytes, str],
+    ) -> None:
         if isinstance(key, str):
             key = key.encode(_utils._get_encoding())
 
-        rname_rfc6680.delete_name_attribute(self._name, key)
+        rname_rfc6680.delete_name_attribute(  # type: ignore[union-attr]
+            self._name, key)
 
-    def __iter__(self):
+    def __iter__(self) -> t.Iterator[bytes]:
         return iter(self._name._inquire(attrs=True).attrs)
 
-    def __len__(self):
+    def __len__(self) -> int:
         return len(self._name._inquire(attrs=True).attrs)
diff --git a/gssapi/py.typed b/gssapi/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/gssapi/raw/_enum_extensions/__init__.py b/gssapi/raw/_enum_extensions/__init__.py
index 8051c50c..ee2c43ee 100644
--- a/gssapi/raw/_enum_extensions/__init__.py
+++ b/gssapi/raw/_enum_extensions/__init__.py
@@ -1,16 +1,27 @@
+import typing as t
+
 from enum import EnumMeta
 
 
-_extra_values = {}
+_extra_values: t.Dict[str, t.Dict[str, t.Any]] = {}
 
 
-def register_value(cl_str, name, value):
+def register_value(
+    cl_str: str,
+    name: str,
+    value: t.Any,
+) -> None:
     _extra_values[cl_str] = _extra_values.get(cl_str, {})
     _extra_values[cl_str][name] = value
 
 
 class ExtendableEnum(EnumMeta):
-    def __new__(metacl, name, bases, classdict):
+    def __new__(
+        metacl,
+        name: str,
+        bases: t.Tuple[t.Type],
+        classdict: t.Dict[str, t.Any],
+    ) -> "ExtendableEnum":
         extra_vals = _extra_values.get(name)
 
         if extra_vals is not None:
diff --git a/gssapi/raw/chan_bindings.pyi b/gssapi/raw/chan_bindings.pyi
new file mode 100644
index 00000000..bd1a2e1b
--- /dev/null
+++ b/gssapi/raw/chan_bindings.pyi
@@ -0,0 +1,30 @@
+import typing as t
+
+
+class ChannelBindings:
+    """GSSAPI Channel Bindings
+
+    This class represents a set of GSSAPI channel bindings.
+
+    Args:
+        initiator_address_type: the initiator address type
+        initiator_address: the initiator address
+        acceptor_address_type:  the acceptor address type
+        acceptor_address: the acceptor address
+        application_data: additional application-specific data
+    """
+
+    initiator_address_type: t.Optional[int]
+    initiator_address: t.Optional[bytes]
+    acceptor_address_type: t.Optional[int]
+    acceptor_address: t.Optional[bytes]
+    application_data: t.Optional[bytes]
+
+    def __init__(
+        self,
+        initiator_address_type: t.Optional[int] = None,
+        initiator_address: t.Optional[bytes] = None,
+        acceptor_address_type: t.Optional[int] = None,
+        acceptor_address: t.Optional[bytes] = None,
+        application_data: t.Optional[bytes] = None,
+    ) -> None: ...
diff --git a/gssapi/raw/chan_bindings.pyx b/gssapi/raw/chan_bindings.pyx
index d66f587a..cb9c6e38 100644
--- a/gssapi/raw/chan_bindings.pyx
+++ b/gssapi/raw/chan_bindings.pyx
@@ -3,11 +3,6 @@ from libc.stdlib cimport calloc, free
 from gssapi.raw.cython_types cimport *
 
 cdef class ChannelBindings:
-    """GSSAPI Channel Bindings
-
-    This class represents a set of GSSAPI channel bindings.
-    """
-
     # defined in pxd file
     # cdef public object initiator_address_type
     # cdef public bytes initiator_address
@@ -20,17 +15,6 @@ cdef class ChannelBindings:
     def __init__(ChannelBindings self, initiator_address_type=None,
                  initiator_address=None, acceptor_address_type=None,
                  acceptor_address=None, application_data=None):
-        """
-        Args:
-            initiator_address_type (~gssapi.AddressType): the initiator address
-                type
-            initiator_address (bytes): the initiator address
-            acceptor_address_type (~gssapi.AddressType):  the acceptor address
-                type
-            acceptor_address (bytes): the acceptor address
-            application_data (bytes): additional application-specific data
-        """
-
         self.initiator_address_type = initiator_address_type
         self.initiator_address = initiator_address
 
diff --git a/gssapi/raw/creds.pyi b/gssapi/raw/creds.pyi
new file mode 100644
index 00000000..19f5e162
--- /dev/null
+++ b/gssapi/raw/creds.pyi
@@ -0,0 +1,186 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+    from gssapi.raw.named_tuples import (
+        AcquireCredResult,
+        AddCredResult,
+        InquireCredResult,
+        InquireCredByMechResult,
+    )
+
+
+class Creds:
+    """
+    GSSAPI Credentials
+    """
+
+    def __new__(
+        cls,
+        cpy: t.Optional["Creds"] = None,
+    ) -> "Creds": ...
+
+
+def acquire_cred(
+    name: t.Optional["Name"],
+    lifetime: t.Optional[int] = None,
+    mechs: t.Optional[t.Iterable["OID"]] = None,
+    usage: str = 'both',
+) -> "AcquireCredResult":
+    """Get GSSAPI credentials for the given name and mechanisms.
+
+    This method gets GSSAPI credentials corresponding to the given name
+    and mechanims.  The desired TTL and usage for the the credential may also
+    be specified.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name for which to acquire the
+            credentials (or None for the "no name" functionality)
+        lifetime (int): the lifetime for the credentials (or None for
+            indefinite)
+        mechs (~gssapi.raw.types.MechType): the desired mechanisms for which
+            the credentials should work, or None for the default set
+        usage (str): the usage type for the credentials: may be
+            'initiate', 'accept', or 'both'
+
+    Returns:
+        AcquireCredResult: the resulting credentials, the actual mechanisms
+        with which they may be used, and their actual lifetime (or None for
+        indefinite or not supported)
+
+    Raises:
+        ~gssapi.exceptions.BadMechanismError
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+        ~gssapi.exceptions.ExpiredCredentialsError
+        ~gssapi.exceptions.MissingCredentialsError
+    """
+
+
+def release_cred(
+    creds: Creds,
+) -> None:
+    """
+    release_cred(creds)
+    Release GSSAPI Credentials.
+
+    This method releases GSSAPI credentials.
+
+    Warning:
+        This method is deprecated.  Credentials are
+        automatically freed by Python.
+
+    Args:
+        creds (Creds): the credentials in question
+
+    Raises:
+        ~gssapi.exceptions.MissingCredentialsError
+    """
+
+
+def add_cred(
+    input_cred: Creds,
+    name: "Name",
+    mech: "OID",
+    usage: str = 'initiate',
+    init_lifetime: t.Optional[int] = None,
+    accept_lifetime: t.Optional[int] = None,
+    mutate_input: bool = False,
+) -> "AddCredResult":
+    """Add a credential element to a credential.
+
+    This method can be used to either compose two credentials (i.e., original
+    and new credential), or to add a new element to an existing credential.
+
+    Args:
+        input_cred (Cred): the set of credentials to which to add the new
+            credentials
+        name (~gssapi.raw.names.Name): name of principal to acquire a
+            credential for
+        mech (~gssapi.raw.types.MechType): the desired security mechanism
+            (required).
+        usage (str): usage type for credentials.  Possible values:
+            'initiate' (default), 'accept', 'both' (failsafe).
+        init_lifetime (int): lifetime of credentials for use in initiating
+            security contexts (None for indefinite)
+        accept_lifetime (int): lifetime of credentials for use in accepting
+            security contexts (None for indefinite)
+        mutate_input (bool): whether to mutate the input credentials (True)
+            or produce a new set of credentials (False).  Defaults to False
+
+    Returns:
+        AddCredResult: the actual mechanisms with which the credentials may be
+        used, the actual initiator TTL, and the actual acceptor TTL (None for
+        either indefinite or not supported).  Note that the credentials may
+        be set to None if mutate_input is set to True.
+
+    Raises:
+        ~gssapi.exceptions.BadMechanismError
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+        ~gssapi.exceptions.DuplicateCredentialsElementError
+        ~gssapi.exceptions.ExpiredCredentialsError
+        ~gssapi.exceptions.MissingCredentialsError
+    """
+
+
+def inquire_cred(
+    creds: Creds,
+    name: bool = True,
+    lifetime: bool = True,
+    usage: bool = True,
+    mechs: bool = True,
+) -> "InquireCredResult":
+    """Inspect credentials for information.
+
+    This method inspects a :class:`Creds` object for information.
+
+    Args:
+        creds (Creds): the credentials to inspect
+        name (bool): get the Name associated with the credentials
+        lifetime (bool): get the TTL for the credentials
+        usage (bool): get the usage type of the credentials
+        mechs (bool): the mechanims used with the credentials
+
+    Returns:
+        InquireCredResult: the information about the credentials,
+        with unused fields set to None
+
+    Raises:
+        ~gssapi.exceptions.MissingCredentialsError
+        ~gssapi.exceptions.InvalidCredentialsError
+        ~gssapi.exceptions.ExpiredCredentialsError
+    """
+
+
+def inquire_cred_by_mech(
+    creds: Creds,
+    mech: "OID",
+    name: bool = True,
+    init_lifetime: bool = True,
+    accept_lifetime: bool = True,
+    usage: bool = True,
+) -> "InquireCredByMechResult":
+    """Inspect credentials for mechanism-specific information.
+
+    This method inspects a :class:`Creds` object for information
+    specific to a particular mechanism.  It functions similarly
+    to :func:`inquire_cred`.
+
+    Args:
+        creds (Creds): the credentials to inspect
+        mech (~gssapi.OID): the desired mechanism
+        name (bool): get the Name associated with the credentials
+        init_lifetime (bool): get the initiator TTL for the credentials
+        accept_lifetime (bool): get the acceptor TTL for the credentials
+        usage (bool): get the usage type of the credentials
+
+    Returns:
+        InquireCredByMechResult: the information about the credentials,
+        with unused fields set to None
+
+    Raises:
+        ~gssapi.exceptions.MissingCredentialsError
+        ~gssapi.exceptions.InvalidCredentialsError
+    """
diff --git a/gssapi/raw/creds.pyx b/gssapi/raw/creds.pyx
index caac3ea6..6a01cd02 100644
--- a/gssapi/raw/creds.pyx
+++ b/gssapi/raw/creds.pyx
@@ -56,9 +56,6 @@ cdef extern from "python_gssapi.h":
 
 
 cdef class Creds:
-    """
-    GSSAPI Credentials
-    """
     # defined in pxd
     # cdef gss_cred_id_t raw_creds
 
@@ -81,37 +78,6 @@ cdef class Creds:
 
 
 def acquire_cred(Name name=None, lifetime=None, mechs=None, usage='both'):
-    """
-    acquire_cred(name=None, lifetime=None, mechs=None, usage='both')
-    Get GSSAPI credentials for the given name and mechanisms.
-
-    This method gets GSSAPI credentials corresponding to the given name
-    and mechanims.  The desired TTL and usage for the the credential may also
-    be specified.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name for which to acquire the
-            credentials (or None for the "no name" functionality)
-        lifetime (int): the lifetime for the credentials (or None for
-            indefinite)
-        mechs (~gssapi.MechType): the desired mechanisms for which the
-            credentials should work, or None for the default set
-        usage (str): the usage type for the credentials: may be
-            'initiate', 'accept', or 'both'
-
-    Returns:
-        AcquireCredResult: the resulting credentials, the actual mechanisms
-        with which they may be used, and their actual lifetime (or None for
-        indefinite or not supported)
-
-    Raises:
-        ~gssapi.exceptions.BadMechanismError
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-        ~gssapi.exceptions.ExpiredCredentialsError
-        ~gssapi.exceptions.MissingCredentialsError
-    """
-
     cdef gss_OID_set desired_mechs
     if mechs is not None:
         desired_mechs = c_get_mech_oid_set(mechs)
@@ -162,23 +128,6 @@ def acquire_cred(Name name=None, lifetime=None, mechs=None, usage='both'):
 
 
 def release_cred(Creds creds not None):
-    """
-    release_cred(creds)
-    Release GSSAPI Credentials.
-
-    This method releases GSSAPI credentials.
-
-    Warning:
-        This method is deprecated.  Credentials are
-        automatically freed by Python.
-
-    Args:
-        creds (Creds): the credentials in question
-
-    Raises:
-        ~gssapi.exceptions.MissingCredentialsError
-    """
-
     cdef OM_uint32 maj_stat, min_stat
     maj_stat = gss_release_cred(&min_stat, &creds.raw_creds)
     if maj_stat != GSS_S_COMPLETE:
@@ -189,43 +138,6 @@ def release_cred(Creds creds not None):
 def add_cred(Creds input_cred, Name name not None, OID mech not None,
              usage='initiate', init_lifetime=None,
              accept_lifetime=None, mutate_input=False):
-    """
-    add_cred(input_cred, name, mech, usage='initiate', init_lifetime=None, \
-accept_lifetime=None, mutate_input=False)
-    Add a credential element to a credential.
-
-    This method can be used to either compose two credentials (i.e., original
-    and new credential), or to add a new element to an existing credential.
-
-    Args:
-        input_cred (Cred): the set of credentials to which to add the new
-            credentials
-        name (~gssapi.raw.names.Name): name of principal to acquire a
-            credential for
-        mech (~gssapi.MechType): the desired security mechanism (required).
-        usage (str): usage type for credentials.  Possible values:
-            'initiate' (default), 'accept', 'both' (failsafe).
-        init_lifetime (int): lifetime of credentials for use in initiating
-            security contexts (None for indefinite)
-        accept_lifetime (int): lifetime of credentials for use in accepting
-            security contexts (None for indefinite)
-        mutate_input (bool): whether to mutate the input credentials (True)
-            or produce a new set of credentials (False).  Defaults to False
-
-    Returns:
-        AddCredResult: the actual mechanisms with which the credentials may be
-        used, the actual initiator TTL, and the actual acceptor TTL (None for
-        either indefinite or not supported).  Note that the credentials may
-        be set to None if mutate_input is set to True.
-
-    Raises:
-        ~gssapi.exceptions.BadMechanismError
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-        ~gssapi.exceptions.DuplicateCredentialsElementError
-        ~gssapi.exceptions.ExpiredCredentialsError
-        ~gssapi.exceptions.MissingCredentialsError
-    """
     cdef gss_cred_usage_t c_usage
     if usage == 'initiate':
         c_usage = GSS_C_INITIATE
@@ -280,29 +192,6 @@ accept_lifetime=None, mutate_input=False)
 
 def inquire_cred(Creds creds not None, name=True, lifetime=True, usage=True,
                  mechs=True):
-    """
-    inquire_cred(creds, name=True, lifetime=True, usage=True, mechs=True)
-    Inspect credentials for information.
-
-    This method inspects a :class:`Creds` object for information.
-
-    Args:
-        creds (Creds): the credentials to inspect
-        name (bool): get the Name associated with the credentials
-        lifetime (bool): get the TTL for the credentials
-        usage (bool): get the usage type of the credentials
-        mechs (bool): the mechanims used with the credentials
-
-    Returns:
-        InquireCredResult: the information about the credentials,
-            with unused fields set to None
-
-    Raises:
-        ~gssapi.exceptions.MissingCredentialsError
-        ~gssapi.exceptions.InvalidCredentialsError
-        ~gssapi.exceptions.ExpiredCredentialsError
-    """
-
     # TODO(directxman12): add docs
     cdef gss_name_t res_name
     cdef gss_name_t *res_name_ptr = NULL
@@ -361,32 +250,6 @@ def inquire_cred(Creds creds not None, name=True, lifetime=True, usage=True,
 def inquire_cred_by_mech(Creds creds not None, OID mech not None,
                          name=True, init_lifetime=True,
                          accept_lifetime=True, usage=True):
-    """
-    inquire_cred_by_mech(creds, mech, name=True, init_lifetime=True, \
-accept_lifetime=True, usage=True)
-    Inspect credentials for mechanism-specific information.
-
-    This method inspects a :class:`Creds` object for information
-    specific to a particular mechanism.  It functions similarly
-    to :func:`inquire_cred`.
-
-    Args:
-        creds (Creds): the credentials to inspect
-        mech (~gssapi.OID): the desired mechanism
-        name (bool): get the Name associated with the credentials
-        init_lifetime (bool): get the initiator TTL for the credentials
-        accept_lifetime (bool): get the acceptor TTL for the credentials
-        usage (bool): get the usage type of the credentials
-
-    Returns:
-        InquireCredByMechResult: the information about the credentials,
-            with unused fields set to None
-
-    Raises:
-        ~gssapi.exceptions.MissingCredentialsError
-        ~gssapi.exceptions.InvalidCredentialsError
-    """
-
     # TODO(directxman12): add docs
     cdef gss_name_t res_name
     cdef gss_name_t *res_name_ptr = NULL
diff --git a/gssapi/raw/exceptions.pyi b/gssapi/raw/exceptions.pyi
new file mode 100644
index 00000000..4e2328f2
--- /dev/null
+++ b/gssapi/raw/exceptions.pyi
@@ -0,0 +1,67 @@
+from gssapi.raw.misc import GSSError
+
+class ParameterReadError(GSSError): ...
+
+class ParameterWriteError(GSSError): ...
+
+class MalformedParameterError(GSSError): ...
+
+class BadMechanismError(GSSError): ...
+
+class BadNameError(GSSError): ...
+
+class BadNameTypeError(GSSError): ...
+
+class BadChannelBindingsError(GSSError): ...
+
+class BadStatusError(GSSError): ...
+
+class BadMICError(GSSError): ...
+
+class MissingCredentialsError(GSSError): ...
+
+class MissingContextError(GSSError): ...
+
+class InvalidTokenError(GSSError): ...
+
+class InvalidCredentialsError(GSSError): ...
+
+class ExpiredCredentialsError(GSSError): ...
+
+class ExpiredContextError(GSSError): ...
+
+class BadQoPError(GSSError): ...
+
+class UnauthorizedError(GSSError): ...
+
+class OperationUnavailableError(GSSError): ...
+
+class DuplicateCredentialsElementError(GSSError): ...
+
+class MechanismNameRequiredError(GSSError): ...
+
+class NameReadError(ParameterReadError, BadNameError): ...
+
+class NameTypeReadError(ParameterReadError, BadNameTypeError): ...
+
+class TokenReadError(ParameterReadError, InvalidTokenError): ...
+
+class ContextReadError(ParameterReadError, MissingContextError): ...
+
+class CredentialsReadError(ParameterReadError, MissingCredentialsError): ...
+
+class ContextWriteError(ParameterWriteError, MissingContextError): ...
+
+class CredentialsWriteError(ParameterWriteError, MissingCredentialsError): ...
+
+class SupplementaryError(GSSError): ...
+
+class DuplicateTokenError(SupplementaryError): ...
+
+class ExpiredTokenError(SupplementaryError): ...
+
+class TokenOutOfSequenceError(SupplementaryError): ...
+
+class TokenTooLateError(TokenOutOfSequenceError): ...
+
+class TokenTooEarlyError(TokenOutOfSequenceError): ...
diff --git a/gssapi/raw/ext_cred_imp_exp.pyi b/gssapi/raw/ext_cred_imp_exp.pyi
new file mode 100644
index 00000000..2677e45c
--- /dev/null
+++ b/gssapi/raw/ext_cred_imp_exp.pyi
@@ -0,0 +1,44 @@
+"""Credentials Import/Export Extension"""
+
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+
+
+def export_cred(
+    creds: "Creds",
+) -> bytes:
+    """Export GSSAPI credentials.
+
+    This method exports GSSSAPI credentials into a token
+    which may be transmitted between different processes.
+
+    Args:
+        creds (Creds): the credentials object to be exported
+
+    Returns:
+        bytes: the exported token representing the given credentials object
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def import_cred(
+    token: bytes,
+) -> "Creds":
+    """Import GSSAPI credentials from a token.
+
+    This method imports a credentials object from a token
+    previously exported by :func:`export_cred`.
+
+    Args:
+        token (bytes): the token to import
+
+    Returns:
+        Creds: the imported credentials object
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_cred_imp_exp.pyx b/gssapi/raw/ext_cred_imp_exp.pyx
index aa43cf86..d0561448 100644
--- a/gssapi/raw/ext_cred_imp_exp.pyx
+++ b/gssapi/raw/ext_cred_imp_exp.pyx
@@ -1,4 +1,3 @@
-"""Credentials Import/Export Extension"""
 GSSAPI="BASE"  # This ensures that a full module is generated by Cython
 
 from gssapi.raw.cython_types cimport *
@@ -22,23 +21,6 @@ cdef extern from "python_gssapi_ext.h":
 
 
 def export_cred(Creds creds not None):
-    """
-    export_cred(creds)
-    Export GSSAPI credentials.
-
-    This method exports GSSSAPI credentials into a token
-    which may be transmitted between different processes.
-
-    Args:
-        creds (Creds): the credentials object to be exported
-
-    Returns:
-        bytes: the exported token representing the given credentials object
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     # GSS_C_EMPTY_BUFFER
     cdef gss_buffer_desc exported_creds = gss_buffer_desc(0, NULL)
 
@@ -56,23 +38,6 @@ def export_cred(Creds creds not None):
 
 
 def import_cred(token not None):
-    """
-    import_cred(token)
-    Import GSSAPI credentials from a token.
-
-    This method imports a credentials object from a token
-    previously exported by :func:`export_cred`.
-
-    Args:
-        token (bytes): the token to import
-
-    Returns:
-        Creds: the imported credentials object
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc token_buffer = gss_buffer_desc(len(token), token)
 
     cdef gss_cred_id_t creds
diff --git a/gssapi/raw/ext_cred_store.pyi b/gssapi/raw/ext_cred_store.pyi
new file mode 100644
index 00000000..b025f81e
--- /dev/null
+++ b/gssapi/raw/ext_cred_store.pyi
@@ -0,0 +1,136 @@
+"""Credential Store Extension"""
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.named_tuples import AcquireCredResult, StoreCredResult
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+
+
+def acquire_cred_from(
+    dict_store: t.Optional[
+        t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+    ] = None,
+    name: t.Optional["Name"] = None,
+    lifetime: t.Optional[int] = None,
+    mechs: t.Optional[t.Iterable["OID"]] = None,
+    usage: str = 'both',
+) -> "AcquireCredResult":
+    """Acquire credentials from the given store.
+
+    This method acquires credentials from the store specified by the
+    given credential store information.
+
+    The credential store information is a dictionary containing
+    mechanisms-specific keys and values pointing to a credential store
+    or stores.
+
+    Args:
+        store (dict): the credential store information pointing to the
+            credential store from which to acquire the credentials.
+            See :doc:`credstore` for valid values
+        name (~gssapi.raw.names.Name): the name associated with the
+            credentials, or None for the default name
+        lifetime (int): the desired lifetime of the credentials, or None
+            for indefinite
+        mechs (list): the desired mechanisms to be used with these
+            credentials, or None for the default set
+        usage (str): the usage for these credentials -- either 'both',
+            'initiate', or 'accept'
+
+    Returns:
+        AcquireCredResult: the acquired credentials and information about
+        them
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def add_cred_from(
+    dict_store: t.Optional[
+        t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+    ],
+    input_creds: "Creds",
+    name: "Name",
+    mech: "OID",
+    usage: str = 'both',
+    init_lifetime: t.Optional[int] = None,
+    accept_lifetime: t.Optional[int] = None,
+) -> "AcquireCredResult":
+    """Acquire credentials to add to the current set from the given store.
+
+    This method works like :func:`acquire_cred_from`, except that it
+    adds the acquired credentials for a single mechanism to a copy of
+    the current set, instead of creating a new set for multiple mechanisms.
+    Unlike :func:`~gssapi.raw.creds.acquire_cred`, you cannot pass None for the
+    desired name or mechanism.
+
+    The credential store information is a dictionary containing
+    mechanisms-specific keys and values pointing to a credential store
+    or stores.
+
+    Args:
+        store (dict): the store into which to store the credentials,
+            or None for the default store.
+            See :doc:`credstore` for valid values
+        name (~gssapi.raw.names.Name): the name associated with the credentials
+        mech (~gssapi.OID): the desired mechanism to be used with these
+            credentials
+        usage (str): the usage for these credentials -- either 'both',
+            'initiate', or 'accept'
+        init_lifetime (int): the desired initiate lifetime of the
+            credentials, or None for indefinite
+        accept_lifetime (int): the desired accept lifetime of the
+            credentials, or None for indefinite
+
+    Returns:
+        AcquireCredResult: the new credentials set and information about
+        it
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def store_cred_into(
+    dict_store: t.Optional[
+        t.Dict[t.Union[bytes, str], t.Union[bytes, str]]
+    ],
+    creds: "Creds",
+    usage: str = 'both',
+    mech: t.Optional["OID"] = None,
+    overwrite: bool = False,
+    set_default: bool = False,
+) -> "StoreCredResult":
+    """Store credentials into the given store.
+
+    This method stores the given credentials into the store specified
+    by the given store information.  They may then be retrieved later using
+    :func:`acquire_cred_from` or :func:`add_cred_from`.
+
+    The credential store information is a dictionary containing
+    mechanisms-specific keys and values pointing to a credential store
+    or stores.
+
+    Args:
+        store (dict): the store into which to store the credentials,
+            or None for the default store.
+            See :doc:`credstore` for valid values
+        creds (Creds): the credentials to store
+        usage (str): the usage to store the credentials with -- either
+            'both', 'initiate', or 'accept'
+        mech (~gssapi.OID): the mechansim to associate with the stored
+            credentials
+        overwrite (bool): whether or not to overwrite existing credentials
+            stored with the same name, etc
+        set_default (bool): whether or not to set these credentials as
+            the default credentials for the given store.
+
+    Returns:
+        StoreCredResult: the results of the credential storing operation
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_cred_store.pyx b/gssapi/raw/ext_cred_store.pyx
index 5edd5e65..0b216204 100644
--- a/gssapi/raw/ext_cred_store.pyx
+++ b/gssapi/raw/ext_cred_store.pyx
@@ -1,4 +1,3 @@
-"""Credential Store Extension"""
 GSSAPI="BASE"  # This ensures that a full module is generated by Cython
 
 from libc.string cimport memcmp, memcpy, memset
@@ -104,39 +103,6 @@ cdef void c_free_key_value_set(gss_key_value_set_desc *kvset):
 
 def acquire_cred_from(dict store=None, Name name=None, lifetime=None,
                       mechs=None, usage='both'):
-    """
-    acquire_cred_from(store=None, name=None, lifetime=None, mechs=None, \
-usage='both')
-    Acquire credentials from the given store.
-
-    This method acquires credentials from the store specified by the
-    given credential store information.
-
-    The credential store information is a dictionary containing
-    mechanisms-specific keys and values pointing to a credential store
-    or stores.
-
-    Args:
-        store (dict): the credential store information pointing to the
-            credential store from which to acquire the credentials.
-            See :doc:`credstore` for valid values
-        name (~gssapi.raw.names.Name): the name associated with the
-            credentials, or None for the default name
-        lifetime (int): the desired lifetime of the credentials, or None
-            for indefinite
-        mechs (list): the desired mechanisms to be used with these
-            credentials, or None for the default set
-        usage (str): the usage for these credentials -- either 'both',
-            'initiate', or 'accept'
-
-    Returns:
-        AcquireCredResult: the acquired credentials and information about
-        them
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_OID_set desired_mechs
     if mechs is not None:
         desired_mechs = c_get_mech_oid_set(mechs)
@@ -199,43 +165,6 @@ def add_cred_from(dict store, Creds input_creds,
                   Name name not None, OID mech not None,
                   usage='both', init_lifetime=None,
                   accept_lifetime=None):
-    """
-    add_cred_from(store, input_creds, name, mech, usage='both', \
-init_lifetime=None, accept_lifetime=None)
-    Acquire credentials to add to the current set from the given store.
-
-    This method works like :func:`acquire_cred_from`, except that it
-    adds the acquired credentials for a single mechanism to a copy of
-    the current set, instead of creating a new set for multiple mechanisms.
-    Unlike :func:`acquire_cred`, you cannot pass None for the desired name or
-    mechanism.
-
-    The credential store information is a dictionary containing
-    mechanisms-specific keys and values pointing to a credential store
-    or stores.
-
-    Args:
-        store (dict): the store into which to store the credentials,
-            or None for the default store.
-            See :doc:`credstore` for valid values
-        name (~gssapi.raw.names.Name): the name associated with the credentials
-        mech (~gssapi.OID): the desired mechanism to be used with these
-            credentials
-        usage (str): the usage for these credentials -- either 'both',
-            'initiate', or 'accept'
-        init_lifetime (int): the desired initiate lifetime of the
-            credentials, or None for indefinite
-        accept_lifetime (int): the desired accept lifetime of the
-            credentials, or None for indefinite
-
-    Returns:
-        AcquireCredResult: the new credentials set and information about
-        it
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef OM_uint32 input_initiator_ttl = c_py_ttl_to_c(init_lifetime)
     cdef OM_uint32 input_acceptor_ttl = c_py_ttl_to_c(accept_lifetime)
 
@@ -296,40 +225,6 @@ init_lifetime=None, accept_lifetime=None)
 def store_cred_into(dict store, Creds creds not None,
                     usage='both', OID mech=None, bint overwrite=False,
                     bint set_default=False):
-    """
-    store_cred_into(store, creds, usage='both', mech=None, overwrite=False, \
-set_default=False)
-    Store credentials into the given store.
-
-    This method stores the given credentials into the store specified
-    by the given store information.  They may then be retrieved later using
-    :func:`acquire_cred_from` or :func:`add_cred_from`.
-
-    The credential store information is a dictionary containing
-    mechanisms-specific keys and values pointing to a credential store
-    or stores.
-
-    Args:
-        store (dict): the store into which to store the credentials,
-            or None for the default store.
-            See :doc:`credstore` for valid values
-        creds (Creds): the credentials to store
-        usage (str): the usage to store the credentials with -- either
-            'both', 'initiate', or 'accept'
-        mech (~gssapi.OID): the mechansim to associate with the stored
-            credentials
-        overwrite (bool): whether or not to overwrite existing credentials
-            stored with the same name, etc
-        set_default (bool): whether or not to set these credentials as
-            the default credentials for the given store.
-
-    Returns:
-        StoreCredResult: the results of the credential storing operation
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_OID desired_mech
     if mech is not None:
         desired_mech = &mech.raw_oid
diff --git a/gssapi/raw/ext_dce.pyi b/gssapi/raw/ext_dce.pyi
new file mode 100644
index 00000000..a535df9c
--- /dev/null
+++ b/gssapi/raw/ext_dce.pyi
@@ -0,0 +1,187 @@
+import typing as t
+
+from enum import IntEnum
+
+from gssapi.raw.ext_dce_aead import wrap_aead, unwrap_aead
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import IOVUnwrapResult, WrapResult
+    from gssapi.raw.sec_contexts import SecurityContext
+
+
+class IOVBufferType(IntEnum):
+    """
+    IOV Buffer Types
+
+    This IntEnum represent GSSAPI IOV buffer
+    types to be used with the IOV methods.
+
+    The numbers behind the values correspond directly
+    to their C counterparts.
+    """
+
+    empty = 0 #: GSS_IOV_BUFFER_TYPE_EMPTY
+    data = 1 #: GSS_IOV_BUFFER_TYPE_DATA
+    header = 2 #: GSS_IOV_BUFFER_TYPE_HEADER
+    mech_params = 3 #: GSS_IOV_BUFFER_TYPE_MECH_PARAMS
+    trailer = 7 #: GSS_IOV_BUFFER_TYPE_TRAILER
+    padding = 9 #: GSS_IOV_BUFFER_TYPE_PADDING
+    stream = 10 #: GSS_IOV_BUFFER_TYPE_STREAM
+    sign_only = 11 #: GSS_IOV_BUFFER_TYPE_SIGN_ONLY
+    mic_token = 12 #: GSS_IOV_BUFFER_TYPE_MIC_TOKEN
+
+
+class IOVBuffer(t.NamedTuple):
+    type: IOVBufferType
+    allocate: t.Optional[bool]
+    value: t.Optional[bytes]
+
+
+class IOV:
+    """A GSSAPI IOV"""
+
+    def __init__(
+        self,
+        *args: t.Union[
+            IOVBuffer,
+            t.Tuple[
+                t.Union[IOVBufferType, int],
+                t.Optional[bool],
+                t.Optional[bytes]],
+            t.Tuple[
+                t.Union[IOVBufferType, int],
+                t.Optional[t.Union[bool, bytes]],
+            ],
+            bytes,
+            t.Union[IOVBufferType, int],
+        ],
+        std_layout: bool = True,
+        auto_alloc: bool = True,
+    ) -> None: ...
+
+    def __getitem__(
+        self,
+        ind: int,
+    ) -> IOVBuffer: ...
+
+    def __len__(self) -> int: ...
+
+    def __iter__(self) -> t.Iterator[IOVBuffer]: ...
+
+    def __contains__(
+        self,
+        item: IOVBuffer,
+    ) -> bool: ...
+
+    def __reversed__(self) -> t.Iterator[IOVBuffer]: ...
+
+    def index(
+        self,
+        value: t.Any,
+    ) -> int: ...
+
+    def count(
+        self,
+        value: t.Any,
+    ) -> int: ...
+
+
+def wrap_iov(
+    context: "SecurityContext",
+    message: IOV,
+    confidential: bool = True,
+    qop: t.Optional[int] = None,
+) -> bool:
+    """Wrap/Encrypt an IOV message.
+
+    This method wraps or encrypts an IOV message.  The allocate
+    parameter of the :class:`IOVBuffer` objects in the :class:`IOV`
+    indicates whether or not that particular buffer should be
+    automatically allocated (for use with padding, header, and
+    trailer buffers).
+
+    Warning:
+        This modifies the input :class:`IOV`.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (IOV): an :class:`IOV` containing the message
+        confidential (bool): whether or not to encrypt the miovessage (True),
+            or just wrap it with a MIC (False)
+        qop (int): the desired Quality of Protection
+            (or None for the default QoP)
+
+    Returns:
+        bool: whether or not confidentiality was actually used
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def unwrap_iov(
+    context: "SecurityContext",
+    message: IOV,
+) -> "IOVUnwrapResult":
+    """Unwrap/Decrypt an IOV message.
+
+    This method uwraps or decrypts an IOV message.  The allocate
+    parameter of the :class:`IOVBuffer` objects in the :class:`IOV`
+    indicates whether or not that particular buffer should be
+    automatically allocated (for use with padding, header, and
+    trailer buffers).
+
+    As a special case, you may pass an entire IOV message
+    as a single 'stream'.  In this case, pass a buffer type
+    of :attr:`IOVBufferType.stream` followed by a buffer type of
+    :attr:`IOVBufferType.data`.  The former should contain the
+    entire IOV message, while the latter should be empty.
+
+    Warning:
+        This modifies the input :class:`IOV`.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (IOV): an :class:`IOV` containing the message
+
+    Returns:
+        IOVUnwrapResult: whether or not confidentiality was used,
+        and the QoP used.
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def wrap_iov_length(
+    context: "SecurityContext",
+    message: IOV,
+    confidential: bool = True,
+    qop: t.Optional[int] = None,
+) -> "WrapResult":
+    """Appropriately size padding, trailer, and header IOV buffers.
+
+    This method sets the length values on the IOV buffers.  You
+    should already have data provided for the data (and sign-only)
+    buffer(s) so that padding lengths can be appropriately computed.
+
+    In Python terms, this will result in an appropriately sized
+    `bytes` object consisting of all zeros.
+
+    Warning:
+        This modifies the input :class:`IOV`.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (IOV): an :class:`IOV` containing the message
+
+    Returns:
+        WrapResult: a list of :class:IOVBuffer` objects, and whether or not
+        encryption was actually used
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_dce.pyx b/gssapi/raw/ext_dce.pyx
index 7cc44b25..19476bb9 100644
--- a/gssapi/raw/ext_dce.pyx
+++ b/gssapi/raw/ext_dce.pyx
@@ -71,16 +71,6 @@ cdef extern from "python_gssapi_ext.h":
 
 
 class IOVBufferType(IntEnum, metaclass=ExtendableEnum):
-    """
-    IOV Buffer Types
-
-    This IntEnum represent GSSAPI IOV buffer
-    types to be used with the IOV methods.
-
-    The numbers behind the values correspond directly
-    to their C counterparts.
-    """
-
     empty = GSS_IOV_BUFFER_TYPE_EMPTY
     data = GSS_IOV_BUFFER_TYPE_DATA
     header = GSS_IOV_BUFFER_TYPE_HEADER
@@ -95,7 +85,6 @@ IOVBuffer = namedtuple('IOVBuffer', ['type', 'allocate', 'value'])
 
 
 cdef class IOV:
-    """A GSSAPI IOV"""
     # defined in ext_dce.pxd
 
     # cdef int iov_len
@@ -308,35 +297,6 @@ cdef class IOV:
 
 def wrap_iov(SecurityContext context not None, IOV message not None,
              confidential=True, qop=None):
-    """
-    wrap_iov(context, message, confidential=True, qop=None)
-    Wrap/Encrypt an IOV message.
-
-    This method wraps or encrypts an IOV message.  The allocate
-    parameter of the :class:`IOVBuffer` objects in the :class:`IOV`
-    indicates whether or not that particular buffer should be
-    automatically allocated (for use with padding, header, and
-    trailer buffers).
-
-    Warning:
-        This modifies the input :class:`IOV`.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (IOV): an :class:`IOV` containing the message
-        confidential (bool): whether or not to encrypt the message (True),
-            or just wrap it with a MIC (False)
-        qop (int): the desired Quality of Protection
-            (or None for the default QoP)
-
-    Returns:
-        bool: whether or not confidentiality was actually used
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef int conf_req = confidential
     cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT
     cdef int conf_used
@@ -357,38 +317,6 @@ def wrap_iov(SecurityContext context not None, IOV message not None,
 
 
 def unwrap_iov(SecurityContext context not None, IOV message not None):
-    """
-    unwrap_iov(context, message)
-    Unwrap/Decrypt an IOV message.
-
-    This method uwraps or decrypts an IOV message.  The allocate
-    parameter of the :class:`IOVBuffer` objects in the :class:`IOV`
-    indicates whether or not that particular buffer should be
-    automatically allocated (for use with padding, header, and
-    trailer buffers).
-
-    As a special case, you may pass an entire IOV message
-    as a single 'stream'.  In this case, pass a buffer type
-    of :attr:`IOVBufferType.stream` followed by a buffer type of
-    :attr:`IOVBufferType.data`.  The former should contain the
-    entire IOV message, while the latter should be empty.
-
-    Warning:
-        This modifies the input :class:`IOV`.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (IOV): an :class:`IOV` containing the message
-
-    Returns:
-        IOVUnwrapResult: whether or not confidentiality was used,
-        and the QoP used.
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef int conf_used
     cdef gss_qop_t qop_used
     cdef gss_iov_buffer_desc *res_arr = message.__cvalue__()
@@ -408,33 +336,6 @@ def unwrap_iov(SecurityContext context not None, IOV message not None):
 
 def wrap_iov_length(SecurityContext context not None, IOV message not None,
                     confidential=True, qop=None):
-    """
-    wrap_iov_length(context, message, confidential=True, qop=None)
-    Appropriately size padding, trailer, and header IOV buffers.
-
-    This method sets the length values on the IOV buffers.  You
-    should already have data provided for the data (and sign-only)
-    buffer(s) so that padding lengths can be appropriately computed.
-
-    In Python terms, this will result in an appropriately sized
-    `bytes` object consisting of all zeros.
-
-    Warning:
-        This modifies the input :class:`IOV`.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (IOV): an :class:`IOV` containing the message
-
-    Returns:
-        WrapResult: a list of :class:IOVBuffer` objects, and whether or not
-        encryption was actually used
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef int conf_req = confidential
     cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT
     cdef int conf_used
diff --git a/gssapi/raw/ext_dce_aead.pyi b/gssapi/raw/ext_dce_aead.pyi
new file mode 100644
index 00000000..55310f1e
--- /dev/null
+++ b/gssapi/raw/ext_dce_aead.pyi
@@ -0,0 +1,61 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import WrapResult, UnwrapResult
+    from gssapi.raw.sec_contexts import SecurityContext
+
+
+def wrap_aead(
+    context: "SecurityContext",
+    message: bytes,
+    associated: t.Optional[bytes] = None,
+    confidential: bool = True,
+    qop: t.Optional[int] = None,
+) -> "WrapResult":
+    """Wrap/Encrypt an AEAD message.
+
+    This method takes an input message and associated data,
+    and outputs and AEAD message.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (bytes): the message to wrap or encrypt
+        associated (bytes): associated data to go with the message
+        confidential (bool): whether or not to encrypt the message (True),
+            or just wrap it with a MIC (False)
+        qop (int): the desired Quality of Protection
+            (or None for the default QoP)
+
+    Returns:
+        WrapResult: the wrapped/encrypted total message, and whether or not
+        encryption was actually used
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def unwrap_aead(
+    context: "SecurityContext",
+    message: bytes,
+    associated: t.Optional[bytes] = None,
+) -> "UnwrapResult":
+    """Unwrap/Decrypt an AEAD message.
+
+    This method takes an encrpyted/wrapped AEAD message and some associated
+    data, and returns an unwrapped/decrypted message.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (bytes): the AEAD message to unwrap or decrypt
+        associated (bytes): associated data that goes with the message
+
+    Returns:
+        UnwrapResult: the unwrapped/decrypted message, whether or on
+        encryption was used, and the QoP used
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_dce_aead.pyx b/gssapi/raw/ext_dce_aead.pyx
index 32af479b..2b31dbf4 100644
--- a/gssapi/raw/ext_dce_aead.pyx
+++ b/gssapi/raw/ext_dce_aead.pyx
@@ -23,31 +23,6 @@ cdef extern from "python_gssapi_ext.h":
 
 def wrap_aead(SecurityContext context not None, bytes message not None,
               bytes associated=None, confidential=True, qop=None):
-    """
-    wrap_aead(context, message, associated=None, confidential=True, qop=None)
-    Wrap/Encrypt an AEAD message.
-
-    This method takes an input message and associated data,
-    and outputs and AEAD message.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (bytes): the message to wrap or encrypt
-        associated (bytes): associated data to go with the message
-        confidential (bool): whether or not to encrypt the message (True),
-            or just wrap it with a MIC (False)
-        qop (int): the desired Quality of Protection
-            (or None for the default QoP)
-
-    Returns:
-        WrapResult: the wrapped/encrypted total message, and whether or not
-        encryption was actually used
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef int conf_req = confidential
     cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT
     cdef gss_buffer_desc message_buffer = gss_buffer_desc(len(message),
@@ -80,27 +55,6 @@ def wrap_aead(SecurityContext context not None, bytes message not None,
 
 def unwrap_aead(SecurityContext context not None, bytes message not None,
                 bytes associated=None):
-    """
-    unwrap_aead(context, message, associated=None)
-    Unwrap/Decrypt an AEAD message.
-
-    This method takes an encrpyted/wrapped AEAD message and some associated
-    data, and returns an unwrapped/decrypted message.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (bytes): the AEAD message to unwrap or decrypt
-        associated (bytes): associated data that goes with the message
-
-    Returns:
-        UnwrapResult: the unwrapped/decrypted message, whether or on
-        encryption was used, and the QoP used
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc input_buffer = gss_buffer_desc(len(message), message)
 
     cdef gss_buffer_t assoc_buffer_ptr = GSS_C_NO_BUFFER
diff --git a/gssapi/raw/ext_ggf.pyi b/gssapi/raw/ext_ggf.pyi
new file mode 100644
index 00000000..30436667
--- /dev/null
+++ b/gssapi/raw/ext_ggf.pyi
@@ -0,0 +1,97 @@
+"""
+GGF Extensions
+
+GGF provides extended credential and security context inquiry that allows
+application to retrieve more information about the client's credentials and
+security context. One common use case is to use
+:meth:`inquire_sec_context_by_oid` to retrieve the "session" key that is
+required by the SMB protocol for signing and encrypting a message.
+
+Draft IETF document for these extensions can be found at
+https://tools.ietf.org/html/draft-engert-ggf-gss-extensions-00
+"""
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.oids import OID
+    from gssapi.raw.sec_contexts import SecurityContext
+
+
+def inquire_cred_by_oid(
+    cred_handle: "Creds",
+    desired_aspect: "OID",
+) -> t.List[bytes]:
+    """
+    This method inspects a :class:`~gssapi.raw.creds.Creds` object for
+    information specific to a particular desired aspect as an OID.
+
+    Args:
+        cred_handle (Creds): the Credentials to query
+        desired_aspect (~gssapi.raw.oids.OID): the desired aspect of the
+            Credentials to inquire about.
+
+    Returns:
+        list: A list of zero or more pieces of data (as bytes objects)
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def inquire_sec_context_by_oid(
+    context: "SecurityContext",
+    desired_aspect: "OID",
+) -> t.List[bytes]:
+    """
+    This method inspects a :class:`~gssapi.raw.sec_contexts.SecurityContext`
+    object for information specific to a particular desired aspect as an OID.
+
+    This method can be used with the GSS_KRB5_INQ_SSPI_SESSION_KEY_OID OID to
+    retrieve the required key that is used to derive the SMB/SAMBA signing and
+    encryption keys.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the Security
+            Context to query
+        desired_aspect (~gssapi.raw.oids.OID): the desired aspect of the
+            Security Context to inquire about.
+
+    Returns:
+        list: A list of zero or more pieces of data (as bytes objects)
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def set_sec_context_option(
+    desired_aspect: "OID",
+    context: "SecurityContext",
+    value: t.Optional[bytes] = None,
+) -> None:
+    """
+    This method is used to set a value for a specific OID of a
+    :class:`~gssapi.raw.sec_contexts.SecurityContext` object. The OID and value
+    to pass in depends on the mech the SecurityContext backs.
+
+    An example of how this can be used would be to reset the NTLM crypto engine
+    used in gss-ntlmssp. The OID that controls this value is
+    '1.3.6.1.4.1.7165.655.1.3' and it takes it a byte value that represents
+    an int32 where 1 resets the verifier handle and any other int resets the
+    sender handle.
+
+    Args:
+        desired_aspect (~gssapi.raw.oids.OID): the desired aspect of the
+            Security Context to set the value for.
+        context (~gssapi.raw.sec_contexts.SecurityContext): the Security
+            Context to set, or None to create a new context.
+        value (bytes): the value to set on the desired aspect of the Security
+            Context or None to send GSS_C_EMPTY_BUFFER.
+
+    Returns:
+        ~gssapi.raw.sec_contexts.SecurityContext: The output security context.
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_ggf.pyx b/gssapi/raw/ext_ggf.pyx
index 249631ac..ba689cf8 100644
--- a/gssapi/raw/ext_ggf.pyx
+++ b/gssapi/raw/ext_ggf.pyx
@@ -1,15 +1,3 @@
-"""
-GGF Extensions
-
-GGF provides extended credential and security context inquiry that allows
-application to retrieve more information about the client's credentials and
-security context. One common use case is to use
-:meth:`inquire_sec_context_by_oid` to retrieve the "session" key that is
-required by the SMB protocol for signing and encrypting a message.
-
-Draft IETF document for these extensions can be found at
-https://tools.ietf.org/html/draft-engert-ggf-gss-extensions-00
-"""
 GSSAPI="BASE"  # This ensures that a full module is generated by Cython
 
 from gssapi.raw.cython_types cimport *
@@ -39,24 +27,6 @@ cdef extern from "python_gssapi_ext.h":
 
 def inquire_cred_by_oid(Creds cred_handle not None,
                         OID desired_aspect not None):
-    """
-    inquire_cred_by_oid(cred_handle, desired_aspect)
-
-    This method inspects a :class:`Creds` object for information
-    specific to a particular desired aspect as an OID.
-
-    Args:
-        cred_handle (Creds): the Credentials to query
-        desired_aspect (~gssapi.OID): the desired aspect of the Credentials
-            to inquire about.
-
-    Returns:
-        list: A list of zero or more pieces of data (as bytes objects)
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_set_t *data_set_ptr = NULL
     cdef gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET
     cdef OM_uint32 maj_stat, min_stat
@@ -85,29 +55,6 @@ def inquire_cred_by_oid(Creds cred_handle not None,
 
 def inquire_sec_context_by_oid(SecurityContext context not None,
                                OID desired_aspect not None):
-    """
-    inquire_sec_context_by_oid(context, desired_aspect)
-
-    This method inspects a :class:`SecurityContext` object for information
-    specific to a particular desired aspect as an OID.
-
-    This method can be used with the GSS_KRB5_INQ_SSPI_SESSION_KEY_OID OID to
-    retrieve the required key that is used to derive the SMB/SAMBA signing and
-    encryption keys.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the Security
-            Context to query
-        desired_aspect (~gssapi.OID): the desired aspect of the Security
-            Context to inquire about.
-
-    Returns:
-        list: A list of zero or more pieces of data (as bytes objects)
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_set_t *data_set_ptr = NULL
     cdef gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET
     cdef OM_uint32 maj_stat, min_stat
@@ -137,34 +84,6 @@ def inquire_sec_context_by_oid(SecurityContext context not None,
 def set_sec_context_option(OID desired_aspect not None,
                            SecurityContext context=None,
                            value=None):
-    """
-    set_sec_context_option(desired_aspect, context=None, value=None)
-
-    This method is used to set a value for a specific OID of a
-    :class:`SecurityContext` object. The OID and value to pass in depends on
-    the mech the SecurityContext backs.
-
-    An example of how this can be used would be to reset the NTLM crypto engine
-    used in gss-ntlmssp. The OID that controls this value is
-    '1.3.6.1.4.1.7165.655.1.3' and it takes it a byte value that represents
-    an int32 where 1 resets the verifier handle and any other int resets the
-    sender handle.
-
-    Args:
-        desired_aspect (~gssapi.OID): the desired aspect of the Security
-            Context to set the value for.
-        context (~gssapi.raw.sec_contexts.SecurityContext): the Security
-            Context to set, or None to create a new context.
-        value (bytes): the value to set on the desired aspect of the Security
-            Context or None to send GSS_C_EMPTY_BUFFER.
-
-    Returns:
-        ~gssapi.raw.sec_contexts.SecurityContext: The output security context.
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc value_buffer
     if value is not None:
         value_buffer = gss_buffer_desc(len(value), value)
diff --git a/gssapi/raw/ext_iov_mic.pyi b/gssapi/raw/ext_iov_mic.pyi
new file mode 100644
index 00000000..377db63b
--- /dev/null
+++ b/gssapi/raw/ext_iov_mic.pyi
@@ -0,0 +1,90 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.ext_dce import IOV
+    from gssapi.raw.sec_contexts import SecurityContext
+
+
+def get_mic_iov(
+    context: "SecurityContext",
+    message: "IOV",
+    qop: t.Optional[int] = None,
+) -> None:
+    """Generate MIC tokens for the given IOV message.
+
+    This method generates a MIC token for the given IOV message, and places it
+    in the :attr:`~gssapi.raw.ext_dce.IOVBufferType.mic_token` buffer in the
+    IOV. This method operates entirely in-place, and returns nothing.
+
+    Warning:
+        This modifies the input :class:`~gssapi.raw.ext_dce.IOV`.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (IOV): the :class:`~gssapi.raw.ext_dce.IOV` containing the
+            message
+        qop (int): the desired Quality of Protection
+            (or None for the default QoP)
+
+    Returns:
+        None
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def get_mic_iov_length(
+    context: "SecurityContext",
+    message: "IOV",
+    qop: t.Optional[int] = None,
+) -> None:
+    """Allocate space for the MIC buffer in the given IOV message.
+
+    This method allocates space for the MIC token buffer
+    (:attr:`~gssapi.raw.ext_dce.IOVBufferType.mic_token`) in the given IOV
+    message.
+
+    Warning:
+        This modifies the input :class:`~gssapi.raw.ext_dce.IOV`.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (IOV): the :class:`~gssapi.raw.ext_dce.IOV` containing the
+            message
+        qop (int): the desired Quality of Protection
+            (or None for the default QoP)
+
+    Returns:
+        None
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def verify_mic_iov(
+    context: "SecurityContext",
+    message: "IOV",
+    qop: t.Optional[int] = None,
+) -> int:
+    """Verify that the MIC matches the data in the given IOV message.
+
+    This method verifies that the MIC token in the MIC buffer
+    (:attr:`~gssapi.raw.ext_dce.IOVBufferType.mic_token`) match the data
+    buffer(s) in the given IOV method.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (IOV): the :class:`~gssapi.raw.ext_dce.IOV` containing the
+            message
+
+    Returns:
+        int: the QoP used to generate the MIC token
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_iov_mic.pyx b/gssapi/raw/ext_iov_mic.pyx
index 8d31ff5c..f6c5dda1 100644
--- a/gssapi/raw/ext_iov_mic.pyx
+++ b/gssapi/raw/ext_iov_mic.pyx
@@ -33,31 +33,6 @@ IOV.AUTO_ALLOC_BUFFERS.add(IOVBufferType.mic_token)
 
 def get_mic_iov(SecurityContext context not None, IOV message not None,
                 qop=None):
-    """
-    get_mic_iov(context, message, qop=None)
-    Generate MIC tokens for the given IOV message.
-
-    This method generates a MIC token for the given IOV message, and places it
-    in the :attr:`IOVBufferType.mic_token` buffer in the IOV.  This method
-    operates entirely in-place, and returns nothing.
-
-    Warning:
-        This modifies the input :class:`IOV`.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (IOV): the :class:`IOV` containing the message
-        qop (int): the desired Quality of Protection
-            (or None for the default QoP)
-
-    Returns:
-        None
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT
 
     cdef gss_iov_buffer_desc *res_arr = message.__cvalue__()
@@ -77,30 +52,6 @@ def get_mic_iov(SecurityContext context not None, IOV message not None,
 
 def get_mic_iov_length(SecurityContext context not None, IOV message not None,
                        qop=None):
-    """
-    get_mic_iov_length(context, message, qop=None)
-    Allocate space for the MIC buffer in the given IOV message.
-
-    This method allocates space for the MIC token buffer
-    (:attr:`IOVBufferType.mic_token`) in the given IOV message.
-
-    Warning:
-        This modifies the input :class:`IOV`.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (IOV): the :class:`IOV` containing the message
-        qop (int): the desired Quality of Protection
-            (or None for the default QoP)
-
-    Returns:
-        None
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_qop_t qop_req = qop if qop is not None else GSS_C_QOP_DEFAULT
 
     cdef gss_iov_buffer_desc *res_arr = message.__cvalue__()
@@ -120,26 +71,6 @@ def get_mic_iov_length(SecurityContext context not None, IOV message not None,
 
 def verify_mic_iov(SecurityContext context not None, IOV message not None,
                    qop=None):
-    """
-    verify_mic_iov(context, message, qop=None)
-    Verify that the MIC matches the data in the given IOV message.
-
-    This method verifies that the MIC token in the MIC buffer
-    (:attr:`IOVBufferType.mic_token`) match the data buffer(s)
-    in the given IOV method.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        message (IOV): the :class:`IOV` containing the message
-
-    Returns:
-        int: the QoP used to generate the MIC token
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_iov_buffer_desc *res_arr = message.__cvalue__()
 
     cdef gss_qop_t qop_state
diff --git a/gssapi/raw/ext_krb5.pyi b/gssapi/raw/ext_krb5.pyi
new file mode 100644
index 00000000..f109c8b0
--- /dev/null
+++ b/gssapi/raw/ext_krb5.pyi
@@ -0,0 +1,280 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.named_tuples import CfxKeyData, Rfc1964KeyData
+    from gssapi.raw.sec_contexts import SecurityContext
+
+
+class Krb5LucidContext:
+    """
+    The base container returned by :meth:`krb5_export_lucid_sec_context` when
+    an unknown version was requested.
+    """
+
+
+class Krb5LucidContextV1(Krb5LucidContext):
+    """
+    Kerberos context data returned by :meth:`krb5_export_lucid_sec_context`
+    when version 1 was requested.
+    """
+
+    @property
+    def version(self) -> t.Optional[int]:
+        """The structure version number
+
+        Returns:
+            Optional[int]: the structure version number
+        """
+
+    @property
+    def is_initiator(self) -> t.Optional[bool]:
+        """Whether the context was the initiator
+
+        Returns:
+            Optional[bool]: ``True`` when the exported context was the
+            initiator
+        """
+
+    @property
+    def endtime(self) -> t.Optional[int]:
+        """Expiration time of the context
+
+        Returns:
+            Optional[int]: the expiration time of the context
+        """
+
+    @property
+    def send_seq(self) -> t.Optional[int]:
+        """Sender sequence number
+
+        Returns:
+            Optional[int]: the sender sequence number
+        """
+
+    @property
+    def recv_seq(self) -> t.Optional[int]:
+        """Receiver sequence number
+
+        Returns:
+            Optional[int]: the receiver sequence number
+        """
+
+    @property
+    def protocol(self) -> t.Optional[int]:
+        """The protocol number
+
+        If the protocol number is 0 then :attr:`rfc1964_kd` is set and
+        :attr:`cfx_kd` is `None`. If the protocol number is 1 then the opposite
+        is true.
+
+        Protocol 0 refers to RFC1964 and 1 refers to RFC4121.
+
+        Returns:
+            Optional[int]: the protocol number
+        """
+
+    @property
+    def rfc1964_kd(self) -> t.Optional["Rfc1964KeyData"]:
+        """Keydata for protocol 0 (RFC1964)
+
+        This will be set when :attr:`protocol` is ``0``.
+
+        Returns:
+            Optional[Rfc1964KeyData]: the RFC1964 key data
+        """
+
+    @property
+    def cfx_kd(self) -> t.Optional["CfxKeyData"]:
+        """Key data for protocol 1 (RFC4121)
+
+        This will be set when :attr:`protocol` is ``1``.
+
+        Returns:
+            Optional[CfxKeyData]: the RFC4121 key data
+        """
+
+
+def krb5_ccache_name(
+    name: t.Optional[bytes],
+) -> bytes:
+    """Set the default Kerberos Protocol credentials cache name.
+
+    This method sets the default credentials cache name for use by he Kerberos
+    mechanism. The default credentials cache is used by
+    :meth:`~gssapi.raw.creds.acquire_cred` to create a GSS-API credential. It
+    is also used by :meth:`~gssapi.raw.sec_contexts.init_sec_context` when
+    `GSS_C_NO_CREDENTIAL` is specified.
+
+    Note:
+        Heimdal does not return the old name when called. It also does not
+        reset the ccache lookup behaviour when setting to ``None``.
+
+    Note:
+        The return value may not be thread safe.
+
+    Args:
+        name (Optional[bytes]): the name to set as the new thread specific
+            ccache name. Set to ``None`` to revert back to getting the ccache
+            from the config/environment settings.
+
+    Returns:
+        bytes: the old name that was previously set
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def krb5_export_lucid_sec_context(
+    context: "SecurityContext",
+    version: int,
+) -> Krb5LucidContext:
+    """Retuns a non-opaque version of the internal context info.
+
+    Gets information about the Kerberos security context passed in. Currently
+    only version 1 is known and supported by this library.
+
+    Note:
+        The context handle must not be used again by the caller after this
+        call.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        version (int): the output structure version to export.  Currently
+            only 1 is supported.
+
+    Returns:
+        Krb5LucidContext: the non-opaque version context info
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def krb5_extract_authtime_from_sec_context(
+    context: "SecurityContext",
+) -> int:
+    """Get the auth time for the security context.
+
+    Gets the auth time for the established security context.
+
+    Note:
+        Heimdal can only get the authtime on the acceptor security context.
+        MIT is able to get the authtime on both initiators and acceptors.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+
+    Returns:
+        int: the authtime
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def krb5_extract_authz_data_from_sec_context(
+    context: "SecurityContext",
+    ad_type: int,
+) -> bytes:
+    """Extracts Kerberos authorization data.
+
+    Extracts authorization data that may be stored within the context.
+
+    Note:
+        Only operates on acceptor contexts.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        ad_type (int): the type of data to extract
+
+    Returns:
+        bytes: the raw authz data from the sec context
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def krb5_import_cred(
+    cred_handle: "Creds",
+    cache: t.Optional[int] = None,
+    keytab_principal: t.Optional[int] = None,
+    keytab: t.Optional[int] = None,
+) -> None:
+    """Import Krb5 credentials into GSSAPI credential.
+
+    Imports the krb5 credentials (either or both of the keytab and cache) into
+    the GSSAPI credential so it can be used within GSSAPI. The ccache is
+    copied by reference and thus shared, so if the credential is destroyed,
+    all users of cred_handle will fail.
+
+    Args:
+        cred_handle (Creds): the credential handle to import into
+        cache (int): the krb5_ccache address pointer, as an int, to import
+            from
+        keytab_principal (int): the krb5_principal address pointer, as an int,
+            of the credential to import
+        keytab (int): the krb5_keytab address pointer, as an int, of the
+            keytab to import
+
+    Returns:
+        None
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def krb5_get_tkt_flags(
+    context: "SecurityContext",
+) -> int:
+    """Return ticket flags for the kerberos ticket.
+
+    Return the ticket flags for the kerberos ticket received when
+    authenticating the initiator.
+
+    Note:
+        Heimdal can only get the tkt flags on the acceptor security context.
+        MIT is able to get the tkt flags on initators and acceptors.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the security
+            context
+
+    Returns:
+        int: the ticket flags for the received kerberos ticket
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def krb5_set_allowable_enctypes(
+    cred_handle: "Creds",
+    ktypes: t.Iterable[int],
+) -> None:
+    """Limits the keys that can be exported.
+
+    Called by a context initiator after acquiring the creds but before calling
+    :meth:`~gssapi.raw.sec_contexts.init_sec_context` to restrict the set of
+    enctypes which will be negotiated during context establisment to those in
+    the provided list.
+
+    Warning:
+        The cred_handle should not be ``GSS_C_NO_CREDENTIAL``.
+
+    Args:
+        cred_hande (Creds): the credential handle
+        ktypes (List[int]): list of enctypes allowed
+
+    Returns:
+        None
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_krb5.pyx b/gssapi/raw/ext_krb5.pyx
index 3ac36b64..d6134a30 100644
--- a/gssapi/raw/ext_krb5.pyx
+++ b/gssapi/raw/ext_krb5.pyx
@@ -105,10 +105,6 @@ cdef extern from "python_gssapi_krb5.h":
 
 
 cdef class Krb5LucidContext:
-    """
-    The base container returned by :meth:`krb5_export_lucid_sec_context` when
-    an unknown version was requested.
-    """
     # defined in pxd
     # cdef void *raw_ctx
 
@@ -124,18 +120,9 @@ cdef class Krb5LucidContext:
 
 
 cdef class Krb5LucidContextV1(Krb5LucidContext):
-    """
-    Kerberos context data returned by :meth:`krb5_export_lucid_sec_context`
-    when version 1 was requested.
-    """
 
     @property
     def version(self) -> typing.Optional[int]:
-        """The structure version number
-
-        Returns:
-            Optional[int]: the structure version number
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx:
@@ -144,12 +131,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def is_initiator(self) -> typing.Optional[bool]:
-        """Whether the context was the initiator
-
-        Returns:
-            Optional[bool]: ``True`` when the exported context was the
-            initiator
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx:
@@ -158,11 +139,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def endtime(self) -> typing.Optional[int]:
-        """Expiration time of the context
-
-        Returns:
-            Optional[int]: the expiration time of the context
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx:
@@ -171,11 +147,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def send_seq(self) -> typing.Optional[int]:
-        """Sender sequence number
-
-        Returns:
-            Optional[int]: the sender sequence number
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx:
@@ -184,11 +155,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def recv_seq(self) -> typing.Optional[int]:
-        """Receiver sequence number
-
-        Returns:
-            Optional[int]: the receiver sequence number
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx:
@@ -197,17 +163,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def protocol(self) -> typing.Optional[int]:
-        """The protocol number
-
-        If the protocol number is 0 then :attr:`rfc1964_kd` is set and
-        :attr:`cfx_kd` is `None`. If the protocol number is 1 then the opposite
-        is true.
-
-        Protocol 0 refers to RFC1964 and 1 refers to RFC4121.
-
-        Returns:
-            Optional[int]: the protocol number
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx:
@@ -216,13 +171,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def rfc1964_kd(self) -> typing.Optional[Rfc1964KeyData]:
-        """Keydata for protocol 0 (RFC1964)
-
-        This will be set when :attr:`protocol` is ``0``.
-
-        Returns:
-            Optional[Rfc1964KeyData]: the RFC1964 key data
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx != NULL and self.protocol == 0:
@@ -235,13 +183,6 @@ cdef class Krb5LucidContextV1(Krb5LucidContext):
 
     @property
     def cfx_kd(self) -> typing.Optional[CfxKeyData]:
-        """Key data for protocol 1 (RFC4121)
-
-        This will be set when :attr:`protocol` is ``1``.
-
-        Returns:
-            Optional[CfxKeyData]: the RFC4121 key data
-        """
         cdef gss_krb5_lucid_context_v1_t *ctx = NULL
 
         if self.raw_ctx != NULL and self.protocol == 1:
@@ -267,34 +208,6 @@ gsstypes.NameType.krb5_nt_principal_name = c_make_oid(
 
 
 def krb5_ccache_name(const unsigned char[:] name):
-    """
-    krb5_ccache_name(name)
-    Set the default Kerberos Protocol credentials cache name.
-
-    This method sets the default credentials cache name for use by he Kerberos
-    mechanism. The default credentials cache is used by
-    :meth:`~gssapi.raw.creds.acquire_cred` to create a GSS-API credential. It
-    is also used by :meth:`~gssapi.raw.sec_contexts.init_sec_context` when
-    `GSS_C_NO_CREDENTIAL` is specified.
-
-    Note:
-        Heimdal does not return the old name when called. It also does not
-        reset the ccache lookup behaviour when setting to ``None``.
-
-    Note:
-        The return value may not be thread safe.
-
-    Args:
-        name (Optional[bytes]): the name to set as the new thread specific
-            ccache name. Set to ``None`` to revert back to getting the ccache
-            from the config/environment settings.
-
-    Returns:
-        bytes: the old name that was previously set
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef const char *name_ptr = NULL
     if name is not None and len(name):
         name_ptr = &name[0]
@@ -317,29 +230,6 @@ def krb5_ccache_name(const unsigned char[:] name):
 
 def krb5_export_lucid_sec_context(SecurityContext context not None,
                                   OM_uint32 version):
-    """
-    krb5_export_lucid_sec_context(context, version)
-    Retuns a non-opaque version of the internal context info.
-
-    Gets information about the Kerberos security context passed in. Currently
-    only version 1 is known and supported by this library.
-
-    Note:
-        The context handle must not be used again by the caller after this
-        call.
-
-    Args:
-        context ((~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        version (int): the output structure version to export.  Currently
-            only 1 is supported.
-
-    Returns:
-        Krb5LucidContext: the non-opaque version context info
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     info = {
         1: Krb5LucidContextV1,
     }.get(version, Krb5LucidContext)()
@@ -358,26 +248,6 @@ def krb5_export_lucid_sec_context(SecurityContext context not None,
 
 
 def krb5_extract_authtime_from_sec_context(SecurityContext context not None):
-    """
-    krb5_extract_authtime_from_sec_context(context)
-    Get the auth time for the security context.
-
-    Gets the auth time for the established security context.
-
-    Note:
-        Heimdal can only get the authtime on the acceptor security context.
-        MIT is able to get the authtime on both initiators and acceptors.
-
-    Args:
-        context ((~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-
-    Returns:
-        int: the authtime
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     # In Heimdal, authtime is time_t which is either a 4 or 8 byte int.  By
     # passing in a uint64_t reference, there should be enough space for GSSAPI
     # to store the data in either situation. Coming back to Python it will be
@@ -398,26 +268,6 @@ def krb5_extract_authtime_from_sec_context(SecurityContext context not None):
 
 def krb5_extract_authz_data_from_sec_context(SecurityContext context not None,
                                              ad_type):
-    """
-    krb5_extract_authz_data_from_sec_context(context, ad_type)
-    Extracts Kerberos authorization data.
-
-    Extracts authorization data that may be stored within the context.
-
-    Note:
-        Only operates on acceptor contexts.
-
-    Args:
-        context ((~gssapi.raw.sec_contexts.SecurityContext): the current
-            security context
-        ad_type (int): the type of data to extract
-
-    Returns:
-        bytes: the raw authz data from the sec context
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     # GSS_C_EMPTY_BUFFER
     cdef gss_buffer_desc ad_data = gss_buffer_desc(0, NULL)
     cdef int ad_type_val = ad_type
@@ -441,31 +291,6 @@ def krb5_extract_authz_data_from_sec_context(SecurityContext context not None,
 
 def krb5_import_cred(Creds cred_handle not None, cache=None,
                      keytab_principal=None, keytab=None):
-    """
-    krb5_import_cred(cred_handle, cache=None, keytab_principal=None, \
-    keytab=None)
-    Import Krb5 credentials into GSSAPI credential.
-
-    Imports the krb5 credentials (either or both of the keytab and cache) into
-    the GSSAPI credential so it can be used within GSSAPI. The ccache is
-    copied by reference and thus shared, so if the credential is destroyed,
-    all users of cred_handle will fail.
-
-    Args:
-        cred_handle (Creds): the credential handle to import into
-        cache (int): the krb5_ccache address pointer, as an int, to import
-            from
-        keytab_principal (int): the krb5_principal address pointer, as an int,
-            of the credential to import
-        keytab (int): the krb5_keytab address pointer, as an int, of the
-            keytab to import
-
-    Returns:
-        None
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef void *cache_ptr = NULL
     if cache is not None and cache:
         cache_ptr = (cache)
@@ -491,27 +316,6 @@ def krb5_import_cred(Creds cred_handle not None, cache=None,
 
 
 def krb5_get_tkt_flags(SecurityContext context not None):
-    """
-    krb5_get_tkt_flags(context)
-    Return ticket flags for the kerberos ticket.
-
-    Return the ticket flags for the kerberos ticket received when
-    authenticating the initiator.
-
-    Note:
-        Heimdal can only get the tkt flags on the acceptor security context.
-        MIT is able to get the tkt flags on initators and acceptors.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the security
-            context
-
-    Returns:
-        int: the ticket flags for the received kerberos ticket
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef OM_uint32 maj_stat, min_stat
     cdef uint32_t ticket_flags = 0
 
@@ -527,28 +331,6 @@ def krb5_get_tkt_flags(SecurityContext context not None):
 
 def krb5_set_allowable_enctypes(Creds cred_handle not None,
                                 ktypes):
-    """
-    krb5_set_allowable_enctypes(cred_handle, ktypes)
-    Limits the keys that can be exported.
-
-    Called by a context initiator after acquiring the creds but before calling
-    :meth:`~gssapi.raw.sec_contexts.init_sec_context` to restrict the set of
-    enctypes which will be negotiated during context establisment to those in
-    the provided list.
-
-    Warning:
-        The cred_handle should not be ``GSS_C_NO_CREDENTIAL``.
-
-    Args:
-        cred_hande (Creds): the credential handle
-        ktypes (List[int]): list of enctypes allowed
-
-    Returns:
-        None
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef OM_uint32 maj_stat, min_stat
 
     # This shouldn't ever happen but it's here to satisfy compiler warnings
diff --git a/gssapi/raw/ext_password.pyi b/gssapi/raw/ext_password.pyi
new file mode 100644
index 00000000..c5e101c2
--- /dev/null
+++ b/gssapi/raw/ext_password.pyi
@@ -0,0 +1,41 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import AcquireCredResult
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+
+
+def acquire_cred_with_password(
+    name: "Name",
+    password: bytes,
+    lifetime: t.Optional[int] = None,
+    mechs: t.Optional[t.Iterable["OID"]] = None,
+    usage: str = 'initiate',
+) -> "AcquireCredResult":
+    """Acquire credentials through provided password.
+
+    This function is originally from Solaris and is not documented by either
+    MIT or Heimdal.
+
+    In general, it functions similarly to
+    :func:`~gssapi.raw.creds.acquire_cred`.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to acquire credentials for
+        password (bytes): the password used to acquire credentialss with
+        lifetime (int): the lifetime for the credentials (or None for
+            indefinite)
+        mechs (~gssapi.raw.types.MechType): the desired mechanisms for which
+            the credentials should work (or None for the default set)
+        usage (str): usage type for credentials.  Possible values:
+            'initiate' (default), 'accept', 'both' (failsafe).
+
+    Returns:
+        AcquireCredResult: the resulting credentials, the actual mechanisms
+        with which they may be used, and their actual lifetime (or None for
+        indefinite or not supported)
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_password.pyx b/gssapi/raw/ext_password.pyx
index 4f1ed81e..33b2bae1 100644
--- a/gssapi/raw/ext_password.pyx
+++ b/gssapi/raw/ext_password.pyx
@@ -29,35 +29,6 @@ cdef extern from "python_gssapi_ext.h":
 
 def acquire_cred_with_password(Name name not None, password not None,
                                lifetime=None, mechs=None, usage="initiate"):
-    """
-    acquire_cred_with_password(name, password, lifetime=None, mechs=None, \
-usage="initiate")
-    Acquire credentials through provided password.
-
-    This function is originally from Solaris and is not documented by either
-    MIT or Heimdal.
-
-    In general, it functions similarly to :func:`acquire_cred`.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to acquire credentials for
-        password (bytes): the password used to acquire credentialss with
-        lifetime (int): the lifetime for the credentials (or None for
-            indefinite)
-        mechs (~gssapi.MechType): the desired mechanisms for which the
-            credentials should work (or None for the default set)
-        usage (str): usage type for credentials.  Possible values:
-            'initiate' (default), 'accept', 'both' (failsafe).
-
-    Returns:
-        AcquireCredResult: the resulting credentials, the actual mechanisms
-        with which they may be used, and their actual lifetime (or None for
-        indefinite or not supported)
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc password_buffer = gss_buffer_desc(len(password),
                                                            password)
 
diff --git a/gssapi/raw/ext_password_add.pyi b/gssapi/raw/ext_password_add.pyi
new file mode 100644
index 00000000..32b270b3
--- /dev/null
+++ b/gssapi/raw/ext_password_add.pyi
@@ -0,0 +1,48 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.named_tuples import AddCredResult
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+
+
+def add_cred_with_password(
+    input_cred: "Creds",
+    name: "Name",
+    mech: "OID",
+    password: bytes,
+    usage: str = 'initiate',
+    init_lifetime: t.Optional[int] = None,
+    accept_lifetime: t.Optional[int] = None,
+) -> "AddCredResult":
+    """Add a credential-element to a credential using provided password.
+
+    This function is originally from Solaris and is not documented by either
+    MIT or Heimdal.
+
+    In general, it functions similarly to :func:`~gssapi.raw.creds.add_cred`.
+
+    Args:
+        input_cred (~gssapi.raw.creds.Creds): the credentials to add to
+        name (~gssapi.raw.names.Name): the name to acquire credentials for
+        mech (~gssapi.raw.types.MechType): the desired mechanism.  Note that
+            this is both singular and required
+        password (bytes): the password used to acquire credentialss with
+        usage (str): the usage type for the credentials: may be
+            'initiate', 'accept', or 'both'
+        init_lifetime (int): the lifetime for the credentials to remain valid
+            when using them to initiate security contexts (or None for
+            indefinite)
+        accept_lifetime (int): the lifetime for the credentials to remain
+            valid when using them to accept security contexts (or None for
+            indefinite)
+
+    Returns:
+        AddCredResult: the actual mechanisms with which the credentials may be
+        used, the actual initiator TTL, and the actual acceptor TTL (the TTLs
+        may be None for indefinite or not supported)
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_password_add.pyx b/gssapi/raw/ext_password_add.pyx
index 5a142e76..9db07889 100644
--- a/gssapi/raw/ext_password_add.pyx
+++ b/gssapi/raw/ext_password_add.pyx
@@ -35,41 +35,6 @@ def add_cred_with_password(Creds input_cred not None, Name name not None,
                            OID mech not None, password not None,
                            usage="initiate", init_lifetime=None,
                            accept_lifetime=None):
-
-    """
-    add_cred_with_password(input_cred, name, mech, password, \
-usage='initiate', init_lifetime=None, accept_lifetime=None)
-    Add a credential-element to a credential using provided password.
-
-    This function is originally from Solaris and is not documented by either
-    MIT or Heimdal.
-
-    In general, it functions similarly to :func:`add_cred`.
-
-    Args:
-        input_cred (Creds): the credentials to add to
-        name (~gssapi.raw.names.Name): the name to acquire credentials for
-        mech (~gssapi.MechType): the desired mechanism.  Note that this is both
-            singular and required
-        password (bytes): the password used to acquire credentialss with
-        usage (str): the usage type for the credentials: may be
-            'initiate', 'accept', or 'both'
-        init_lifetime (int): the lifetime for the credentials to remain valid
-            when using them to initiate security contexts (or None for
-            indefinite)
-        accept_lifetime (int): the lifetime for the credentials to remain
-            valid when using them to accept security contexts (or None for
-            indefinite)
-
-    Returns:
-        AddCredResult: the actual mechanisms with which the credentials may be
-        used, the actual initiator TTL, and the actual acceptor TTL (the TTLs
-        may be None for indefinite or not supported)
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc password_buffer = gss_buffer_desc(len(password),
                                                            password)
 
diff --git a/gssapi/raw/ext_rfc4178.pyi b/gssapi/raw/ext_rfc4178.pyi
new file mode 100644
index 00000000..6826bc1e
--- /dev/null
+++ b/gssapi/raw/ext_rfc4178.pyi
@@ -0,0 +1,27 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.oids import OID
+
+
+def set_neg_mechs(
+    cred_handle: "Creds",
+    mech_set: t.Iterable["OID"],
+) -> None:
+    """
+    Specify the set of security mechanisms that may be negotiated with
+    the credential identified by cred_handle.
+    If more than one mechanism is specified in mech_set, the order in
+    which those mechanisms are specified implies a relative preference.
+
+    Args:
+        cred_handle (Creds): credentials to set negotiable mechanisms for
+        mech_set (~gssapi.raw.types.MechType): negotiable mechanisms to be set
+
+    Returns:
+        None
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_rfc4178.pyx b/gssapi/raw/ext_rfc4178.pyx
index 407d1f3d..44db2f8f 100644
--- a/gssapi/raw/ext_rfc4178.pyx
+++ b/gssapi/raw/ext_rfc4178.pyx
@@ -14,25 +14,6 @@ cdef extern from "python_gssapi_ext.h":
 
 
 def set_neg_mechs(Creds cred_handle not None, mech_set not None):
-    """
-    set_neg_mechs(cred_handle not None, mech_set not None)
-
-    Specify the set of security mechanisms that may be negotiated with
-    the credential identified by cred_handle.
-    If more than one mechanism is specified in mech_set, the order in
-    which those mechanisms are specified implies a relative preference.
-
-    Args:
-        cred_handle (Creds): credentials to set negotiable mechanisms for
-        mech_set (~gssapi.MechType): negotiable mechanisms to be set
-
-    Returns:
-        None
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_OID_set negotiable_mechs = c_get_mech_oid_set(mech_set)
 
     cdef OM_uint32 maj_stat, min_stat
diff --git a/gssapi/raw/ext_rfc5587.pyi b/gssapi/raw/ext_rfc5587.pyi
new file mode 100644
index 00000000..b1a6ee31
--- /dev/null
+++ b/gssapi/raw/ext_rfc5587.pyi
@@ -0,0 +1,63 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import InquireAttrsResult, DisplayAttrResult
+    from gssapi.raw.oids import OID
+
+
+def indicate_mechs_by_attrs(
+    desired_mech_attrs: t.Optional[t.Iterable["OID"]] = None,
+    except_mech_attrs: t.Optional[t.Iterable["OID"]] = None,
+    critical_mech_attrs: t.Optional[t.Iterable["OID"]] = None,
+) -> t.Set["OID"]:
+    """Get a set of mechanisms that have the specified attributes.
+
+    Args:
+        desired_mech_attrs (~gssapi.OID): Attributes that the output mechs MUST
+            offer
+        except_mech_attrs (~gssapi.OID): Attributes that the output mechs MUST
+            NOT offer
+        critical_mech_attrs (~gssapi.OID): Attributes that the output mechs
+            MUST understand and offer
+
+    Returns:
+        ~gssapi.MechType: a set of mechs which satisfy the given criteria
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def inquire_attrs_for_mech(
+    mech: "OID",
+) -> "InquireAttrsResult":
+    """Gets the set of attrs supported and known by a mechanism.
+
+    Args:
+        mech (~gssapi.raw.types.MechType): Mechanism to inquire about
+
+    Returns:
+        InquireAttrsResult: the results of inquiry; a mech's attributes and
+        known attributes
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def display_mech_attr(
+    attr: "OID",
+) -> "DisplayAttrResult":
+    """Returns information about attributes in human readable form.
+
+    Args:
+        attr (~gssapi.OID): Mechanism attribute to retrive names and
+            descriptions of
+
+    Returns:
+        DisplayAttrResult: the results of displaying the attribute; mech name,
+        short description, and long description.
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_rfc5587.pyx b/gssapi/raw/ext_rfc5587.pyx
index ca669023..fbedf6ed 100644
--- a/gssapi/raw/ext_rfc5587.pyx
+++ b/gssapi/raw/ext_rfc5587.pyx
@@ -32,25 +32,6 @@ cdef extern from "python_gssapi_ext.h":
 
 def indicate_mechs_by_attrs(desired_mech_attrs=None, except_mech_attrs=None,
                             critical_mech_attrs=None):
-    """
-    indicate_mechs_by_attrs(desired_mech_attrs=None, except_mech_attrs=None,\
-    critical_mech_attrs=None)
-    Get a set of mechanisms that have the specified attributes.
-
-    Args:
-        desired_mech_attrs (~gssapi.OID): Attributes that the output mechs MUST
-            offer
-        except_mech_attrs (~gssapi.OID): Attributes that the output mechs MUST
-            NOT offer
-        critical_mech_attrs (~gssapi.OID): Attributes that the output mechs
-            MUST understand and offer
-
-    Returns:
-        ~gssapi.MechType: a set of mechs which satisfy the given criteria
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef OM_uint32 maj_stat, min_stat
     cdef gss_OID_set desired_attrs = GSS_C_NO_OID_SET
     cdef gss_OID_set except_attrs = GSS_C_NO_OID_SET
@@ -78,20 +59,6 @@ def indicate_mechs_by_attrs(desired_mech_attrs=None, except_mech_attrs=None,
 
 
 def inquire_attrs_for_mech(OID mech):
-    """
-    inquire_attrs_for_mech(mech)
-    Gets the set of attrs supported and known by a mechanism.
-
-    Args:
-        mech (~gssapi.MechType): Mechanism to inquire about
-
-    Returns:
-        InquireAttrsResult: the results of inquiry; a mech's attributes and
-        known attributes
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef OM_uint32 maj_stat, min_stat
     cdef gss_OID m = GSS_C_NO_OID
     cdef gss_OID_set mech_attrs = GSS_C_NO_OID_SET
@@ -112,21 +79,6 @@ def inquire_attrs_for_mech(OID mech):
 
 
 def display_mech_attr(OID attr):
-    """
-    display_mech_attrs(attr)
-    Returns information about attributes in human readable form.
-
-    Args:
-        attr (~gssapi.OID): Mechanism attribute to retrive names and
-            descriptions of
-
-    Returns:
-        DisplayAttrResult: the results of displaying the attribute; mech name,
-        short description, and long description.
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
     cdef OM_uint32 maj_stat, min_stat
     cdef gss_OID a = GSS_C_NO_OID
     cdef gss_buffer_desc name
diff --git a/gssapi/raw/ext_rfc5588.pyi b/gssapi/raw/ext_rfc5588.pyi
new file mode 100644
index 00000000..320b74aa
--- /dev/null
+++ b/gssapi/raw/ext_rfc5588.pyi
@@ -0,0 +1,42 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.named_tuples import StoreCredResult
+    from gssapi.raw.oids import OID
+
+
+def store_cred(
+    creds: "Creds",
+    usage: str = 'both',
+    mech: t.Optional["OID"] = None,
+    overwrite: bool = False,
+    set_default: bool = False,
+) -> "StoreCredResult":
+    """Store credentials into the default store.
+
+    This method stores the given credentials into the default store.
+    They may then be retrieved later using
+    :func:`~gssapi.raw.creds.acquire_cred`.
+
+    Args:
+        creds (Creds): the credentials to store
+        usage (str): the usage to store the credentials with -- either
+            'both', 'initiate', or 'accept'
+        mech (~gssapi.OID): the mechansim to associate with the stored
+            credentials
+        overwrite (bool): whether or not to overwrite existing credentials
+            stored with the same name, etc
+        set_default (bool): whether or not to set these credentials as
+            the default credentials for the given store.
+
+    Returns:
+        StoreCredResult: the results of the credential storing operation
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+        ~gssapi.exceptions.ExpiredCredentialsError
+        ~gssapi.exceptions.MissingCredentialsError
+        ~gssapi.exceptions.OperationUnavailableError
+        ~gssapi.exceptions.DuplicateCredentialsElementError
+    """
diff --git a/gssapi/raw/ext_rfc5588.pyx b/gssapi/raw/ext_rfc5588.pyx
index dbf1fcd0..95b924f5 100644
--- a/gssapi/raw/ext_rfc5588.pyx
+++ b/gssapi/raw/ext_rfc5588.pyx
@@ -24,35 +24,6 @@ cdef extern from "python_gssapi.h":
 
 def store_cred(Creds creds not None, usage='both', OID mech=None,
                bint overwrite=False, bint set_default=False):
-    """
-    store_cred(creds, usage='both', mech=None, overwrite=False, \
-set_default=False)
-    Store credentials into the default store.
-
-    This method stores the given credentials into the default store.
-    They may then be retrieved later using :func:`acquire_cred`.
-
-    Args:
-        creds (Creds): the credentials to store
-        usage (str): the usage to store the credentials with -- either
-            'both', 'initiate', or 'accept'
-        mech (~gssapi.OID): the mechansim to associate with the stored
-            credentials
-        overwrite (bool): whether or not to overwrite existing credentials
-            stored with the same name, etc
-        set_default (bool): whether or not to set these credentials as
-            the default credentials for the given store.
-
-    Returns:
-        StoreCredResult: the results of the credential storing operation
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-        ~gssapi.exceptions.ExpiredCredentialsError
-        ~gssapi.exceptions.MissingCredentialsError
-        ~gssapi.exceptions.OperationUnavailableError
-        ~gssapi.exceptions.DuplicateCredentialsElementError
-    """
     cdef gss_OID desired_mech
     if mech is not None:
         desired_mech = &mech.raw_oid
diff --git a/gssapi/raw/ext_rfc5801.pyi b/gssapi/raw/ext_rfc5801.pyi
new file mode 100644
index 00000000..55a7d06d
--- /dev/null
+++ b/gssapi/raw/ext_rfc5801.pyi
@@ -0,0 +1,39 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import InquireSASLNameResult
+    from gssapi.raw.oids import OID
+
+
+def inquire_saslname_for_mech(
+    mech: "OID",
+) -> "InquireSASLNameResult":
+    """Gets information about a specified mech, including the SASL name,
+    the mech name, and the mech description.
+
+    Args:
+        mech (~gssapi.OID): Mechanism to inquire about
+
+    Returns:
+        InquireSASLNameResult: the results of inquiry; a mech's SASL name,
+        name, and description.
+
+    Raises:
+        ~gssapi.exceptions.GSSError: an unknown failure occurred
+    """
+
+
+def inquire_mech_for_saslname(
+    sasl_name: bytes,
+) -> "OID":
+    """Gets the OID for the mech specified by SASL name.
+
+    Args:
+        sasl_name (bytes): SASL name of the mechanism
+
+    Returns:
+        ~gssapi.OID: the mechanism with corresponding SASL name.
+
+    Raises:
+        ~gssapi.exceptions.GSSError: An unknown failure occurred
+    """
diff --git a/gssapi/raw/ext_rfc5801.pyx b/gssapi/raw/ext_rfc5801.pyx
index 89da2ae1..4d9f5837 100644
--- a/gssapi/raw/ext_rfc5801.pyx
+++ b/gssapi/raw/ext_rfc5801.pyx
@@ -22,21 +22,6 @@ cdef extern from "python_gssapi_ext.h":
 
 
 def inquire_saslname_for_mech(OID mech not None):
-    """
-    inquire_saslname_for_mech(mech)
-    Gets information about a specified mech, including the SASL name,
-    the mech name, and the mech description.
-
-    Args:
-        mech (~gssapi.OID): Mechanism to inquire about
-
-    Returns:
-        InquireSASLNameResult: the results of inquiry; a mech's SASL name,
-        name, and description.
-
-    Raises:
-        ~gssapi.exceptions.GSSError: an unknown failure occurred
-    """
     cdef OM_uint32 maj_stat, min_stat
     cdef gss_buffer_desc sasl_mech_name
     cdef gss_buffer_desc mech_name
@@ -64,19 +49,6 @@ def inquire_saslname_for_mech(OID mech not None):
 
 
 def inquire_mech_for_saslname(bytes sasl_name not None):
-    """
-    inquire_mech_for_saslname(sasl_name)
-    Gets the OID for the mech specified by SASL name.
-
-    Args:
-        sasl_name (bytes): SASL name of the mechanism
-
-    Returns:
-        ~gssapi.OID: the mechanism with corresponding SASL name.
-
-    Raises:
-        ~gssapi.exceptions.GSSError: An unknown failure occurred
-    """
     cdef OM_uint32 maj_stat, min_stat
     cdef gss_buffer_desc sn
     cdef gss_OID m
diff --git a/gssapi/raw/ext_rfc6680.pyi b/gssapi/raw/ext_rfc6680.pyi
new file mode 100644
index 00000000..862e6163
--- /dev/null
+++ b/gssapi/raw/ext_rfc6680.pyi
@@ -0,0 +1,169 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import (
+        GetNameAttributeResult,
+        InquireNameResult,
+    )
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+
+
+def display_name_ext(
+    name: "Name",
+    name_type: "OID",
+) -> bytes:
+    """Display the given Name using the given name type.
+
+    This method attempts to display the given Name using the syntax of
+    the given name type.  If this is not possible, an appropriate error
+    will be raised.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to display
+        name_type (~gssapi.OID): the name type (see NameType) to use to
+            display the given name
+
+    Returns:
+        bytes: the displayed name
+
+    Raises:
+        ~gssapi.exceptions.OperationUnavailableError: the given name could not
+            be displayed using the given name type
+    """
+
+
+def inquire_name(
+    name: "Name",
+    mech_name: bool = True,
+    attrs: bool = True,
+) -> "InquireNameResult":
+    """Get information about a Name.
+
+    This method retrives information about the given name, including
+    the set of attribute names for the given name, as well as whether or
+    not the name is a mechanism name.  Additionally, if the given name is
+    a mechanism name, the associated mechansim is returned as well.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name about which to inquire
+        mech_name (bool): whether or not to retrieve if this name
+            is a mech_name (and the associate mechanism)
+        attrs (bool): whether or not to retrieve the attribute name list
+
+    Returns:
+        InquireNameResult: the set of attribute names for the given name,
+        whether or not the name is a Mechanism Name, and potentially
+        the associated mechanism if it is a Mechanism Name
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def set_name_attribute(
+    name: "Name",
+    attr: bytes,
+    value: t.Iterable[bytes],
+    complete: bool = False,
+) -> None:
+    """Set the value(s) of a name attribute.
+
+    This method sets the value(s) of the given attribute on the given name.
+
+    Note that this functionality more closely matches the pseudo-API
+    presented in RFC 6680, not the C API (which uses multiple calls to
+    add multiple values).  However, multiple calls to this method will
+    continue adding values, so :func:`delete_name_attribute` must be
+    used in between calls to "clear" the values.
+
+    Args:
+        name (~gssapi.raw.names.Name): the Name on which to set the attribute
+        attr (bytes): the name of the attribute
+        value (list): a list of bytes objects to use as the value(s)
+        complete (bool): whether or not to mark this attribute's value
+            set as being "complete"
+
+    Raises:
+        ~gssapi.exceptions.OperationUnavailableError: the given attribute name
+            is unknown or could not be set
+    """
+
+
+def get_name_attribute(
+    name: "Name",
+    attr: bytes,
+    more: t.Optional[int] = None,
+) -> "GetNameAttributeResult":
+    """Get the value(s) of a name attribute.
+
+    This method retrieves the value(s) of the given attribute
+    for the given Name.
+
+    Note that this functionality matches pseudo-API presented
+    in RFC 6680, not the C API (which uses a state variable and
+    multiple calls to retrieve multiple values).
+
+    Args:
+        name (~gssapi.raw.names.Name): the Name from which to get the attribute
+        attr (bytes): the name of the attribute
+
+    Returns:
+        GetNameAttributeResult: the raw version of the value(s),
+        the human-readable version of the value(s), whether
+        or not the attribute was authenticated, and whether or
+        not the attribute's value set was marked as complete
+
+    Raises:
+        ~gssapi.exceptions.OperationUnavailableError: the given attribute is
+            unknown or unset
+    """
+
+
+def delete_name_attribute(
+    name: "Name",
+    attr: bytes,
+) -> None:
+    """Remove an attribute from a name.
+
+    This method removes an attribute from a Name.  This method may be
+    used before :func:`set_name_attribute` clear the values of an attribute
+    before setting a new value (making the latter method work like a 'set'
+    operation instead of an 'add' operation).
+
+    Note that the removal of certain attributes may not be allowed.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to remove the attribute from
+        attr (bytes): the name of the attribute
+
+    Raises:
+        ~gssapi.exceptions.OperationUnavailableError
+        ~gssapi.exceptions.UnauthorizedError
+    """
+
+
+def export_name_composite(
+    name: "Name",
+) -> bytes:
+    """Export a name, preserving attribute information.
+
+    This method functions similarly to :func:`~gssapi.raw.names.export_name`,
+    except that it preserves attribute information.  The resulting bytes may be
+    imported using :func:`~gssapi.raw.names.import_name` with the
+    :attr:`~gssapi.raw.types.NameType.composite_export` name type.
+
+    Note:
+        Some versions of MIT Kerberos require you to either canonicalize a name
+        once it has been imported with composite-export name type, or to import
+        using the normal export name type.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to export
+
+    Returns:
+        bytes: the exported composite name
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_rfc6680.pyx b/gssapi/raw/ext_rfc6680.pyx
index 94f52708..70adcce3 100644
--- a/gssapi/raw/ext_rfc6680.pyx
+++ b/gssapi/raw/ext_rfc6680.pyx
@@ -37,27 +37,6 @@ cdef extern from "python_gssapi_ext.h":
 
 
 def display_name_ext(Name name not None, OID name_type not None):
-    """
-    display_name_ext(name, name_type)
-    Display the given Name using the given name type.
-
-    This method attempts to display the given Name using the syntax of
-    the given name type.  If this is not possible, an appropriate error
-    will be raised.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to display
-        name_type (~gssapi.OID): the name type (see NameType) to use to
-            display the given name
-
-    Returns:
-        bytes: the displayed name
-
-    Raises:
-        ~gssapi.exceptions.OperationUnavailableError: the given name could not
-            be displayed using the given name type
-    """
-
     # GSS_C_EMPTY_BUFFER
     cdef gss_buffer_desc output_name = gss_buffer_desc(0, NULL)
 
@@ -75,30 +54,6 @@ def display_name_ext(Name name not None, OID name_type not None):
 
 
 def inquire_name(Name name not None, mech_name=True, attrs=True):
-    """
-    inquire_name(name, mech_name=True, attrs=True)
-    Get information about a Name.
-
-    This method retrives information about the given name, including
-    the set of attribute names for the given name, as well as whether or
-    not the name is a mechanism name.  Additionally, if the given name is
-    a mechanism name, the associated mechansim is returned as well.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name about which to inquire
-        mech_name (bool): whether or not to retrieve if this name
-            is a mech_name (and the associate mechanism)
-        attrs (bool): whether or not to retrieve the attribute name list
-
-    Returns:
-        InquireNameResult: the set of attribute names for the given name,
-            whether or not the name is a Mechanism Name, and potentially
-            the associated mechanism if it is a Mechanism Name
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef int *name_is_mn_ptr = NULL
     cdef gss_OID *mn_mech_ptr = NULL
     cdef gss_buffer_set_t *attr_names_ptr = NULL
@@ -143,30 +98,6 @@ def inquire_name(Name name not None, mech_name=True, attrs=True):
 
 def set_name_attribute(Name name not None, attr not None, value not None,
                        bint complete=False):
-    """
-    set_name_attribute(name, attr, value, complete=False)
-    Set the value(s) of a name attribute.
-
-    This method sets the value(s) of the given attribute on the given name.
-
-    Note that this functionality more closely matches the pseudo-API
-    presented in RFC 6680, not the C API (which uses multiple calls to
-    add multiple values).  However, multiple calls to this method will
-    continue adding values, so :func:`delete_name_attribute` must be
-    used in between calls to "clear" the values.
-
-    Args:
-        name (~gssapi.raw.names.Name): the Name on which to set the attribute
-        attr (bytes): the name of the attribute
-        value (list): a list of bytes objects to use as the value(s)
-        complete (bool): whether or not to mark this attribute's value
-            set as being "complete"
-
-    Raises:
-        ~gssapi.exceptions.OperationUnavailableError: the given attribute name
-            is unknown or could not be set
-    """
-
     cdef gss_buffer_desc attr_buff = gss_buffer_desc(len(attr), attr)
     cdef gss_buffer_desc val_buff
 
@@ -189,31 +120,6 @@ def set_name_attribute(Name name not None, attr not None, value not None,
 
 
 def get_name_attribute(Name name not None, attr not None, more=None):
-    """
-    get_name_attribute(name, attr, more=None)
-    Get the value(s) of a name attribute.
-
-    This method retrieves the value(s) of the given attribute
-    for the given Name.
-
-    Note that this functionality matches pseudo-API presented
-    in RFC 6680, not the C API (which uses a state variable and
-    multiple calls to retrieve multiple values).
-
-    Args:
-        name (~gssapi.raw.names.Name): the Name from which to get the attribute
-        attr (bytes): the name of the attribute
-
-    Returns:
-        GetNameAttributeResult: the raw version of the value(s),
-        the human-readable version of the value(s), whether
-        or not the attribute was authenticated, and whether or
-        not the attribute's value set was marked as complete
-
-    Raises:
-        ~gssapi.exceptions.OperationUnavailableError: the given attribute is
-            unknown or unset
-    """
     cdef gss_buffer_desc attr_buff = gss_buffer_desc(len(attr), attr)
 
     cdef gss_buffer_desc val_buff = gss_buffer_desc(0, NULL)
@@ -249,26 +155,6 @@ def get_name_attribute(Name name not None, attr not None, more=None):
 
 
 def delete_name_attribute(Name name not None, attr not None):
-    """
-    delete_name_attribute(name, attr)
-    Remove an attribute from a name.
-
-    This method removes an attribute from a Name.  This method may be
-    used before :func:`set_name_attribute` clear the values of an attribute
-    before setting a new value (making the latter method work like a 'set'
-    operation instead of an 'add' operation).
-
-    Note that the removal of certain attributes may not be allowed.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to remove the attribute from
-        attr (bytes): the name of the attribute
-
-    Raises:
-        ~gssapi.exceptions.OperationUnavailableError
-        ~gssapi.exceptions.UnauthorizedError
-    """
-
     cdef gss_buffer_desc attr_buff = gss_buffer_desc(len(attr), attr)
 
     cdef OM_uint32 maj_stat, min_stat
@@ -281,30 +167,6 @@ def delete_name_attribute(Name name not None, attr not None):
 
 
 def export_name_composite(Name name not None):
-    """
-    export_name_composite(name)
-    Export a name, preserving attribute information.
-
-    This method functions similarly to :func:`export_name`, except that
-    it preserves attribute information.  The resulting bytes may be imported
-    using :func:`import_name` with the :attr:`NameType.composite_export`
-    name type.
-
-    Note:
-        Some versions of MIT Kerberos require you to either canonicalize a name
-        once it has been imported with composite-export name type, or to import
-        using the normal export name type.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to export
-
-    Returns:
-        bytes: the exported composite name
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc res = gss_buffer_desc(0, NULL)
 
     cdef OM_uint32 maj_stat, min_stat
diff --git a/gssapi/raw/ext_rfc6680_comp_oid.pyi b/gssapi/raw/ext_rfc6680_comp_oid.pyi
new file mode 100644
index 00000000..e69de29b
diff --git a/gssapi/raw/ext_s4u.pyi b/gssapi/raw/ext_s4u.pyi
new file mode 100644
index 00000000..85756b9d
--- /dev/null
+++ b/gssapi/raw/ext_s4u.pyi
@@ -0,0 +1,86 @@
+"""Service4User Extension"""
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.named_tuples import AcquireCredResult, AddCredResult
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+
+
+def acquire_cred_impersonate_name(
+    impersonator_cred: "Creds",
+    name: "Name",
+    lifetime: t.Optional[int] = None,
+    mechs: t.Optional[t.Iterable["OID"]] = None,
+    usage: str = 'initiate',
+) -> "AcquireCredResult":
+    """Acquire credentials by impersonating another name.
+
+    This method is one of the ways to use S4U2Self.  It acquires credentials
+    by impersonating another name using a set of proxy credentials.  The
+    impersonator credentials must have a usage of 'both' or 'initiate'.
+
+    Args:
+        impersonator_cred (~gssapi.raw.creds.Creds): the credentials with
+            permissions to impersonate the target name
+        name (~gssapi.raw.names.Name): the name to impersonate
+        lifetime (int): the lifetime for the credentials (or None for
+            indefinite)
+        mechs (~gssapi.raw.types.MechType): the desired mechanisms for which
+            the credentials should work (or None for the default set)
+        usage (str): the usage type for the credentials: may be
+            'initiate', 'accept', or 'both'
+
+    Returns:
+        AcquireCredResult: the resulting credentials, the actual mechanisms
+        with which they may be used, and their actual lifetime (or None for
+        indefinite or not support)
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def add_cred_impersonate_name(
+    input_cred: "Creds",
+    impersonator_cred: "Creds",
+    name: "Name",
+    mech: "OID",
+    usage: str = 'initiate',
+    init_lifetime: t.Optional[int] = None,
+    accept_lifetime: t.Optional[int] = None,
+) -> "AddCredResult":
+    """Add a credentials element to a credential by impersonating another name.
+
+    This method is one of the ways to use S4U2Self.  It adds credentials
+    to the input credentials by impersonating another name using a set of
+    proxy credentials.  The impersonator credentials must have a usage of
+    'both' or 'initiate'.
+
+    Args:
+        input_cred (~gssapi.raw.creds.Creds): the set of credentials to which
+            to add the new credentials
+        impersonator_cred (~gssapi.raw.creds.Creds): the credentials with
+            permissions to impersonate the target name
+        name (~gssapi.raw.names.Name): the name to impersonate
+        mech (~gssapi.raw.types.MechType): the desired mechanism. Note that
+            this is both
+            singular and required, unlike acquireCredImpersonateName
+        usage (str): the usage type for the credentials: may be
+            'initiate', 'accept', or 'both'
+        init_lifetime (int): the lifetime for the credentials to remain
+            valid when using them to initiate security contexts (or None for
+            indefinite)
+        accept_lifetime (int): the lifetime for the credentials to remain
+            valid when using them to accept security contexts (or None for
+            indefinite)
+
+    Returns:
+        AddCredResult: the actual mechanisms with which the credentials may be
+        used, the actual initiator TTL, and the actual acceptor TTL (the TTLs
+        may be None for indefinite or not supported)
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_s4u.pyx b/gssapi/raw/ext_s4u.pyx
index 177b02e3..b123e165 100644
--- a/gssapi/raw/ext_s4u.pyx
+++ b/gssapi/raw/ext_s4u.pyx
@@ -1,4 +1,3 @@
-"""Service4User Extension"""
 GSSAPI="BASE"  # This ensures that a full module is generated by Cython
 
 from gssapi.raw.cython_types cimport *
@@ -41,35 +40,6 @@ cdef extern from "python_gssapi_ext.h":
 def acquire_cred_impersonate_name(Creds impersonator_cred not None,
                                   Name name not None, lifetime=None,
                                   mechs=None, usage='initiate'):
-    """
-    acquire_cred_impersonate_name(impersonator_cred, name, lifetime=None, \
-mechs=None, usage='initiate')
-    Acquire credentials by impersonating another name.
-
-    This method is one of the ways to use S4U2Self.  It acquires credentials
-    by impersonating another name using a set of proxy credentials.  The
-    impersonator credentials must have a usage of 'both' or 'initiate'.
-
-    Args:
-        impersonator_cred (Cred): the credentials with permissions to
-            impersonate the target name
-        name (~gssapi.raw.names.Name): the name to impersonate
-        lifetime (int): the lifetime for the credentials (or None for
-            indefinite)
-        mechs (~gssapi.MechType): the desired mechanisms for which the
-            credentials should work (or None for the default set)
-        usage (str): the usage type for the credentials: may be
-            'initiate', 'accept', or 'both'
-
-    Returns:
-        AcquireCredResult: the resulting credentials, the actual mechanisms
-        with which they may be used, and their actual lifetime (or None for
-        indefinite or not support)
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_OID_set desired_mechs
     if mechs is not None:
         desired_mechs = c_get_mech_oid_set(mechs)
@@ -120,42 +90,6 @@ def add_cred_impersonate_name(Creds input_cred,
                               Name name not None, OID mech not None,
                               usage='initiate', init_lifetime=None,
                               accept_lifetime=None):
-    """
-    add_cred_impersonate_name(input_cred, impersonator_cred, name, mech, \
-usage='initiate', init_lifetime=None, accept_lifetime=None)
-    Add a credentials element to a credential by impersonating another name.
-
-    This method is one of the ways to use S4U2Self.  It adds credentials
-    to the input credentials by impersonating another name using a set of
-    proxy credentials.  The impersonator credentials must have a usage of
-    'both' or 'initiate'.
-
-    Args:
-        input_cred (Cred): the set of credentials to which to add the new
-            credentials
-        impersonator_cred (Cred): the credentials with permissions to
-            impersonate the target name
-        name (~gssapi.raw.names.Name): the name to impersonate
-        mech (~gssapi.MechType): the desired mechanism.  Note that this is both
-            singular and required, unlike acquireCredImpersonateName
-        usage (str): the usage type for the credentials: may be
-            'initiate', 'accept', or 'both'
-        init_lifetime (int): the lifetime for the credentials to remain
-            valid when using them to initiate security contexts (or None for
-            indefinite)
-        accept_lifetime (int): the lifetime for the credentials to remain
-            valid when using them to accept security contexts (or None for
-            indefinite)
-
-    Returns:
-        AddCredResult: the actual mechanisms with which the credentials may be
-        used, the actual initiator TTL, and the actual acceptor TTL (the TTLs
-        may be None for indefinite or not supported)
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef OM_uint32 input_initiator_ttl = c_py_ttl_to_c(init_lifetime)
     cdef OM_uint32 input_acceptor_ttl = c_py_ttl_to_c(accept_lifetime)
     cdef gss_name_t c_name = name.raw_name
diff --git a/gssapi/raw/ext_set_cred_opt.pyi b/gssapi/raw/ext_set_cred_opt.pyi
new file mode 100644
index 00000000..eeb0e123
--- /dev/null
+++ b/gssapi/raw/ext_set_cred_opt.pyi
@@ -0,0 +1,50 @@
+"""
+gss_set_cred_option
+
+Provides a way to set options on a credential based on the OID specified. A
+common use case is to set the GSS_KRB5_CRED_NO_CI_FLAGS_X on a Kerberos
+credential. This is used for interoperability with Microsoft's SSPI.
+
+Note this function is commonly lumped with the GGF extensions but they are not
+part of the GGF IETF draft so it's separated into it's own file.
+
+Closest draft IETF document for the gss_set_cred_option can be found at
+https://tools.ietf.org/html/draft-williams-kitten-channel-bound-flag-01
+"""
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.oids import OID
+
+
+def set_cred_option(
+    desired_aspect: "OID",
+    creds: t.Optional["Creds"] = None,
+    value: t.Optional[bytes] = None,
+) -> "Creds":
+    """
+    This method is used to set options of a :class:`~gssapi.raw.creds.Creds`
+    object based on an OID key. The options that can be set depends on the mech
+    the credentials were created with.
+
+    An example of how this can be used would be to set the
+    GSS_KRB5_CRED_NO_CI_FLAGS_X on a Kerberos credential. The OID string for
+    this flag is '1.2.752.43.13.29' and it requires no value to be set. This
+    must be set before the SecurityContext was initialised with the
+    credentials.
+
+    Args:
+        desired_aspect (~gssapi.raw.oids.OID): the desired aspect of the
+            Credential to set.
+        cred_handle (~gssapi.raw.creds.Creds): the Credentials to set, or None
+            to create a new credential.
+        value (bytes): the value to set on the desired aspect of the Credential
+            or None to send GSS_C_EMPTY_BUFFER.
+
+    Returns:
+        Creds: The output credential.
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
diff --git a/gssapi/raw/ext_set_cred_opt.pyx b/gssapi/raw/ext_set_cred_opt.pyx
index 506dd12c..b59d18d1 100644
--- a/gssapi/raw/ext_set_cred_opt.pyx
+++ b/gssapi/raw/ext_set_cred_opt.pyx
@@ -1,16 +1,3 @@
-"""
-gss_set_cred_option
-
-Provides a way to set options on a credential based on the OID specified. A
-common use case is to set the GSS_KRB5_CRED_NO_CI_FLAGS_X on a Kerberos
-credential. This is used for interoperability with Microsoft's SSPI.
-
-Note this function is commonly lumped with the GGF extensions but they are not
-part of the GGF IETF draft so it's separated into it's own file.
-
-Closest draft IETF document for the gss_set_cred_option can be found at
-https://tools.ietf.org/html/draft-williams-kitten-channel-bound-flag-01
-"""
 GSSAPI="BASE"  # This ensures that a full module is generated by Cython
 
 from gssapi.raw.cython_types cimport *
@@ -28,34 +15,6 @@ cdef extern from "python_gssapi_ext.h":
 
 
 def set_cred_option(OID desired_aspect not None, Creds creds=None, value=None):
-    """
-    set_cred_option(desired_aspect, creds=None, value=None)
-
-    This method is used to set options of a :class:`Creds` object based on
-    an OID key. The options that can be set depends on the mech the credentials
-    were created with.
-
-    An example of how this can be used would be to set the
-    GSS_KRB5_CRED_NO_CI_FLAGS_X on a Kerberos credential. The OID string for
-    this flag is '1.2.752.43.13.29' and it requires no value to be set. This
-    must be set before the SecurityContext was initialised with the
-    credentials.
-
-    Args:
-        desired_aspect (~gssapi.OID): the desired aspect of the Credential to
-            set.
-        cred_handle (Creds): the Credentials to set, or None to create a new
-            credential.
-        value (bytes): the value to set on the desired aspect of the Credential
-            or None to send GSS_C_EMPTY_BUFFER.
-
-    Returns:
-        Creds: The output credential.
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_buffer_desc value_buffer
     if value is not None:
         value_buffer = gss_buffer_desc(len(value), value)
diff --git a/gssapi/raw/mech_krb5.pyi b/gssapi/raw/mech_krb5.pyi
new file mode 100644
index 00000000..e69de29b
diff --git a/gssapi/raw/message.pyi b/gssapi/raw/message.pyi
new file mode 100644
index 00000000..04c6df5e
--- /dev/null
+++ b/gssapi/raw/message.pyi
@@ -0,0 +1,156 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import WrapResult, UnwrapResult
+    from gssapi.sec_contexts import SecurityContext
+
+
+def get_mic(
+    context: "SecurityContext",
+    message: bytes,
+    qop: t.Optional[int] = None,
+) -> bytes:
+    """Generate a MIC for a message.
+
+    This method generates a Message Integrity Check token for the
+    given message.  This can be separately trasmitted to the other
+    entity, unlike wrap, which bundles the MIC and the message
+    together.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (bytes): the message for which to generate the MIC
+        qop (int): the requested Quality of Protection
+            (or None to use the default)
+
+    Returns:
+        bytes: the generated MIC token
+
+    Raises:
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.BadQoPError
+    """
+
+
+def verify_mic(
+    context: "SecurityContext",
+    message: bytes,
+    token: bytes,
+) -> int:
+    """Verify that a MIC matches a message.
+
+    This method verifies that the given MIC matches the given message.
+    If the MIC does not match the given message, an exception will
+    be raised.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (bytes): the message in question
+        token (bytes): the MIC token in question
+
+    Returns:
+        int: the QoP used.
+
+    Raises:
+        ~gssapi.exceptions.InvalidTokenError
+        ~gssapi.exceptions.BadMICError
+        ~gssapi.exceptions.DuplicateTokenError
+        ~gssapi.exceptions.ExpiredTokenError
+        ~gssapi.exceptions.TokenTooLateError
+        ~gssapi.exceptions.TokenTooEarlyError
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.MissingContextError
+    """
+
+
+def wrap_size_limit(
+    context: "SecurityContext",
+    output_size: int,
+    confidential: bool = True,
+    qop: t.Optional[int] = None,
+) -> int:
+    """Calculate the max message size.
+
+    This method calculates the unwrapped/unencrypted message size for
+    the given maximum wrapped/encrypted message size.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        output_size (int): the maximum desired wrapped/encrypted message size
+        confidential (bool): whether or not confidentiality is being used
+        qop (int): the QoP that will be when you actually call wrap
+            (or None for the default QoP)
+
+    Returns:
+        int: the maximum unencrypted/unwrapped message size
+
+    Raises:
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.BadQoPError
+    """
+
+
+def wrap(
+    context: "SecurityContext",
+    message: bytes,
+    confidential: bool = True,
+    qop: t.Optional[int] = None,
+) -> "WrapResult":
+    """Wrap/Encrypt a message.
+
+    This method wraps or encrypts a message (depending on the value
+    of confidential) with the given Quality of Protection.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (bytes): the message to wrap or encrypt
+        confidential (bool): whether or not to encrypt the message (True),
+            or just wrap it with a MIC (False)
+        qop (int): the desired Quality of Protection
+            (or None for the default QoP)
+
+    Returns:
+        WrapResult: the wrapped/encrypted message, and whether or not
+            encryption was actually used
+
+    Raises:
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.BadQoPError
+    """
+
+
+def unwrap(
+    context: "SecurityContext",
+    message: bytes,
+) -> "UnwrapResult":
+    """Unwrap/Decrypt a message.
+
+    This method unwraps or decrypts a message, depending
+    on whether the sender used confidentiality.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the current
+            security context
+        message (bytes): the message to unwrap/decrypt
+
+    Returns:
+        UnwrapResult: the unwrapped/decrypted message, whether or on
+            encryption was used, and the QoP used
+
+    Raises:
+        ~gssapi.exceptions.InvalidTokenError
+        ~gssapi.exceptions.BadMICError
+        ~gssapi.exceptions.DuplicateTokenError
+        ~gssapi.exceptions.ExpiredTokenError
+        ~gssapi.exceptions.TokenTooLateError
+        ~gssapi.exceptions.TokenTooEarlyError
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.MissingContextError
+    """
diff --git a/gssapi/raw/misc.pyi b/gssapi/raw/misc.pyi
new file mode 100644
index 00000000..00c17a93
--- /dev/null
+++ b/gssapi/raw/misc.pyi
@@ -0,0 +1,166 @@
+import typing as t
+
+from gssapi.raw.names import Name
+from gssapi.raw.oids import OID
+from gssapi.raw.types import MechType
+
+
+def indicate_mechs() -> t.Set[OID]:
+    """Get the currently supported mechanisms.
+
+    This method retrieves the currently supported GSSAPI mechanisms.
+    Note that if unknown mechanims are found, those will be skipped.
+    """
+
+
+def inquire_names_for_mech(
+    mech: OID,
+) -> t.Set[OID]:
+    """
+    inquire_names_for_mech(mech)
+    Get the name types supported by a mechanism.
+
+    This method retrives the different name types supported by
+    the given mechanism.
+
+    Args:
+        mech (~gssapi.OID): the mechanism in question
+
+    Returns:
+        list: the name type OIDs supported by the given mechanism
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def inquire_mechs_for_name(
+    name: Name,
+) -> t.Set[OID]:
+    """
+    inquire_mechs_for_name(name)
+    List the mechanisms which can process a name.
+
+    This method lists the mechanisms which may be able to
+    process the given name.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name in question
+
+    Returns:
+        The mechanism OIDs able to process the given name
+
+    Raises:
+        ~gssapi.exceptions.GSSError
+    """
+
+
+def _display_status(
+    error_code: int,
+    is_major_code: bool,
+    mech: t.Optional[MechType] = None,
+    message_context: int = 0,
+) -> t.Tuple[bytes, int, bool]:
+    """
+    Display a string message for a GSSAPI error code.
+
+    This method displays a message for a corresponding GSSAPI error code.
+    Since some error codes might have multiple messages, a context parameter
+    may be passed to indicate where in the series of messages we currently are
+    (this is the second item in the return value tuple).  Additionally, the
+    third item in the return value tuple indicates whether or not more
+    messages are available.
+
+    Args:
+        error_code (int): The error code in question
+        is_major_code (bool): is this a major code (True) or a
+            minor code (False)
+        mech (~gssapi.raw.types.MechType): The mechanism type that returned
+            this error code (defaults to None, for the default mechanism)
+        message_context (int): The context for this call -- this is used when
+            multiple messages are available (defaults to 0)
+
+    Returns:
+        (bytes, int, bool): the message, the new message context, and
+            whether or not to call again for further messages
+
+    Raises:
+       ValueError
+    """
+
+
+class GSSError(Exception):
+    """
+    A GSSAPI Error
+
+    This Exception represents an error returned from the GSSAPI
+    C bindings.  It contains the major and minor status codes
+    returned by the method which caused the error, and can
+    generate human-readable string messages from the error
+    codes
+    """
+
+    maj_code: int
+    min_code: int
+    token: t.Optional[bytes]
+    calling_code: int
+    routine_code: int
+    supplementary_code: int
+
+    @classmethod
+    def _parse_major_code(
+        cls,
+        maj_code: int
+    ) -> t.Tuple[int, int, int]: ...
+
+    def __init__(
+        self,
+        maj_code: int,
+        min_code: int,
+        token: t.Optional[bytes] = None,
+    ) -> None:
+        """
+        Create a new GSSError.
+
+        This method creates a new GSSError,
+        retrieves the releated human-readable
+        string messages, and uses the results to construct an
+        exception message
+
+        Args:
+            maj_code: the major code associated with this error
+            min_code: the minor code associated with this error
+            token: an error token associated with the error
+        """
+
+    def get_all_statuses(
+        self,
+        code: int,
+        is_maj: bool,
+    ) -> t.List[str]:
+        """
+        Retrieve all messages for a status code.
+
+        This method retrieves all human-readable messages
+        available for the given status code.
+
+        Args:
+            code: the status code in question
+            is_maj: whether this is a major status code (True)
+                or minor status code (False)
+
+        Returns:
+            [str]: A list of string messages associated with the
+                given code
+        """
+
+    def gen_message(self) -> str:
+        """
+        Retrieves all messages for this error's status codes
+
+        This method retrieves all messages for this error's status codes,
+        and forms them into a string for use as an exception message
+
+        Returns:
+            str: a string for use as this error's message
+        """
diff --git a/gssapi/raw/misc.pyx b/gssapi/raw/misc.pyx
index c16a0431..4179f642 100644
--- a/gssapi/raw/misc.pyx
+++ b/gssapi/raw/misc.pyx
@@ -31,14 +31,6 @@ cdef extern from "python_gssapi.h":
 
 
 def indicate_mechs():
-    """
-    indicate_mechs()
-    Get the currently supported mechanisms.
-
-    This method retrieves the currently supported GSSAPI mechanisms.
-    Note that if unknown mechanims are found, those will be skipped.
-    """
-
     cdef gss_OID_set mech_set
 
     cdef OM_uint32 maj_stat, min_stat
@@ -52,23 +44,6 @@ def indicate_mechs():
 
 
 def inquire_names_for_mech(OID mech not None):
-    """
-    inquire_names_for_mech(mech)
-    Get the name types supported by a mechanism.
-
-    This method retrives the different name types supported by
-    the given mechanism.
-
-    Args:
-        mech (~gssapi.OID): the mechanism in question
-
-    Returns:
-        list: the name type OIDs supported by the given mechanism
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_OID_set name_types
 
     cdef OM_uint32 maj_stat, min_stat
@@ -83,23 +58,6 @@ def inquire_names_for_mech(OID mech not None):
 
 
 def inquire_mechs_for_name(Name name not None):
-    """
-    inquire_mechs_for_name(name)
-    List the mechanisms which can process a name.
-
-    This method lists the mechanisms which may be able to
-    process the given name.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name in question
-
-    Returns:
-        list: the mechanism OIDs able to process the given name
-
-    Raises:
-        ~gssapi.exceptions.GSSError
-    """
-
     cdef gss_OID_set mech_types
 
     cdef OM_uint32 maj_stat, min_stat
@@ -115,33 +73,6 @@ def inquire_mechs_for_name(Name name not None):
 
 def _display_status(unsigned int error_code, bint is_major_code,
                     OID mech=None, unsigned int message_context=0):
-    """
-    Display a string message for a GSSAPI error code.
-
-    This method displays a message for a corresponding GSSAPI error code.
-    Since some error codes might have multiple messages, a context parameter
-    may be passed to indicate where in the series of messages we currently are
-    (this is the second item in the return value tuple).  Additionally, the
-    third item in the return value tuple indicates whether or not more
-    messages are available.
-
-    Args:
-        error_code (int): The error code in question
-        is_major_code (bool): is this a major code (True) or a
-            minor code (False)
-        mech (~gssapi.MechType): The mechanism type that returned this error
-            code (defaults to None, for the default mechanism)
-        message_context (int): The context for this call -- this is used when
-            multiple messages are available (defaults to 0)
-
-    Returns:
-        (bytes, int, bool): the message, the new message context, and
-            whether or not to call again for further messages
-
-    Raises:
-       ValueError
-    """
-
     cdef int status_type
     cdef gss_OID c_mech_type
 
@@ -223,15 +154,6 @@ class GSSErrorRegistry(type):
 # NB(directxman12): this needs to be here (and not in another file)
 #                   so that display_status can use it
 class GSSError(Exception, metaclass=GSSErrorRegistry):
-    """
-    A GSSAPI Error
-
-    This Exception represents an error returned from the GSSAPI
-    C bindings.  It contains the major and minor status codes
-    returned by the method which caused the error, and can
-    generate human-readable string messages from the error
-    codes
-    """
 
     MESSAGE = u"Major ({maj_stat}): {maj_str}, Minor ({min_stat}): {min_str}"
 
@@ -248,20 +170,6 @@ class GSSError(Exception, metaclass=GSSErrorRegistry):
         return (calling_code, routine_code, supplementary_code)
 
     def __init__(self, maj_code, min_code, token=None):
-        """
-        Create a new GSSError.
-
-        This method creates a new GSSError,
-        retrieves the releated human-readable
-        string messages, and uses the results to construct an
-        exception message
-
-        Args:
-            maj_code (int): the major code associated with this error
-            min_code (int): the minor code associated with this error
-            token (bytes): an error token associated with the error
-        """
-
         self.maj_code = maj_code
         self.min_code = min_code
 
@@ -275,22 +183,6 @@ class GSSError(Exception, metaclass=GSSErrorRegistry):
         super(GSSError, self).__init__(self.gen_message())
 
     def get_all_statuses(self, code, is_maj):
-        """
-        Retrieve all messages for a status code.
-
-        This method retrieves all human-readable messages
-        available for the given status code.
-
-        Args:
-            code (int): the status code in question
-            is_maj (bool): whether this is a major status code (True)
-                or minor status code (False)
-
-        Returns:
-            [bytes]: A list of string messages associated with the
-                given code
-        """
-
         try:
             msg_encoding = locale.getlocale(locale.LC_MESSAGES)[1] or 'UTF-8'
         except AttributeError:  # Windows doesn't have LC_MESSAGES
@@ -316,16 +208,6 @@ class GSSError(Exception, metaclass=GSSErrorRegistry):
         return res
 
     def gen_message(self):
-        """
-        Retrieves all messages for this error's status codes
-
-        This method retrieves all messages for this error's status codes,
-        and forms them into a string for use as an exception message
-
-        Returns:
-            bytes: a string for use as this error's message
-        """
-
         maj_statuses = self.get_all_statuses(self.maj_code, True)
         min_statuses = self.get_all_statuses(self.min_code, False)
 
diff --git a/gssapi/raw/named_tuples.py b/gssapi/raw/named_tuples.py
index e41bec95..f6e2b95b 100644
--- a/gssapi/raw/named_tuples.py
+++ b/gssapi/raw/named_tuples.py
@@ -1,4 +1,7 @@
-from typing import Iterable, List, NamedTuple, Optional, Set, TYPE_CHECKING
+from typing import List, NamedTuple, Optional, Set, TYPE_CHECKING
+
+from gssapi.raw.oids import OID
+from gssapi.raw.types import RequirementFlag
 
 if TYPE_CHECKING:
     import gssapi.raw as g
@@ -7,7 +10,7 @@
 class AcquireCredResult(NamedTuple):
     """Credential result when acquiring a GSSAPI credential."""
     creds: "g.Creds"  #: GSSAPI credentials that were acquired
-    mechs: Set["g.OID"]  #: Set of mechs the cred is for
+    mechs: Set[OID]  #: Set of mechs the cred is for
     lifetime: int  #: Number of seconds for which the cred will remain valid
 
 
@@ -16,7 +19,7 @@ class InquireCredResult(NamedTuple):
     name: Optional["g.Name"]  #: The principal associated with the credential
     lifetime: Optional[int]  #: Number of seconds which the cred is valid for
     usage: Optional[str]  #: How the credential can be used
-    mechs: Optional[Set["g.OID"]]  #: Set of mechs the cred is for
+    mechs: Optional[Set[OID]]  #: Set of mechs the cred is for
 
 
 class InquireCredByMechResult(NamedTuple):
@@ -30,7 +33,7 @@ class InquireCredByMechResult(NamedTuple):
 class AddCredResult(NamedTuple):
     """Result of adding to a GSSAPI credential."""
     creds: Optional["g.Creds"]  #: The credential that was generated
-    mechs: Set["g.OID"]  #: Set of mechs the cred is for
+    mechs: Set[OID]  #: Set of mechs the cred is for
     init_lifetime: int  #: Time valid for initiation
     accept_lifetime: int  #: Time valid for accepting
 
@@ -38,7 +41,7 @@ class AddCredResult(NamedTuple):
 class DisplayNameResult(NamedTuple):
     """Textual representation of a GSSAPI name."""
     name: bytes  #: The representation of the GSSAPI name
-    name_type: Optional["g.OID"]  #: The type of GSSAPI name
+    name_type: Optional[OID]  #: The type of GSSAPI name
 
 
 class WrapResult(NamedTuple):
@@ -58,9 +61,9 @@ class AcceptSecContextResult(NamedTuple):
     """Result when accepting a security context by an initiator."""
     context: "g.SecurityContext"  #: The acceptor security context
     initiator_name: "g.Name"  #: The authenticated name of the initiator
-    mech: "g.OID"  #: Mechanism with which the context was established
+    mech: OID  #: Mechanism with which the context was established
     token: Optional[bytes]  #: Token to be returned to the initiator
-    flags: "g.equirementFlag"  #: Services requested by the initiator
+    flags: RequirementFlag  #: Services requested by the initiator
     lifetime: int  #: Seconds for which the context is valid for
     delegated_creds: Optional["g.Creds"]  #: Delegated credentials
     more_steps: bool  #: More input is required to complete the exchange
@@ -69,8 +72,8 @@ class AcceptSecContextResult(NamedTuple):
 class InitSecContextResult(NamedTuple):
     """Result when initiating a security context"""
     context: "g.SecurityContext"  #: The initiator security context
-    mech: "g.OID"  #: Mechanism used in the security context
-    flags: "g.RequirementFlag"  #: Services available for the context
+    mech: OID  #: Mechanism used in the security context
+    flags: RequirementFlag  #: Services available for the context
     token: Optional[bytes]  #: Token to be sent to the acceptor
     lifetime: int  #: Seconds for which the context is valid for
     more_steps: bool  #: More input is required to complete the exchange
@@ -81,15 +84,15 @@ class InquireContextResult(NamedTuple):
     initiator_name: Optional["g.Name"]  #: Name of the initiator
     target_name: Optional["g.Name"]  #: Name of the acceptor
     lifetime: Optional[int]  #: Time valid for the security context
-    mech: Optional["g.OID"]  #: Mech used to create the security context
-    flags: Optional["g.RequirementFlag"]  #: Services available for the context
+    mech: Optional[OID]  #: Mech used to create the security context
+    flags: Optional[RequirementFlag]  #: Services available for the context
     locally_init: Optional[bool]  #: Context was initiated locally
     complete: Optional[bool]  #: Context has been established and ready to use
 
 
 class StoreCredResult(NamedTuple):
     """Result of the credential storing operation."""
-    mechs: List["g.OID"]  #: Mechs that were stored in the credential store
+    mechs: List[OID]  #: Mechs that were stored in the credential store
     usage: str  #: How the credential can be used
 
 
@@ -103,21 +106,21 @@ class InquireNameResult(NamedTuple):
     """Information about a GSSAPI Name."""
     attrs: List[bytes]  #: Set of attribute names
     is_mech_name: bool  #: Name is a mechanism name
-    mech: "g.OID"  #: The mechanism if is_name_mech is True
+    mech: OID  #: The mechanism if is_name_mech is True
 
 
 class GetNameAttributeResult(NamedTuple):
     """GSSAPI Name attribute values."""
-    values: Iterable[bytes]  #: Raw values
-    display_values: Iterable[bytes]  #: Human-readable values
+    values: List[bytes]  #: Raw values
+    display_values: List[bytes]  #: Human-readable values
     authenticated: bool  #: Attribute has been authenticated
     complete: bool  #: Attribute value is marked as complete
 
 
 class InquireAttrsResult(NamedTuple):
     """Set of attributes supported and known by a mechanism."""
-    mech_attrs: Set["g.OID"]  #: The mechanisms attributes
-    known_mech_attrs: Set["g.OID"]  #: Known attributes of the mechanism
+    mech_attrs: Set[OID]  #: The mechanisms attributes
+    known_mech_attrs: Set[OID]  #: Known attributes of the mechanism
 
 
 class DisplayAttrResult(NamedTuple):
diff --git a/gssapi/raw/names.pyi b/gssapi/raw/names.pyi
new file mode 100644
index 00000000..85d91611
--- /dev/null
+++ b/gssapi/raw/names.pyi
@@ -0,0 +1,170 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.named_tuples import DisplayNameResult
+    from gssapi.raw.oids import OID
+
+class Name:
+    """
+    A GSSAPI Name
+    """
+
+    def __new__(
+        cls,
+        cpy: t.Optional["Name"] = None,
+    ) -> "Name": ...
+
+
+def import_name(
+    name: bytes,
+    name_type: t.Optional["OID"] = None,
+) -> Name:
+    """Convert a string and a name type into a GSSAPI name.
+
+    This method takes a string name and a name type and converts
+    them into a GSSAPI :class:`Name`.
+
+    Args:
+        name (~gssapi.raw.names.Name): the string version of the name
+        name_type (~gssapi.raw.types.MechType): the type of this name
+
+    Returns:
+        Name: the GSSAPI version of the name
+
+    Raises:
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+        ~gssapi.exceptions.BadMechanismError
+    """
+
+
+def display_name(
+    name: Name,
+    name_type: bool = True,
+) -> "DisplayNameResult":
+    """Convert a GSSAPI name into its components.
+
+    This method converts a GSSAPI :class:`Name` back into its
+    text form.  If ``name_type`` is True, it also attempts to
+    retrieve the :class:`~gssapi.raw.types.NameType` of the name (otherwise the
+    returned name type will be ``None``).
+
+    Args:
+        name (~gssapi.raw.names.Name): the name in question
+        name_type (~gssapi.raw.types.MechType): whether or not to retrieve the
+            name type
+
+    Returns:
+        DisplayNameResult: the text part of the name and its type
+
+    Raises:
+        ~gssapi.exceptions.BadNameError
+    """
+
+
+def compare_name(
+    name1: Name,
+    name2: Name,
+) -> bool:
+    """Check two GSSAPI names to see if they are the same.
+
+    This method compares two GSSAPI names, checking to
+    see if they are equivalent.
+
+    Args:
+        name1 (~gssapi.raw.names.Name): the first name to compare
+        name2 (~gssapi.raw.names.Name): the second name to compare
+
+    Returns:
+        bool: whether or not the names are equal
+
+    Raises:
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+    """
+
+
+def export_name(
+    name: Name,
+) -> bytes:
+    """Export a GSSAPI name.
+
+    This method "produces a canonical contigous string representation
+    of a mechanism name, suitable for direct comparison for use in
+    authorization functions".
+
+    The input name must be a valid GSSAPI mechanism name, as generated by
+    :func:`canonicalize_name` or
+    :func:`~gssapi.raw.sec_contexts.accept_sec_context`.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to export
+
+    Returns:
+        bytes: the exported name
+
+    Raises:
+        ~gssapi.exceptions.MechanismNameRequiredError
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+    """
+
+
+def canonicalize_name(
+    name: Name,
+    mech: "OID",
+) -> Name:
+    """Canonicalize an arbitrary GSSAPI Name into a Mechanism Name
+
+    This method turns any GSSAPI name into a "mechanism name" --
+    a full form name specific to a mechanism.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to canonicalize
+        mech (~gssapi.raw.types.MechType): the mechanism type to use to
+            canonicalize the name
+
+    Returns:
+        Name: a canonicalized version of the input name
+
+    Raises:
+        ~gssapi.exceptions.BadMechanismError
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+    """
+
+
+def duplicate_name(
+    name: Name,
+) -> Name:
+    """Duplicate a GSSAPI name.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name to duplicate
+
+    Returns:
+        Name: a duplicate of the input name
+
+    Raises:
+        ~gssapi.exceptions.BadNameError
+    """
+
+
+def release_name(
+    name: Name,
+) -> None:
+    """Release a GSSAPI name.
+
+    This method frees a GSSAPI :class:`Name`.
+    You probably won't have to do this.
+
+    Warning:
+        This method is deprecated.  Names are
+        automatically freed by Python.
+
+    Args:
+        name (~gssapi.raw.names.Name): the name in question
+
+    Raises:
+        ~gssapi.exceptions.BadNameError
+    """
diff --git a/gssapi/raw/names.pyx b/gssapi/raw/names.pyx
index a6521dce..f4d22bef 100644
--- a/gssapi/raw/names.pyx
+++ b/gssapi/raw/names.pyx
@@ -41,9 +41,6 @@ cdef extern from "python_gssapi.h":
 
 
 cdef class Name:
-    """
-    A GSSAPI Name
-    """
     # defined in pxd
     # cdef gss_name_t raw_name
 
@@ -66,26 +63,6 @@ cdef class Name:
 
 
 def import_name(name not None, OID name_type=None):
-    """
-    import_name(name, name_type=None)
-    Convert a string and a name type into a GSSAPI name.
-
-    This method takes a string name and a name type and converts
-    them into a GSSAPI :class:`Name`.
-
-    Args:
-        name (bytes): the string version of the name
-        name_type (~gssapi.NameType): the type of this name
-
-    Returns:
-        Name: the GSSAPI version of the name
-
-    Raises:
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-        ~gssapi.exceptions.BadMechanismError
-    """
-
     cdef gss_OID nt
     if name_type is None:
         nt = GSS_C_NO_OID
@@ -114,26 +91,6 @@ def import_name(name not None, OID name_type=None):
 
 
 def display_name(Name name not None, name_type=True):
-    """
-    display_name(name, name_type=True)
-    Convert a GSSAPI name into its components.
-
-    This method converts a GSSAPI :class:`Name` back into its
-    text form.  If ``name_type`` is True, it also attempts to
-    retrieve the :class:`NameType` of the name (otherwise the
-    returned name type will be ``None``).
-
-    Args:
-        name (~gssapi.raw.names.Name): the name in question
-        name_type (bool): whether or not to retrieve the name type
-
-    Returns:
-        DisplayNameResult: the text part of the name and its type
-
-    Raises:
-        ~gssapi.exceptions.BadNameError
-    """
-
     # GSS_C_EMPTY_BUFFER
     cdef gss_buffer_desc output_buffer = gss_buffer_desc(0, NULL)
 
@@ -169,25 +126,6 @@ def display_name(Name name not None, name_type=True):
 
 
 def compare_name(Name name1=None, Name name2=None):
-    """
-    compare_name(name1, name2)
-    Check two GSSAPI names to see if they are the same.
-
-    This method compares two GSSAPI names, checking to
-    see if they are equivalent.
-
-    Args:
-        name1 (~gssapi.raw.names.Name): the first name to compare
-        name2 (~gssapi.raw.names.Name): the second name to compare
-
-    Returns:
-        bool: whether or not the names are equal
-
-    Raises:
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-    """
-
     # check for either value being None
     if name1 is None and name2 is None:
         return True
@@ -208,28 +146,6 @@ def compare_name(Name name1=None, Name name2=None):
 
 
 def export_name(Name name not None):
-    """
-    Export a GSSAPI name.
-
-    This method "produces a canonical contigous string representation
-    of a mechanism name, suitable for direct comparison for use in
-    authorization functions".
-
-    The input name must be a valid GSSAPI mechanism name, as generated
-    by :func:`canonicalize_name` or :func:`accept_sec_context`.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to export
-
-    Returns:
-        bytes: the exported name
-
-    Raises:
-        ~gssapi.exceptions.MechanismNameRequiredError
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-    """
-
     # GSS_C_EMPTY_BUFFER
     cdef gss_buffer_desc exported_name = gss_buffer_desc(0, NULL)
 
@@ -248,27 +164,6 @@ def export_name(Name name not None):
 
 
 def canonicalize_name(Name name not None, OID mech not None):
-    """
-    canonicalize_name(name, mech)
-    Canonicalize an arbitrary GSSAPI Name into a Mechanism Name
-
-    This method turns any GSSAPI name into a "mechanism name" --
-    a full form name specific to a mechanism.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to canonicalize
-        mech (~gssapi.MechType): the mechanism type to use to
-            canonicalize the name
-
-    Returns:
-        Name: a canonicalized version of the input name
-
-    Raises:
-        ~gssapi.exceptions.BadMechanismError
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-    """
-
     cdef gss_name_t canonicalized_name
 
     cdef OM_uint32 maj_stat, min_stat
@@ -287,20 +182,6 @@ def canonicalize_name(Name name not None, OID mech not None):
 
 
 def duplicate_name(Name name not None):
-    """
-    duplicate_name(name)
-    Duplicate a GSSAPI name.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name to duplicate
-
-    Returns:
-        Name: a duplicate of the input name
-
-    Raises:
-        ~gssapi.exceptions.BadNameError
-    """
-
     cdef gss_name_t new_name
 
     cdef OM_uint32 maj_stat, min_stat
@@ -316,24 +197,6 @@ def duplicate_name(Name name not None):
 
 
 def release_name(Name name not None):
-    """
-    release_name(name)
-    Release a GSSAPI name.
-
-    This method frees a GSSAPI :class:`Name`.
-    You probably won't have to do this.
-
-    Warning:
-        This method is deprecated.  Names are
-        automatically freed by Python.
-
-    Args:
-        name (~gssapi.raw.names.Name): the name in question
-
-    Raises:
-        ~gssapi.exceptions.BadNameError
-    """
-
     cdef OM_uint32 maj_stat, min_stat
     maj_stat = gss_release_name(&min_stat, &name.raw_name)
     if maj_stat != GSS_S_COMPLETE:
diff --git a/gssapi/raw/oids.pyi b/gssapi/raw/oids.pyi
new file mode 100644
index 00000000..a613d82a
--- /dev/null
+++ b/gssapi/raw/oids.pyi
@@ -0,0 +1,50 @@
+import typing as t
+
+class OID:
+    """
+    A GSSAPI OID
+
+    A new OID may be created by passing the `elements` argument
+    to the constructor.  The `elements` argument should be a
+    `bytes` consisting of the BER-encoded values in the OID.
+
+    To retrive the underlying bytes, use the :func:`bytes`
+    function in Python 3.
+
+    This object is hashable, and may be compared using equality
+    operators.
+    """
+
+    def __new__(
+        cls,
+        cpy: t.Optional["OID"] = None,
+        elements: t.Optional[bytes] = None,
+    ) -> "OID": ...
+
+    @classmethod
+    def from_int_seq(
+        cls,
+        integer_sequence: t.Union[str, t.Iterable[int]],
+    ) -> "OID":
+        """Create a OID from a sequence of integers.
+
+        This method creates an OID from a sequence of integers.
+        The sequence can either be in dotted form as a string,
+        or in list form.
+
+        This method is not for BER-encoded byte strings, which
+        can be passed directly to the OID constructor.
+
+        Args:
+            integer_sequence: either a list of integers or
+                a string in dotted form
+
+        Returns:
+            OID: the OID represented by the given integer sequence
+
+        Raises:
+            ValueError: the sequence is less than two elements long
+        """
+
+    @property
+    def dotted_form(self) -> str: ...
diff --git a/gssapi/raw/oids.pyx b/gssapi/raw/oids.pyx
index b0bd5546..aa0e17af 100644
--- a/gssapi/raw/oids.pyx
+++ b/gssapi/raw/oids.pyx
@@ -11,20 +11,6 @@ cdef inline bint c_compare_oids(gss_OID a, gss_OID b):
 
 
 cdef class OID:
-    """
-    A GSSAPI OID
-
-    A new OID may be created by passing the `elements` argument
-    to the constructor.  The `elements` argument should be a
-    `bytes` consisting of the BER-encoded values in the OID.
-
-    To retrive the underlying bytes, use the :func:`bytes`
-    function in Python 3 or the :meth:`__bytes__` method directly
-    in Python 2.
-
-    This object is hashable, and may be compared using equality
-    operators.
-    """
     # defined in pxd
     # cdef gss_OID_desc raw_oid = NULL
     # cdef bint _free_on_dealloc = NULL
@@ -73,28 +59,6 @@ cdef class OID:
 
     @classmethod
     def from_int_seq(cls, integer_sequence):
-        """
-        from_int_seq(integer_sequence)
-        Create a OID from a sequence of integers.
-
-        This method creates an OID from a sequence of integers.
-        The sequence can either be in dotted form as a string,
-        or in list form.
-
-        This method is not for BER-encoded byte strings, which
-        can be passed directly to the OID constructor.
-
-        Args:
-            integer_sequence: either a list of integers or
-                a string in dotted form
-
-        Returns:
-            OID: the OID represented by the given integer sequence
-
-        Raises:
-            ValueError: the sequence is less than two elements long
-        """
-
         if isinstance(integer_sequence, str):
             integer_sequence = integer_sequence.split('.')
 
diff --git a/gssapi/raw/sec_contexts.pyi b/gssapi/raw/sec_contexts.pyi
new file mode 100644
index 00000000..0c8068cf
--- /dev/null
+++ b/gssapi/raw/sec_contexts.pyi
@@ -0,0 +1,294 @@
+import typing as t
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.chan_bindings import ChannelBindings
+    from gssapi.raw.creds import Creds
+    from gssapi.raw.named_tuples import (
+        AcceptSecContextResult,
+        InitSecContextResult,
+        InquireContextResult,
+    )
+    from gssapi.raw.names import Name
+    from gssapi.raw.oids import OID
+    from gssapi.raw.types import RequirementFlag
+
+class SecurityContext:
+    """
+    A GSSAPI Security Context
+    """
+
+    def __new__(
+        cls,
+        cpy: t.Optional["SecurityContext"] = None,
+    ) -> "SecurityContext": ...
+
+    @property
+    def _started(self) -> bool: ...
+
+
+def init_sec_context(
+    name: "Name",
+    creds: t.Optional["Creds"] = None,
+    context: t.Optional[SecurityContext] = None,
+    mech: t.Optional["OID"] = None,
+    flags: t.Optional[t.Union[
+        int, "RequirementFlag",
+        t.Iterable[int], t.Iterable["RequirementFlag"]
+    ]] = None,
+    lifetime: t.Optional[int] = None,
+    channel_bindings: t.Optional["ChannelBindings"] = None,
+    input_token: t.Optional[bytes] = None,
+) -> "InitSecContextResult":
+    """Initiate a GSSAPI security context.
+
+    This method initiates a GSSAPI security context, targeting the given
+    target name.  To create a basic context, just provide the target name.
+    Further calls used to update the context should pass in the output context
+    of the last call, as well as the input token received from the acceptor.
+
+    Warning:
+        This changes the input context!
+
+    Args:
+        target_name (~gssapi.raw.names.Name): the target for the security
+            context
+        creds (Creds): the credentials to use to initiate the context,
+            or None to use the default credentials
+        context (~gssapi.raw.sec_contexts.SecurityContext): the security
+            context to update, or None to create a new context
+        mech (~gssapi.raw.types.MechType): the mechanism type for this security
+            context, or None for the default mechanism type
+        flags (list): the flags to request for the security context, or
+            None to use the default set: mutual_authentication and
+            out_of_sequence_detection.  This may also be an
+            :class:`IntEnumFlagSet`
+        lifetime (int): the request lifetime of the security context (a value
+            of 0 or None means indefinite)
+        channel_bindings (ChannelBindings): The channel bindings (or None for
+            no channel bindings)
+        input_token (bytes): the token to use to update the security context,
+            or None if you are creating a new context
+
+    Returns:
+        InitSecContextResult: the output security context, the actual mech
+        type, the actual flags used, the output token to send to the acceptor,
+        the actual lifetime of the context (or None if not supported or
+        indefinite), and whether or not more calls are needed to finish the
+        initiation.
+
+    Raises:
+        ~gssapi.exceptions.InvalidTokenError
+        ~gssapi.exceptions.InvalidCredentialsError
+        ~gssapi.exceptions.MissingCredentialsError
+        ~gssapi.exceptions.ExpiredCredentialsError
+        ~gssapi.exceptions.BadChannelBindingsError
+        ~gssapi.exceptions.BadMICError
+        ~gssapi.exceptions.ExpiredTokenError
+        ~gssapi.exceptions.DuplicateTokenError
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.BadNameTypeError
+        ~gssapi.exceptions.BadNameError
+        ~gssapi.exceptions.BadMechanismError
+    """
+
+
+def accept_sec_context(
+    input_token: bytes,
+    acceptor_creds: t.Optional["Creds"] = None,
+    context: t.Optional[SecurityContext] = None,
+    channel_bindings: t.Optional["ChannelBindings"] = None,
+) -> "AcceptSecContextResult":
+    """Accept a GSSAPI security context.
+
+    This method accepts a GSSAPI security context using a token sent by the
+    initiator, using the given credentials.  It can either be used to accept a
+    security context and create a new security context object, or to update an
+    existing security context object.
+
+    Warning:
+        This changes the input context!
+
+    Args:
+        input_token (bytes): the token sent by the context initiator
+        acceptor_creds (Creds): the credentials to be used to accept the
+            context (or None to use the default credentials)
+        context (~gssapi.raw.sec_contexts.SecurityContext): the security
+            context to update (or None to create a new security context object)
+        channel_bindings (ChannelBindings): The channel bindings (or None for
+            no channel bindings)
+
+    Returns:
+        AcceptSecContextResult: the resulting security context, the initiator
+        name, the mechanism being used, the output token, the flags in use,
+        the lifetime of the context (or None for indefinite or not
+        supported), the delegated credentials (valid only if the
+        delegate_to_peer flag is set), and whether or not further token
+        exchanges are needed to finalize the security context.
+
+    Raises:
+        ~gssapi.exceptions.InvalidTokenError
+        ~gssapi.exceptions.InvalidCredentialsError
+        ~gssapi.exceptions.MissingCredentialsError
+        ~gssapi.exceptions.ExpiredCredentialsError
+        ~gssapi.exceptions.BadChannelBindingsError
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.BadMICError
+        ~gssapi.exceptions.ExpiredTokenError
+        ~gssapi.exceptions.DuplicateTokenError
+        ~gssapi.exceptions.BadMechanismError
+    """
+
+
+def inquire_context(
+    context: SecurityContext,
+    initiator_name: bool = True,
+    target_name: bool = True,
+    lifetime: bool = True,
+    mech: bool = True,
+    flags: bool = True,
+    locally_init: bool = True,
+    complete: bool = True,
+) -> "InquireContextResult":
+    """Get information about a security context.
+
+    This method obtains information about a security context, including
+    the initiator and target names, as well as the TTL, mech,
+    flags, and its current state (open vs closed).
+
+    Note:
+        the target name may be ``None`` if it would have been ``GSS_C_NO_NAME``
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the context in
+            question
+
+    Returns:
+        InquireContextResult: the initiator name, the target name, the TTL
+        (can be None for indefinite or not supported), the mech type, the
+        flags, whether or not the context was locally initiated,
+        and whether or not the context is currently fully established
+
+    Raises:
+        ~gssapi.exceptions.MissingContextError
+    """
+
+
+def context_time(
+    context: SecurityContext,
+) -> int:
+    """Get the amount of time for which the given context will remain valid.
+
+    This method determines the amount of time for which the given
+    security context will remain valid.  An expired context will
+    give a result of 0.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the security
+            context in question
+
+    Returns:
+        int: the number of seconds for which the context will be valid
+
+    Raises:
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.MissingContextError
+    """
+
+
+def process_context_token(
+    context: SecurityContext,
+    token: bytes,
+) -> None:
+    """Process a token asynchronously.
+
+    This method provides a way to process a token, even if the
+    given security context is not expecting one.  For example,
+    if the initiator has the initSecContext return that the context
+    is complete, but the acceptor is unable to accept the context,
+    and wishes to send a token to the initiator, letting the
+    initiator know of the error.
+
+    Warning:
+        This method has been essentially deprecated by :rfc:`2744`.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the security
+            context against which to process the token
+        token (bytes): the token to process
+
+    Raises:
+        ~gssapi.exceptions.InvalidTokenError
+        ~gssapi.exceptions.MissingContextError
+    """
+
+
+def import_sec_context(
+    token: bytes,
+) -> SecurityContext:
+    """Import a context from another process.
+
+    This method imports a security context established in another process
+    by reading the specified token which was output by
+    :func:`export_sec_context`.
+
+    Raises:
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.InvalidTokenError
+        ~gssapi.exceptions.OperationUnavailableError
+        ~gssapi.exceptions.UnauthorizedError
+    """
+
+
+def export_sec_context(
+    context: SecurityContext,
+) -> bytes:
+    """Export a context for use in another process.
+
+    This method exports a security context, deactivating in the current process
+    and creating a token which can then be imported into another process
+    with :func:`import_sec_context`.
+
+    Warning: this modifies the input context
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the context to send
+            to another process
+
+    Returns:
+        bytes: the output token to be imported
+
+    Raises:
+        ~gssapi.exceptions.ExpiredContextError
+        ~gssapi.exceptions.MissingContextError
+        ~gssapi.exceptions.OperationUnavailableError
+    """
+
+
+def delete_sec_context(
+    context: SecurityContext,
+    local_only: bool = True,
+) -> bytes:
+    """Delete a GSSAPI security context.
+
+    This method deletes a GSSAPI security context,
+    returning an output token to send to the other
+    holder of the security context to notify them
+    of the deletion.
+
+    Note:
+        This method generally should not be used.  :class:`SecurityContext`
+        objects will automatically be freed by Python.
+
+    Args:
+        context (~gssapi.raw.sec_contexts.SecurityContext): the security
+            context in question
+        local_only (bool): should we request local deletion (True), or also
+            remote deletion (False), in which case a token is also returned
+
+    Returns:
+        bytes: the output token (if remote deletion is requested).  Generally
+            this is None, but bytes for compatibility.
+
+    Raises:
+        ~gssapi.exceptions.MissingContextError
+    """
diff --git a/gssapi/raw/sec_contexts.pyx b/gssapi/raw/sec_contexts.pyx
index 5ed9b3c2..d2c92051 100644
--- a/gssapi/raw/sec_contexts.pyx
+++ b/gssapi/raw/sec_contexts.pyx
@@ -75,9 +75,6 @@ cdef extern from "python_gssapi.h":
 
 
 cdef class SecurityContext:
-    """
-    A GSSAPI Security Context
-    """
     # defined in pxd
     # cdef gss_ctx_id_t raw_ctx
 
@@ -115,61 +112,6 @@ def init_sec_context(Name target_name not None, Creds creds=None,
                      flags=None, lifetime=None,
                      ChannelBindings channel_bindings=None,
                      input_token=None):
-    """
-    init_sec_context(target_name, creds=None, context=None, mech=None, \
-flags=None, lifetime=None, channel_bindings=None, input_token=None)
-    Initiate a GSSAPI security context.
-
-    This method initiates a GSSAPI security context, targeting the given
-    target name.  To create a basic context, just provide the target name.
-    Further calls used to update the context should pass in the output context
-    of the last call, as well as the input token received from the acceptor.
-
-    Warning:
-        This changes the input context!
-
-    Args:
-        target_name (~gssapi.raw.names.Name): the target for the security
-            context
-        creds (Creds): the credentials to use to initiate the context,
-            or None to use the default credentials
-        context (~gssapi.raw.sec_contexts.SecurityContext): the security
-            context to update, or None to create a new context
-        mech (~gssapi.MechType): the mechanism type for this security context,
-            or None for the default mechanism type
-        flags (list): the flags to request for the security context, or
-            None to use the default set: mutual_authentication and
-            out_of_sequence_detection.  This may also be an
-            :class:`IntEnumFlagSet`
-        lifetime (int): the request lifetime of the security context (a value
-            of 0 or None means indefinite)
-        channel_bindings (ChannelBindings): The channel bindings (or None for
-            no channel bindings)
-        input_token (bytes): the token to use to update the security context,
-            or None if you are creating a new context
-
-    Returns:
-        InitSecContextResult: the output security context, the actual mech
-        type, the actual flags used, the output token to send to the acceptor,
-        the actual lifetime of the context (or None if not supported or
-        indefinite), and whether or not more calls are needed to finish the
-        initiation.
-
-    Raises:
-        ~gssapi.exceptions.InvalidTokenError
-        ~gssapi.exceptions.InvalidCredentialsError
-        ~gssapi.exceptions.MissingCredentialsError
-        ~gssapi.exceptions.ExpiredCredentialsError
-        ~gssapi.exceptions.BadChannelBindingsError
-        ~gssapi.exceptions.BadMICError
-        ~gssapi.exceptions.ExpiredTokenError
-        ~gssapi.exceptions.DuplicateTokenError
-        ~gssapi.exceptions.MissingContextError
-        ~gssapi.exceptions.BadNameTypeError
-        ~gssapi.exceptions.BadNameError
-        ~gssapi.exceptions.BadMechanismError
-    """
-
     cdef gss_OID mech_oid
     if mech is not None:
         mech_oid = &mech.raw_oid
@@ -249,49 +191,6 @@ flags=None, lifetime=None, channel_bindings=None, input_token=None)
 def accept_sec_context(input_token not None, Creds acceptor_creds=None,
                        SecurityContext context=None,
                        ChannelBindings channel_bindings=None):
-    """
-    accept_sec_context(input_token, acceptor_creds=None, context=None, \
-channel_bindings=None)
-    Accept a GSSAPI security context.
-
-    This method accepts a GSSAPI security context using a token sent by the
-    initiator, using the given credentials.  It can either be used to accept a
-    security context and create a new security context object, or to update an
-    existing security context object.
-
-    Warning:
-        This changes the input context!
-
-    Args:
-        input_token (bytes): the token sent by the context initiator
-        acceptor_creds (Creds): the credentials to be used to accept the
-            context (or None to use the default credentials)
-        context (~gssapi.raw.sec_contexts.SecurityContext): the security
-            context to update (or None to create a new security context object)
-        channel_bindings (ChannelBindings): The channel bindings (or None for
-            no channel bindings)
-
-    Returns:
-        AcceptSecContextResult: the resulting security context, the initiator
-            name, the mechanism being used, the output token, the flags in use,
-            the lifetime of the context (or None for indefinite or not
-            supported), the delegated credentials (valid only if the
-            delegate_to_peer flag is set), and whether or not further token
-            exchanges are needed to finalize the security context.
-
-    Raises:
-        ~gssapi.exceptions.InvalidTokenError
-        ~gssapi.exceptions.InvalidCredentialsError
-        ~gssapi.exceptions.MissingCredentialsError
-        ~gssapi.exceptions.ExpiredCredentialsError
-        ~gssapi.exceptions.BadChannelBindingsError
-        ~gssapi.exceptions.MissingContextError
-        ~gssapi.exceptions.BadMICError
-        ~gssapi.exceptions.ExpiredTokenError
-        ~gssapi.exceptions.DuplicateTokenError
-        ~gssapi.exceptions.BadMechanismError
-    """
-
     cdef gss_channel_bindings_t bdng
     if channel_bindings is not None:
         bdng = channel_bindings.__cvalue__()
@@ -374,32 +273,6 @@ channel_bindings=None)
 def inquire_context(SecurityContext context not None, initiator_name=True,
                     target_name=True, lifetime=True, mech=True,
                     flags=True, locally_init=True, complete=True):
-    """
-    inquire_context(context, initiator_name=True, target_name=True, \
-lifetime=True, mech=True, flags=True, locally_init=True, complete=True)
-    Get information about a security context.
-
-    This method obtains information about a security context, including
-    the initiator and target names, as well as the TTL, mech,
-    flags, and its current state (open vs closed).
-
-    Note:
-        the target name may be ``None`` if it would have been ``GSS_C_NO_NAME``
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the context in
-            question
-
-    Returns:
-        InquireContextResult: the initiator name, the target name, the TTL
-            (can be None for indefinite or not supported), the mech type, the
-            flags, whether or not the context was locally initiated,
-            and whether or not the context is currently fully established
-
-    Raises:
-        ~gssapi.exceptions.MissingContextError
-    """
-
     cdef gss_name_t output_init_name
     cdef gss_name_t *init_name_ptr = NULL
     if initiator_name:
@@ -491,26 +364,6 @@ lifetime=True, mech=True, flags=True, locally_init=True, complete=True)
 
 
 def context_time(SecurityContext context not None):
-    """
-    context_time(context)
-    Get the amount of time for which the given context will remain valid.
-
-    This method determines the amount of time for which the given
-    security context will remain valid.  An expired context will
-    give a result of 0.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the security
-            context in question
-
-    Returns:
-        int: the number of seconds for which the context will be valid
-
-    Raises:
-        ~gssapi.exceptions.ExpiredContextError
-        ~gssapi.exceptions.MissingContextError
-    """
-
     cdef OM_uint32 ttl
 
     cdef OM_uint32 maj_stat, min_stat
@@ -524,30 +377,6 @@ def context_time(SecurityContext context not None):
 
 
 def process_context_token(SecurityContext context not None, token):
-    """
-    process_context_token(context, token)
-    Process a token asynchronously.
-
-    This method provides a way to process a token, even if the
-    given security context is not expecting one.  For example,
-    if the initiator has the initSecContext return that the context
-    is complete, but the acceptor is unable to accept the context,
-    and wishes to send a token to the initiator, letting the
-    initiator know of the error.
-
-    Warning:
-        This method has been essentially deprecated by :rfc:`2744`.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the security
-            context against which to process the token
-        token (bytes): the token to process
-
-    Raises:
-        ~gssapi.exceptions.InvalidTokenError
-        ~gssapi.exceptions.MissingContextError
-    """
-
     cdef gss_buffer_desc token_buffer = gss_buffer_desc(len(token), token)
 
     cdef OM_uint32 maj_stat, min_stat
@@ -561,21 +390,6 @@ def process_context_token(SecurityContext context not None, token):
 
 
 def import_sec_context(token not None):
-    """
-    import_sec_context(token)
-    Import a context from another process.
-
-    This method imports a security context established in another process
-    by reading the specified token which was output by
-    :func:`export_sec_context`.
-
-    Raises:
-        ~gssapi.exceptions.MissingContextError
-        ~gssapi.exceptions.InvalidTokenError
-        ~gssapi.exceptions.OperationUnavailableError
-        ~gssapi.exceptions.UnauthorizedError
-    """
-
     cdef gss_buffer_desc token_buffer = gss_buffer_desc(len(token), token)
 
     cdef gss_ctx_id_t ctx
@@ -594,29 +408,6 @@ def import_sec_context(token not None):
 
 
 def export_sec_context(SecurityContext context not None):
-    """
-    export_sec_context(context)
-    Export a context for use in another process.
-
-    This method exports a security context, deactivating in the current process
-    and creating a token which can then be imported into another process
-    with :func:`import_sec_context`.
-
-    Warning: this modifies the input context
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the context to send
-            to another process
-
-    Returns:
-        bytes: the output token to be imported
-
-    Raises:
-        ~gssapi.exceptions.ExpiredContextError
-        ~gssapi.exceptions.MissingContextError
-        ~gssapi.exceptions.OperationUnavailableError
-    """
-
     cdef gss_buffer_desc output_token = gss_buffer_desc(0, NULL)
 
     cdef OM_uint32 maj_stat, min_stat
@@ -634,33 +425,6 @@ def export_sec_context(SecurityContext context not None):
 
 
 def delete_sec_context(SecurityContext context not None, local_only=True):
-    """
-    delete_sec_context(context, local_only=True)
-    Delete a GSSAPI security context.
-
-    This method deletes a GSSAPI security context,
-    returning an output token to send to the other
-    holder of the security context to notify them
-    of the deletion.
-
-    Note:
-        This method generally should not be used.  :class:`SecurityContext`
-        objects will automatically be freed by Python.
-
-    Args:
-        context (~gssapi.raw.sec_contexts.SecurityContext): the security
-            context in question
-        local_only (bool): should we request local deletion (True), or also
-            remote deletion (False), in which case a token is also returned
-
-    Returns:
-        bytes: the output token (if remote deletion is requested).  Generally
-            this is None, but bytes for compatibility.
-
-    Raises:
-        ~gssapi.exceptions.MissingContextError
-    """
-
     cdef OM_uint32 maj_stat, min_stat
     # GSS_C_EMPTY_BUFFER
     cdef gss_buffer_desc output_token = gss_buffer_desc(0, NULL)
diff --git a/gssapi/raw/types.pyi b/gssapi/raw/types.pyi
new file mode 100644
index 00000000..8d928664
--- /dev/null
+++ b/gssapi/raw/types.pyi
@@ -0,0 +1,174 @@
+import numbers
+import typing as t
+
+from collections.abc import MutableSet
+from enum import IntEnum
+
+if t.TYPE_CHECKING:
+    from gssapi.raw.oids import OID
+
+
+class NameType:
+    """
+    GSSAPI Name Types
+
+    This enum-like object represents GSSAPI name
+    types (to be used with :func:`~gssapi.raw.names.import_name`, etc)
+    """
+    #: GSS_C_NT_ANONYMOUS 1.3.6.1.5.6.3
+    anonymous: "OID" = ...
+    #: GSS_C_NT_EXPORT_NAME 1.3.6.1.5.6.4
+    export: "OID" = ...
+    #: GSS_C_NT_HOSTBASED_SERVICE 1.2.840.113554.1.2.1.4
+    hostbased_service: "OID" = ...
+    #: GSS_C_NT_MACHINE_UID_NAME 1.2.840.113554.1.2.1.2
+    machine_uid: "OID" = ...
+    #: GSS_C_NT_STRING_UID_NAME 1.2.840.113554.1.2.1.3
+    string_uid: "OID" = ...
+    #: GSS_C_NT_USER_NAME 1.2.840.113554.1.2.1.1
+    user: "OID" = ...
+
+    # Provided through optional extensions
+    #: GSS_C_NT_COMPOSITE_EXPORT 1.3.6.1.5.6.6
+    composite_export: "OID" = ...
+    #: GSS_KRB5_NT_PRINCIPAL_NAME 1.2.840.113554.1.2.2.1
+    kerberos_principal: "OID" = ...
+    #: GSS_KRB5_NT_PRINCIPAL_NAME 1.2.840.113554.1.2.2.1
+    krb5_nt_principal_name: "OID" = ...
+
+
+class RequirementFlag(IntEnum):
+    """
+    GSSAPI Requirement Flags
+
+    This :class:`~enum.IntEnum` represents flags used with the
+    :class:`~gssapi.raw.sec_contexts.SecurityContext`-related methods (e.g.
+    :func:`~gssapi.raw.sec_contexts.init_sec_context`)
+
+    The numbers behind the values correspond directly
+    to their C counterparts.
+    """
+    # Note the values are only set here for documentation and type hints
+    delegate_to_peer = 1 #: GSS_C_DELEG_FLAG
+    mutual_authentication = 2 #: GSS_C_MUTUAL_FLAG
+    replay_detection = 4 #: GSS_C_REPLAY_FLAG
+    out_of_sequence_detection = 8 #: GSS_C_SEQUENCE_FLAG
+    confidentiality = 16 #: GSS_C_CONF_FLAG
+    integrity = 32 #: GSS_C_INTEG_FLAG
+    anonymity = 64 #: GSS_C_ANON_FLAG
+    protection_ready = 128 #: GSS_C_PROT_READY_FLAG
+    transferable = 256 #: GSS_C_TRANS_FLAG
+    channel_bound = 2048 #: GSS_C_CHANNEL_BOUND_FLAG
+    dce_style = 4096 #: GSS_C_DCE_STYLE
+    identify = 8192 #: GSS_C_IDENTIFY_FLAG
+    extended_error = 16384 #: GSS_C_EXTENDED_ERROR_FLAG
+    ok_as_delegate = 32768 #: GSS_C_DELEG_POLICY_FLAG
+
+
+class AddressType(IntEnum):
+    """
+    GSSAPI Channel Bindings Address Types
+
+    This :class:`~enum.IntEnum` represents the various address
+    types used with the :class:`~gssapi.raw.chan_bindings.ChannelBindings`
+    structure.
+
+    The numbers behind the values correspond directly
+    to their C counterparts.  There is no value for
+    ``GSS_C_AF_UNSPEC``, since this is represented
+    by ``None``.
+    """
+    # Note the values are only set here for documentation and type hints
+    local = 1 #: GSS_C_AF_LOCAL
+    ip = 2 #: GSS_C_AF_INET
+    arpanet = 3 #: GSS_C_AF_IMPLINK
+    pup = 4 #: GSS_C_AF_PUP
+    chaos = 5 #: GSS_C_AF_CHAOS
+    xerox_ns = 6 #: GSS_C_AF_NS
+    nbs = 7 #: GSS_C_AF_NBS
+    ecma = 8 #: GSS_C_AF_ECMA
+    datakit = 9 #: GSS_C_AF_DATAKIT
+    ccitt = 10 #: GSS_C_AF_CCITT
+    ibm_sna = 11 #: GSS_C_AF_SNA
+    decnet = 12 #: GSS_C_AF_DECnet
+    dli = 13 #: GSS_C_AF_DLI
+    lat = 14 #: GSS_C_AF_LAT
+    hyperchannel = 15 #: GSS_C_AF_HYLINK
+    appletalk = 16 #: GSS_C_AF_APPLETALK
+    bisync = 17 #: GSS_C_AF_BSC
+    dss = 18 #: GSS_C_AF_DSS
+    osi_tp4 = 19 #: GSS_C_AF_OSI
+    x25 = 21 #: GSS_C_AF_X25
+    null = 255 #: GSS_C_AF_NULLADDR
+
+
+class MechType:
+    """
+    GSSAPI Mechanism Types
+
+    This enum-like object contains any mechanism :class:`~gssapi.raw.oids.OID`
+    values registered by imported mechanisms.
+    """
+    kerberos: "OID" #: gss_mech_krb5 1.2.840.113554.1.2.2
+
+
+class GenericFlagSet(MutableSet):
+    """A set backed by a 32-bit integer
+
+    This is a set backed by a 32 bit integer.
+    the members are integers where only one
+    bit is set.
+
+    The class supports normal set operations,
+    as well as traditional "flag set" operations,
+    such as bitwise AND, OR, and XOR.
+    """
+
+    MAX_VAL: int
+
+    def __init__(
+        self,
+        flags: t.Optional[
+            t.Union[GenericFlagSet, numbers.Integral, int]
+        ] = None,
+    ) -> None: ...
+
+    def __contains__(
+        self,
+        flag: object,
+    ) -> bool: ...
+
+    def __iter__(self) -> t.Iterator[int]: ...
+
+    def __len__(self) -> int: ...
+
+    def add(
+        self,
+        flag: int,
+    ) -> None: ...
+
+    def discard(
+        self,
+        flag: int,
+    ) -> None: ...
+
+
+class IntEnumFlagSet(GenericFlagSet):
+    """A set backed by a 32-bit integer with enum members
+
+    This class is a :class:`GenericFlagSet` where the returned
+    members are values in an :class:`~enum.IntEnum`.
+
+    It functions exactly like a `GenericFlagSet`, except that
+    it also supports bitwise operations with the enum values.
+    """
+
+    def __init__(
+        self,
+        enum: t.Type[IntEnum],
+        flags: t.Optional[
+            t.Union[GenericFlagSet, numbers.Integral, int]
+        ] = None,
+    ) -> None: ...
+
+    def __iter__(self) -> t.Iterator[IntEnum]: ...
diff --git a/gssapi/raw/types.pyx b/gssapi/raw/types.pyx
index 322d6b16..37697a13 100644
--- a/gssapi/raw/types.pyx
+++ b/gssapi/raw/types.pyx
@@ -16,13 +16,6 @@ from collections.abc import MutableSet
 
 
 class NameType(object):
-    """
-    GSSAPI Name Types
-
-    This enum-like object represents GSSAPI name
-    types (to be used with :func:`import_name`, etc)
-    """
-
     # mech-agnostic name types
     hostbased_service = c_make_oid(GSS_C_NT_HOSTBASED_SERVICE)
     # NB(directxman12): skip GSS_C_NT_HOSTBASED_SERVICE_X since it's deprecated
@@ -36,17 +29,6 @@ class NameType(object):
 
 
 class RequirementFlag(IntEnum, metaclass=ExtendableEnum):
-    """
-    GSSAPI Requirement Flags
-
-    This :class:`~enum.IntEnum` represents flags used with the
-    :class:`SecurityContext`-related methods (e.g.
-    :func:`init_sec_context`)
-
-    The numbers behind the values correspond directly
-    to their C counterparts.
-    """
-
     delegate_to_peer = GSS_C_DELEG_FLAG
     mutual_authentication = GSS_C_MUTUAL_FLAG
     replay_detection = GSS_C_REPLAY_FLAG
@@ -68,18 +50,6 @@ class RequirementFlag(IntEnum, metaclass=ExtendableEnum):
 
 
 class AddressType(IntEnum, metaclass=ExtendableEnum):
-    """
-    GSSAPI Channel Bindings Address Types
-
-    This :class:`~enum.IntEnum` represents the various address
-    types used with the :class:`ChannelBindings` structure.
-
-    The numbers behind the values correspond directly
-    to their C counterparts.  There is no value for
-    ``GSS_C_AF_UNSPEC``, since this is represented
-    by ``None``.
-    """
-
     # unspecified = GSS_C_AF_UNSPEC  # None --> GSS_C_AF_UNSPEC
     local = GSS_C_AF_LOCAL
     ip = GSS_C_AF_INET
@@ -105,28 +75,12 @@ class AddressType(IntEnum, metaclass=ExtendableEnum):
 
 
 class MechType(object):
-    """
-    GSSAPI Mechanism Types
-
-    This enum-like object contains any mechanism :class:`OID`
-    values registered by imported mechanisms.
-    """
     pass
 
     # these are added in by the individual mechanism files on import
 
 
 class GenericFlagSet(MutableSet):
-    """A set backed by a 32-bit integer
-
-    This is a set backed by a 32 bit integer.
-    the members are integers where only one
-    bit is set.
-
-    The class supports normal set operations,
-    as well as traditional "flag set" operations,
-    such as bitwise AND, OR, and XOR.
-    """
 
     __slots__ = '_val'
     MAX_VAL = 1 << 31
@@ -221,14 +175,6 @@ class GenericFlagSet(MutableSet):
 
 
 class IntEnumFlagSet(GenericFlagSet):
-    """A set backed by a 32-bit integer with enum members
-
-    This class is a :class:`GenericFlagSet` where the returned
-    members are values in an :class:`~enum.IntEnum`.
-
-    It functions exactly like a `GenericFlagSet`, except that
-    it also supports bitwise operations with the enum values.
-    """
 
     __slots__ = ('_val', '_enum')
 
diff --git a/gssapi/sec_contexts.py b/gssapi/sec_contexts.py
index 80787ac4..97d54d03 100644
--- a/gssapi/sec_contexts.py
+++ b/gssapi/sec_contexts.py
@@ -1,6 +1,11 @@
+import typing as t
+
+from gssapi.raw import chan_bindings as rchan_bindings
 from gssapi.raw import sec_contexts as rsec_contexts
 from gssapi.raw import message as rmessage
 from gssapi.raw import named_tuples as tuples
+from gssapi.raw import names as rnames
+from gssapi.raw import oids as roids
 from gssapi.raw.types import RequirementFlag, IntEnumFlagSet
 
 import gssapi.exceptions as excs
@@ -24,18 +29,37 @@ class SecurityContext(rsec_contexts.SecurityContext,
     credentials object will not be preserved, however).
     """
 
-    def __new__(cls, base=None, token=None,
-                name=None, creds=None, lifetime=None, flags=None,
-                mech=None, channel_bindings=None, usage=None):
+    def __new__(
+        cls,
+        base: t.Optional[rsec_contexts.SecurityContext] = None,
+        token: t.Optional[bytes] = None,
+        name: t.Optional[rnames.Name] = None,
+        creds: t.Optional[Credentials] = None,
+        lifetime: t.Optional[int] = None,
+        flags: t.Optional[int] = None,
+        mech: t.Optional[roids.OID] = None,
+        channel_bindings: t.Optional[rchan_bindings.ChannelBindings] = None,
+        usage: t.Optional[str] = None,
+    ) -> "SecurityContext":
 
         if token is not None:
             base = rsec_contexts.import_sec_context(token)
 
-        return super(SecurityContext, cls).__new__(cls, base)
-
-    def __init__(self, base=None, token=None,
-                 name=None, creds=None, lifetime=None, flags=None,
-                 mech=None, channel_bindings=None, usage=None):
+        return t.cast("SecurityContext",
+                      super(SecurityContext, cls).__new__(cls, base))
+
+    def __init__(
+        self,
+        base: t.Optional[rsec_contexts.SecurityContext] = None,
+        token: t.Optional[bytes] = None,
+        name: t.Optional[rnames.Name] = None,
+        creds: t.Optional[Credentials] = None,
+        lifetime: t.Optional[int] = None,
+        flags: t.Optional[int] = None,
+        mech: t.Optional[roids.OID] = None,
+        channel_bindings: t.Optional[rchan_bindings.ChannelBindings] = None,
+        usage: t.Optional[str] = None,
+    ) -> None:
         """
         The constructor creates a new security context, but does not begin
         the initiate or accept process.
@@ -123,14 +147,17 @@ def __init__(self, base=None, token=None,
                 raise excs.UnknownUsageError(msg, obj="security context")
 
         # This is to work around an MIT krb5 bug (see the `complete` property)
-        self._complete = None
+        self._complete: t.Optional[bool] = None
 
     # NB(directxman12): DO NOT ADD AN __del__ TO THIS CLASS -- it screws up
     #                   the garbage collector if _last_tb is still defined
 
     # TODO(directxman12): implement flag properties
 
-    def get_signature(self, message):
+    def get_signature(
+        self,
+        message: bytes,
+    ) -> bytes:
         """Calculate the signature for a message.
 
         This method calculates the signature (called a MIC) for
@@ -154,7 +181,11 @@ def get_signature(self, message):
         # TODO(directxman12): check flags?
         return rmessage.get_mic(self, message)
 
-    def verify_signature(self, message, mic):
+    def verify_signature(
+        self,
+        message: bytes,
+        mic: bytes,
+    ) -> int:
         """Verify the signature for a message.
 
         This method verifies that a signature (generated by
@@ -167,6 +198,9 @@ def verify_signature(self, message, mic):
             message (bytes): the message
             mic (bytes): the signature to verify
 
+        Returns:
+            int: the QoP used.
+
         Raises:
             ~gssapi.exceptions.BadMICError: the signature was not valid
             ~gssapi.exceptions.InvalidTokenError
@@ -180,7 +214,11 @@ def verify_signature(self, message, mic):
 
         return rmessage.verify_mic(self, message, mic)
 
-    def wrap(self, message, encrypt):
+    def wrap(
+        self,
+        message: bytes,
+        encrypt: bool,
+    ) -> tuples.WrapResult:
         """Wrap a message, optionally with encryption
 
         This wraps a message, signing it and optionally
@@ -192,7 +230,7 @@ def wrap(self, message, encrypt):
 
         Returns:
             WrapResult: the wrapped message and details about it
-                (e.g. whether encryption was used succesfully)
+            (e.g. whether encryption was used succesfully)
 
         Raises:
             ~gssapi.exceptions.ExpiredContextError
@@ -202,7 +240,10 @@ def wrap(self, message, encrypt):
 
         return rmessage.wrap(self, message, encrypt)
 
-    def unwrap(self, message):
+    def unwrap(
+        self,
+        message: bytes,
+    ) -> tuples.UnwrapResult:
         """Unwrap a wrapped message.
 
         This method unwraps/unencrypts a wrapped message,
@@ -213,7 +254,7 @@ def unwrap(self, message):
 
         Returns:
             UnwrapResult: the unwrapped message and details about it
-                (e.g. wheter encryption was used)
+            (e.g. wheter encryption was used)
 
         Raises:
             ~gssapi.exceptions.InvalidTokenError
@@ -228,7 +269,10 @@ def unwrap(self, message):
 
         return rmessage.unwrap(self, message)
 
-    def encrypt(self, message):
+    def encrypt(
+        self,
+        message: bytes,
+    ) -> bytes:
         """Encrypt a message.
 
         This method wraps and encrypts a message, similarly to
@@ -258,7 +302,10 @@ def encrypt(self, message):
 
         return res.message
 
-    def decrypt(self, message):
+    def decrypt(
+        self,
+        message: bytes,
+    ) -> bytes:
         """Decrypt a message.
 
         This method decrypts and unwraps a message, verifying the signature
@@ -297,8 +344,11 @@ def decrypt(self, message):
 
         return res.message
 
-    def get_wrap_size_limit(self, desired_output_size,
-                            encrypted=True):
+    def get_wrap_size_limit(
+        self,
+        desired_output_size: int,
+        encrypted: bool = True,
+    ) -> int:
         """Calculate the maximum message size for a given wrapped message size.
 
         This method calculates the maximum input message size for a given
@@ -321,7 +371,10 @@ def get_wrap_size_limit(self, desired_output_size,
         return rmessage.wrap_size_limit(self, desired_output_size,
                                         encrypted)
 
-    def process_token(self, token):
+    def process_token(
+        self,
+        token: bytes,
+    ) -> None:
         """Process an output token asynchronously.
 
         This method processes an output token even when the security context
@@ -340,7 +393,7 @@ def process_token(self, token):
 
         rsec_contexts.process_context_token(self, token)
 
-    def export(self):
+    def export(self) -> bytes:
         """Export a security context.
 
         This method exports a security context, allowing it to be passed
@@ -361,7 +414,10 @@ def export(self):
                      'mech', 'flags', 'locally_init', 'complete')
 
     @_utils.check_last_err
-    def _inquire(self, **kwargs):
+    def _inquire(
+        self,
+        **kwargs: bool,
+    ) -> tuples.InquireContextResult:
         """Inspect the security context for information
 
         This method inspects the security context for information.
@@ -382,7 +438,7 @@ def _inquire(self, **kwargs):
 
         Returns:
             InquireContextResult: the results of the inquiry, with unused
-                fields set to None
+            fields set to None
 
         Raises:
             ~gssapi.exceptions.MissingContextError
@@ -415,12 +471,12 @@ def _inquire(self, **kwargs):
                                            res.complete)
 
     @property
-    def lifetime(self):
+    def lifetime(self) -> int:
         """The amount of time for which this context remains valid"""
         return rsec_contexts.context_time(self)
 
     @property
-    def delegated_creds(self):
+    def delegated_creds(self) -> t.Optional[Credentials]:
         """The credentials delegated from the initiator to the acceptor
 
         .. warning::
@@ -442,28 +498,32 @@ def delegated_creds(self):
     locally_initiated = _utils.inquire_property(
         'locally_init', 'Whether this context was locally intiated')
 
-    @property
+    @property  # type: ignore # https://github.com/python/mypy/issues/1362
     @_utils.check_last_err
-    def complete(self):
+    def complete(self) -> bool:
         """Whether negotiation for this context has been completed"""
         # NB(directxman12): MIT krb5 has a bug where it refuses to
         #                   inquire about partially completed contexts,
         #                   so we can't just use `self._inquire` generally
         if self._started:
-            if self._complete is None:
+            complete = self._complete
+            if complete is None:
                 try:
-                    res = self._inquire(complete=True).complete
+                    complete = self._inquire(complete=True).complete
                 except excs.MissingContextError:
                     return False
                 else:
-                    self._complete = res
+                    self._complete = complete
 
-            return self._complete
+            return complete
         else:
             return False
 
     @_utils.catch_and_return_token
-    def step(self, token=None):
+    def step(
+        self,
+        token: t.Optional[bytes] = None,
+    ) -> t.Optional[bytes]:
         """Perform a negotation step.
 
         This method performs a negotiation step based on the usage type
@@ -518,11 +578,14 @@ def step(self, token=None):
         """
 
         if self.usage == 'accept':
-            return self._acceptor_step(token=token)
+            return self._acceptor_step(token=token or b"")
         else:
             return self._initiator_step(token=token)
 
-    def _acceptor_step(self, token):
+    def _acceptor_step(
+        self,
+        token: bytes,
+    ) -> t.Optional[bytes]:
         res = rsec_contexts.accept_sec_context(token, self._creds,
                                                self, self._channel_bindings)
 
@@ -535,7 +598,10 @@ def _acceptor_step(self, token):
 
         return res.token
 
-    def _initiator_step(self, token=None):
+    def _initiator_step(
+        self,
+        token: t.Optional[bytes] = None,
+    ) -> t.Optional[bytes]:
         res = rsec_contexts.init_sec_context(self._target_name, self._creds,
                                              self, self._mech,
                                              self._desired_flags,
@@ -548,6 +614,8 @@ def _initiator_step(self, token=None):
         return res.token
 
     # pickle protocol support
-    def __reduce__(self):
+    def __reduce__(
+        self,
+    ) -> t.Tuple[t.Type["SecurityContext"], t.Tuple[None, bytes]]:
         # the unpickle arguments to new are (base=None, token=self.export())
         return (type(self), (None, self.export()))
diff --git a/gssapi/tests/test_high_level.py b/gssapi/tests/test_high_level.py
index badd597e..d7c43aaf 100644
--- a/gssapi/tests/test_high_level.py
+++ b/gssapi/tests/test_high_level.py
@@ -24,7 +24,7 @@
 SERVICE_PRINCIPAL = TARGET_SERVICE_NAME + b'/' + FQDN
 
 # disable error deferring to catch errors immediately
-gssctx.SecurityContext.__DEFER_STEP_ERRORS__ = False
+gssctx.SecurityContext.__DEFER_STEP_ERRORS__ = False  # type: ignore
 
 
 class _GSSAPIKerberosTestCase(kt.KerberosTestCase):
diff --git a/mypy.ini b/mypy.ini
new file mode 100644
index 00000000..71944250
--- /dev/null
+++ b/mypy.ini
@@ -0,0 +1,31 @@
+[mypy]
+exclude = (?x)(
+    setup.py
+    | docs/     # doc files
+    | build/    # temp build folder
+  )
+show_error_codes = True
+show_column_numbers = True
+disallow_any_unimported = true
+disallow_untyped_calls = true
+disallow_untyped_defs = true
+disallow_incomplete_defs = true
+check_untyped_defs = true
+disallow_untyped_decorators = true
+warn_redundant_casts = true
+warn_unused_ignores = true
+
+[mypy-gssapi.tests.*]
+disallow_any_unimported = false
+disallow_untyped_calls = false
+disallow_untyped_defs = false
+check_untyped_defs = false
+
+[mypy-k5test]
+ignore_missing_imports = True
+
+[mypy-k5test.unit]
+ignore_missing_imports = True
+
+[mypy-parameterized]
+ignore_missing_imports = True
diff --git a/setup.py b/setup.py
index 1daa7438..eba32494 100755
--- a/setup.py
+++ b/setup.py
@@ -349,6 +349,10 @@ def gssapi_modules(lst):
     author_email='jborean93@gmail.com',
     packages=['gssapi', 'gssapi.raw', 'gssapi.raw._enum_extensions',
               'gssapi.tests'],
+    package_data={
+        "gssapi": ["py.typed"],
+        "gssapi.raw": ["*.pyi"],
+    },
     description='Python GSSAPI Wrapper',
     long_description=long_desc,
     license='LICENSE.txt',
diff --git a/test-requirements.txt b/test-requirements.txt
index c0a63b3a..5085d282 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,3 +3,5 @@ parameterized
 Cython
 k5test
 decorator
+mypy
+types-decorator
\ No newline at end of file