From 02924a1c3e4eedf481735f354addab4759d005a2 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Mon, 7 Feb 2022 17:02:29 +1000 Subject: [PATCH] Add Python type annotation Signed-off-by: Jordan Borean --- ci/build.sh | 6 + docs-requirements.txt | 1 + docs/source/conf.py | 67 +++++- docs/source/gssapi.raw.rst | 62 ++--- gssapi/_utils.py | 79 ++++--- gssapi/_win_config.py | 25 +- gssapi/creds.py | 143 ++++++++---- gssapi/exceptions.py | 15 +- gssapi/mechs.py | 65 ++++-- gssapi/names.py | 151 ++++++++---- gssapi/py.typed | 0 gssapi/raw/_enum_extensions/__init__.py | 17 +- gssapi/raw/chan_bindings.pyi | 30 +++ gssapi/raw/chan_bindings.pyx | 16 -- gssapi/raw/creds.pyi | 186 +++++++++++++++ gssapi/raw/creds.pyx | 137 ----------- gssapi/raw/exceptions.pyi | 67 ++++++ gssapi/raw/ext_cred_imp_exp.pyi | 44 ++++ gssapi/raw/ext_cred_imp_exp.pyx | 35 --- gssapi/raw/ext_cred_store.pyi | 136 +++++++++++ gssapi/raw/ext_cred_store.pyx | 105 --------- gssapi/raw/ext_dce.pyi | 187 +++++++++++++++ gssapi/raw/ext_dce.pyx | 99 -------- gssapi/raw/ext_dce_aead.pyi | 61 +++++ gssapi/raw/ext_dce_aead.pyx | 46 ---- gssapi/raw/ext_ggf.pyi | 97 ++++++++ gssapi/raw/ext_ggf.pyx | 81 ------- gssapi/raw/ext_iov_mic.pyi | 90 ++++++++ gssapi/raw/ext_iov_mic.pyx | 69 ------ gssapi/raw/ext_krb5.pyi | 280 ++++++++++++++++++++++ gssapi/raw/ext_krb5.pyx | 218 ------------------ gssapi/raw/ext_password.pyi | 41 ++++ gssapi/raw/ext_password.pyx | 29 --- gssapi/raw/ext_password_add.pyi | 48 ++++ gssapi/raw/ext_password_add.pyx | 35 --- gssapi/raw/ext_rfc4178.pyi | 27 +++ gssapi/raw/ext_rfc4178.pyx | 19 -- gssapi/raw/ext_rfc5587.pyi | 63 +++++ gssapi/raw/ext_rfc5587.pyx | 48 ---- gssapi/raw/ext_rfc5588.pyi | 42 ++++ gssapi/raw/ext_rfc5588.pyx | 29 --- gssapi/raw/ext_rfc5801.pyi | 39 ++++ gssapi/raw/ext_rfc5801.pyx | 28 --- gssapi/raw/ext_rfc6680.pyi | 169 ++++++++++++++ gssapi/raw/ext_rfc6680.pyx | 138 ----------- gssapi/raw/ext_rfc6680_comp_oid.pyi | 0 gssapi/raw/ext_s4u.pyi | 86 +++++++ gssapi/raw/ext_s4u.pyx | 66 ------ gssapi/raw/ext_set_cred_opt.pyi | 50 ++++ gssapi/raw/ext_set_cred_opt.pyx | 41 ---- gssapi/raw/mech_krb5.pyi | 0 gssapi/raw/message.pyi | 156 +++++++++++++ gssapi/raw/misc.pyi | 166 +++++++++++++ gssapi/raw/misc.pyx | 118 ---------- gssapi/raw/named_tuples.py | 37 +-- gssapi/raw/names.pyi | 170 ++++++++++++++ gssapi/raw/names.pyx | 137 ----------- gssapi/raw/oids.pyi | 50 ++++ gssapi/raw/oids.pyx | 36 --- gssapi/raw/sec_contexts.pyi | 294 ++++++++++++++++++++++++ gssapi/raw/sec_contexts.pyx | 236 ------------------- gssapi/raw/types.pyi | 174 ++++++++++++++ gssapi/raw/types.pyx | 54 ----- gssapi/sec_contexts.py | 140 ++++++++--- gssapi/tests/test_high_level.py | 2 +- mypy.ini | 31 +++ setup.py | 4 + test-requirements.txt | 2 + 68 files changed, 3356 insertions(+), 2064 deletions(-) create mode 100644 gssapi/py.typed create mode 100644 gssapi/raw/chan_bindings.pyi create mode 100644 gssapi/raw/creds.pyi create mode 100644 gssapi/raw/exceptions.pyi create mode 100644 gssapi/raw/ext_cred_imp_exp.pyi create mode 100644 gssapi/raw/ext_cred_store.pyi create mode 100644 gssapi/raw/ext_dce.pyi create mode 100644 gssapi/raw/ext_dce_aead.pyi create mode 100644 gssapi/raw/ext_ggf.pyi create mode 100644 gssapi/raw/ext_iov_mic.pyi create mode 100644 gssapi/raw/ext_krb5.pyi create mode 100644 gssapi/raw/ext_password.pyi create mode 100644 gssapi/raw/ext_password_add.pyi create mode 100644 gssapi/raw/ext_rfc4178.pyi create mode 100644 gssapi/raw/ext_rfc5587.pyi create mode 100644 gssapi/raw/ext_rfc5588.pyi create mode 100644 gssapi/raw/ext_rfc5801.pyi create mode 100644 gssapi/raw/ext_rfc6680.pyi create mode 100644 gssapi/raw/ext_rfc6680_comp_oid.pyi create mode 100644 gssapi/raw/ext_s4u.pyi create mode 100644 gssapi/raw/ext_set_cred_opt.pyi create mode 100644 gssapi/raw/mech_krb5.pyi create mode 100644 gssapi/raw/message.pyi create mode 100644 gssapi/raw/misc.pyi create mode 100644 gssapi/raw/names.pyi create mode 100644 gssapi/raw/oids.pyi create mode 100644 gssapi/raw/sec_contexts.pyi create mode 100644 gssapi/raw/types.pyi create mode 100644 mypy.ini 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




pFad - Phonifier reborn



Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy