Skip to content

Commit 9bc6a81

Browse files
committed
High-Level Documentation Updates
This commit updates the high-level documentation. Typos were corrected, improvements were made for readability, and more links were inserted. Additionally, two custom Sphinx extensions were added to help with the process: The first extension catches unknown class references and attempts to track them down. The class is searched for as if it were an `:any:` reference. The results from this searched are used, prefering results in the current API level (high-level vs low-level). The second extension adds a convinience role, `:requires-ext`, which inserts a link and some text indicating that a particular extension is required. If the extension is an RFC, a link to the RFC is generated, otherwise, a link to the low-level API module is generated. In the latter case, the text of the link is generated using the first line of the docstring of the low-level module, if it is present. Otherwise, the partial name of the module is used (the '%s' part of 'ext_%s') Finally, as per above, the docstrings of several extensions were updated.
1 parent e59265d commit 9bc6a81

File tree

12 files changed

+346
-126
lines changed

12 files changed

+346
-126
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import re
2+
from docutils import nodes
3+
from sphinx.util.nodes import make_refnode
4+
5+
MATCH_RE_RAW = r'\b(([A-Z][A-Za-z0-9]+)+)\b'
6+
7+
def setup(app):
8+
app.connect('missing-reference', _missing_ref)
9+
10+
11+
def _missing_ref(app, env, node, contnode):
12+
# skip non-elements
13+
if not isinstance(contnode, nodes.Element):
14+
return
15+
16+
if node.get('refdomain') != 'py':
17+
return
18+
19+
options = env.domains['py'].find_obj(env, None, None, node.get('reftarget'), node.get('reftype'), 1)
20+
if not options:
21+
return
22+
23+
is_raw = node.get('py:module').startswith('gssapi.raw')
24+
25+
if len(options) > 1:
26+
raw_opts = []
27+
non_raw_opts = []
28+
for opt in options:
29+
full_name, type_info = opt
30+
mod_name, _mod_type = type_info
31+
if mod_name.startswith('gssapi.raw'):
32+
raw_opts.append(opt)
33+
else:
34+
non_raw_opts.append(opt)
35+
36+
if is_raw:
37+
if raw_opts:
38+
choice = raw_opts[0]
39+
elif non_raw_opts:
40+
choice = non_raw_opts[0]
41+
else:
42+
return
43+
else:
44+
if non_raw_opts:
45+
choice = non_raw_opts[0]
46+
elif raw_opts:
47+
choice = raw_opts[0]
48+
else:
49+
return
50+
else:
51+
choice = options[0]
52+
53+
choice_name, choice_info = choice
54+
choice_mod, choice_type = choice_info
55+
56+
if choice_type == 'module':
57+
return env.domains['py']._make_module_refnode(app.builder, node.get('refdoc'), choice_name, contnode)
58+
else:
59+
return make_refnode(app.builder, node.get('refdoc'), choice_mod, choice_name, contnode, choice_name)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import sys
2+
3+
from docutils import nodes, statemachine
4+
from docutils.parsers.rst.directives import admonitions
5+
from docutils.parsers.rst.roles import set_classes
6+
from docutils.parsers.rst import roles
7+
from sphinx.domains import python as py_domain
8+
9+
def setup(app):
10+
app.add_role('requires-ext', RequiresExtRole(app))
11+
12+
13+
class RequiresExtRole(object):
14+
def __init__(self, app):
15+
self.app = app
16+
17+
def __call__(self, name, rawtext, text, lineno, inliner,
18+
options={}, content=[]):
19+
if text.startswith('rfc'):
20+
rfc_text = text[3:]
21+
22+
rfc_node, rfc_msg = roles.rfc_reference_role(
23+
'rfc', ':rfc:`%s`' % rfc_text, rfc_text, lineno,
24+
inliner, options, content)
25+
26+
if rfc_msg:
27+
# error
28+
return (rfc_node, rfc_message)
29+
else:
30+
middle_parts = rfc_node + [nodes.Text(" extension",
31+
" extension")]
32+
else:
33+
ext_name = 'gssapi.raw.ext_%s' % text
34+
# autodoc has already imported everything
35+
try:
36+
ext_module = sys.modules[ext_name]
37+
except KeyError:
38+
ext_title = text + " extension"
39+
else:
40+
if ext_module.__doc__:
41+
ext_title = ext_module.__doc__.splitlines()[0]
42+
else:
43+
ext_title = text + " extension"
44+
ref_nodes, ref_messages = self.app.env.domains['py'].role('mod')(
45+
'mod', rawtext, ext_name, lineno, inliner)
46+
47+
if ref_messages:
48+
# error
49+
return (ref_nodes, ref_messages)
50+
51+
title_node = nodes.Text(ext_title, ext_title)
52+
53+
ref_nodes[0].children = [title_node]
54+
55+
middle_parts = ref_nodes
56+
57+
begin_text = nodes.Text("requires the ", "requires the ")
58+
59+
main_nodes = [begin_text] + middle_parts
60+
wrapper_node = nodes.emphasis('', '', *main_nodes)
61+
62+
return ([nodes.Text('', ''), wrapper_node, nodes.Text('', '')], [])

docs/source/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#sys.path.insert(0, os.path.abspath('.'))
2020

2121
sys.path.insert(0, os.path.abspath('../..'))
22+
sys.path.insert(0, os.path.abspath('../custom_extensions'))
2223

2324
# -- General configuration -----------------------------------------------------
2425

@@ -27,7 +28,7 @@
2728

2829
# Add any Sphinx extension module names here, as strings. They can be extensions
2930
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
30-
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', "sphinxcontrib.napoleon"]
31+
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', "sphinxcontrib.napoleon", 'gssapi_find_missing', 'requires_rfc']
3132

3233
# Add any paths that contain templates here, relative to this directory.
3334
templates_path = ['_templates']

docs/source/gssapi.raw.rst

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
Low-Level API
22
=============
33

4-
The low-level API contains a variety of functions that map directly to the
5-
corresponding C functions. Additionally, it contains several basic wrapper
6-
classes that wrap underlying C structs and automatically deallocate them
7-
when the Python object itself is deallocated.
4+
.. py:module:: gssapi.raw
5+
6+
The low-level API contains a variety of Python functions that map directly
7+
to the corresponding C functions. Additionally, it contains several basic
8+
wrapper classes that wrap underlying C structs and automatically deallocate
9+
them when the Python object itself is deallocated.
10+
11+
.. warning::
12+
13+
All methods in both the high-level and low-level APIs may throw the generic
14+
GSSError exception.
815

916
Core RFC 2744
1017
-------------
@@ -53,14 +60,16 @@ Misc
5360
:members:
5461
:undoc-members:
5562

56-
Extensions
57-
----------
63+
Additional RFCs and Extensions
64+
------------------------------
5865

5966
The following is a list of GSSAPI extensions supported by the low-level API.
60-
Ones supported by the high-level API are marked as such. Note that while
61-
all of these extensions have bindings, they may not be supported by your
62-
particularly GSSAPI implementation, in which case they will simply not be
63-
compiled.
67+
68+
.. note::
69+
While all of these extensions have bindings, they may not be supported
70+
by your particularly GSSAPI implementation. In this case, they will not
71+
be compiled, and will simply not be available in the :mod:`gssapi.raw`
72+
namespace.
6473

6574
:rfc:`5588` (GSS-API Extension for Storing Delegated Credentials)
6675
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

docs/source/gssapi.rst

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
11
High-Level API
22
==============
33

4+
.. py:module:: gssapi
5+
46
The high-level API contains three main classes for interacting with GSSAPI,
57
representing the primary abstractions that GSSAPI provides:
68
:class:`~gssapi.names.Name`, :class:`~gssapi.creds.Credentials`, and
7-
:class:`~gssapi.sec_contexts.SecurityContext`. Note that classes in
8-
the high-level API inherit from the corresponding classes in the
9-
low-level API, and thus may be passed in to low-level API functions.
9+
:class:`~gssapi.sec_contexts.SecurityContext`.
10+
11+
.. note::
12+
13+
Classes in the high-level API inherit from the corresponding classes in the
14+
low-level API, and thus may be passed in to low-level API functions.
15+
16+
.. warning::
17+
18+
All methods in both the high-level and low-level APIs may throw the generic
19+
GSSError exception.
1020

1121
Main Classes
1222
------------
1323

1424
.. automodule:: gssapi.names
1525
:members:
1626
:undoc-members:
17-
:inherited-members:
1827

1928
.. automodule:: gssapi.creds
2029
:members:
2130
:undoc-members:
22-
:inherited-members:
2331

2432
.. automodule:: gssapi.sec_contexts
2533
:members:
2634
:undoc-members:
27-
:inherited-members:
2835

2936
Enums and Helper Classes
3037
------------------------
@@ -33,43 +40,37 @@ The following enumerations from the low-level API are also
3340
used with the high-level API. For convienience, the are
3441
imported in the high-level API :mod:`gssapi` module:
3542

36-
.. autoclass:: gssapi.raw.types.NameType
43+
.. autoclass:: gssapi.NameType
3744
:members:
3845
:undoc-members:
3946
:show-inheritance:
40-
:noindex:
4147

42-
.. autoclass:: gssapi.raw.types.MechType
48+
.. autoclass:: gssapi.MechType
4349
:members:
4450
:undoc-members:
4551
:show-inheritance:
46-
:noindex:
4752

4853
.. TODO(directxman12): Sphinx doesn't document enums properly yet,
4954
so we need to figure out how to document them.
5055
51-
.. autoclass:: gssapi.raw.types.RequirementFlag
56+
.. autoclass:: gssapi.RequirementFlag
5257
:show-inheritance:
53-
:noindex:
5458

55-
.. autoclass:: gssapi.raw.types.AddressType
59+
.. autoclass:: gssapi.AddressType
5660
:show-inheritance:
57-
:noindex:
5861

5962
Similiarly, there are a couple classes from the low-level API
6063
that are imported into the high-level API module. These classes
6164
are less likely to be used directly by a user, but are returned
6265
by several methods:
6366

64-
.. autoclass:: gssapi.raw.oids.OID
67+
.. autoclass:: gssapi.OID
6568
:members:
66-
:noindex:
6769

68-
.. autoclass:: gssapi.raw.types.IntEnumFlagSet
70+
.. autoclass:: gssapi.IntEnumFlagSet
6971
:members:
7072
:undoc-members:
7173
:show-inheritance:
72-
:noindex:
7374

7475
Exceptions
7576
----------
@@ -82,3 +83,8 @@ can raise in addition to several other high-level-specific exceptions:
8283
:undoc-members:
8384
:show-inheritance:
8485
:imported-members:
86+
87+
Utilities
88+
---------
89+
90+
.. autofunction:: gssapi.set_encoding

gssapi/__init__.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
"""High-Level GSSAPI Bindings
2+
3+
The high-level API contains three main classes, which represent
4+
the primary abstractions that GSSAPI provides:
5+
6+
Name (see gssapi.names)
7+
8+
Credentials (see gssapi.creds)
9+
10+
SecurityContext (see gssapi.sec_contexts)
11+
12+
Additionally, a number of helper classes shared with the low-level API
13+
exist as well:
14+
15+
Enums (see gssapi.raw.types) --
16+
NameType, RequirementFlag, AddressType, MechType
17+
18+
IntEnumFlagSet (see gssapi.raw.types)
19+
20+
OID (see gssapi.raw.oids)
21+
22+
Note:
23+
24+
Classes in the high-level API inherit from the corresponding
25+
classes in the low-level API, and thus may be passed in to
26+
low-level API functions.
27+
"""
28+
129
from gssapi.raw.types import NameType, RequirementFlag, AddressType # noqa
230
from gssapi.raw.types import MechType, IntEnumFlagSet # noqa
331
from gssapi.raw.oids import OID # noqa
@@ -7,5 +35,3 @@
735
from gssapi.sec_contexts import SecurityContext # noqa
836

937
from gssapi._utils import set_encoding # noqa
10-
11-
"""The High-Level GSSAPI Wrapper"""

0 commit comments

Comments
 (0)