Skip to content

Commit be83ff9

Browse files
author
Gauvain Pocentek
committed
Rework the API documentation
Update the sphinx extension to add method definition in the docs. This makes the documentation a bit more usable. Hide attributes that should not have been exposed. They still exist in the code but their documentation doesn't make much sense.
1 parent 9f7f45f commit be83ff9

File tree

6 files changed

+146
-79
lines changed

6 files changed

+146
-79
lines changed

docs/api/gitlab.rst

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ gitlab.objects module
2828
:show-inheritance:
2929
:exclude-members: Branch, Commit, Content, Event, File, Hook, Issue, Key,
3030
Label, Member, MergeRequest, Milestone, Note, Snippet,
31-
Tag
31+
Tag, canGet, canList, canUpdate, canCreate, canDelete,
32+
requiredUrlAttrs, requiredListAttrs, optionalListAttrs,
33+
optionalGetAttrs, requiredGetAttrs, requiredDeleteAttrs,
34+
requiredCreateAttrs, optionalCreateAttrs,
35+
requiredUpdateAttrs, optionalUpdateAttrs, getRequiresId,
36+
shortPrintAttr, idAttr

docs/ext/docstrings.py

+30-49
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
from sphinx.ext.napoleon.docstring import GoogleDocstring
99

1010

11+
def classref(value, short=True):
12+
tilde = '~' if short else ''
13+
return ':class:`%sgitlab.objects.%s`' % (tilde, value.__name__)
14+
15+
1116
def setup(app):
1217
app.connect('autodoc-process-docstring', _process_docstring)
1318
app.connect('autodoc-skip-member', napoleon._skip_member)
@@ -28,58 +33,34 @@ def _process_docstring(app, what, name, obj, options, lines):
2833

2934

3035
class GitlabDocstring(GoogleDocstring):
31-
def _build_doc(self):
32-
cls = self._obj.obj_cls
33-
opt_get_list = cls.optionalGetAttrs
34-
opt_list_list = cls.optionalListAttrs
35-
md_create_list = list(itertools.chain(cls.requiredUrlAttrs,
36-
cls.requiredCreateAttrs))
37-
opt_create_list = cls.optionalCreateAttrs
38-
39-
opt_get_keys = "None"
40-
if opt_get_list:
41-
opt_get_keys = ", ".join(['``%s``' % i for i in opt_get_list])
42-
43-
opt_list_keys = "None"
44-
if opt_list_list:
45-
opt_list_keys = ", ".join(['``%s``' % i for i in opt_list_list])
46-
47-
md_create_keys = opt_create_keys = "None"
48-
if md_create_list:
49-
md_create_keys = ", ".join(['``%s``' % i for i in md_create_list])
50-
if opt_create_list:
51-
opt_create_keys = ", ".join(['``%s``' % i for i in
52-
opt_create_list])
53-
54-
md_update_list = list(itertools.chain(cls.requiredUrlAttrs,
55-
cls.requiredUpdateAttrs))
56-
opt_update_list = cls.optionalUpdateAttrs
57-
58-
md_update_keys = opt_update_keys = "None"
59-
if md_update_list:
60-
md_update_keys = ", ".join(['``%s``' % i for i in md_update_list])
61-
if opt_update_list:
62-
opt_update_keys = ", ".join(['``%s``' % i for i in
63-
opt_update_list])
64-
65-
tmpl_file = os.path.join(os.path.dirname(__file__), 'template.j2')
66-
with open(tmpl_file) as fd:
67-
template = jinja2.Template(fd.read(), trim_blocks=False)
68-
output = template.render(filename=tmpl_file,
69-
cls=cls,
70-
md_create_keys=md_create_keys,
71-
opt_create_keys=opt_create_keys,
72-
md_update_keys=md_update_keys,
73-
opt_update_keys=opt_update_keys,
74-
opt_get_keys=opt_get_keys,
75-
opt_list_keys=opt_list_keys)
36+
_j2_env = None
37+
38+
def _build_j2_env(self):
39+
if self._j2_env is None:
40+
self._j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(
41+
os.path.dirname(__file__)), trim_blocks=False)
42+
self._j2_env.filters['classref'] = classref
43+
44+
return self._j2_env
45+
46+
def _build_manager_doc(self):
47+
env = self._build_j2_env()
48+
template = env.get_template('manager_tmpl.j2')
49+
output = template.render(cls=self._obj.obj_cls)
50+
51+
return output.split('\n')
52+
53+
def _build_object_doc(self):
54+
env = self._build_j2_env()
55+
template = env.get_template('object_tmpl.j2')
56+
output = template.render(obj=self._obj)
7657

7758
return output.split('\n')
7859

7960
def __init__(self, *args, **kwargs):
8061
super(GitlabDocstring, self).__init__(*args, **kwargs)
8162

82-
if not hasattr(self._obj, 'obj_cls') or self._obj.obj_cls is None:
83-
return
84-
85-
self._parsed_lines = self._build_doc()
63+
if hasattr(self._obj, 'obj_cls') and self._obj.obj_cls is not None:
64+
self._parsed_lines = self._build_manager_doc()
65+
elif hasattr(self._obj, 'canUpdate') and self._obj.canUpdate:
66+
self._parsed_lines = self._build_object_doc()

docs/ext/manager_tmpl.j2

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
Manager for {{ cls | classref() }} objects.
2+
3+
{% if cls.canUpdate %}
4+
{{ cls | classref() }} objects can be updated.
5+
{% else %}
6+
{{ cls | classref() }} objects **cannot** be updated.
7+
{% endif %}
8+
9+
{% if cls.canList %}
10+
.. method:: list(**kwargs)
11+
12+
Returns a list of objects of type {{ cls | classref() }}.
13+
14+
Available keys for ``kwargs`` are:
15+
16+
{% for k in cls.requiredListAttrs %}
17+
* ``{{ k }}`` (required)
18+
{% endfor %}
19+
{% for k in cls.optionalListAttrs %}
20+
* ``{{ k }}`` (optional)
21+
{% endfor %}
22+
* ``per_page`` (int): number of item per page. May be limited by the server.
23+
* ``page`` (int): page to retrieve
24+
* ``all`` (bool): iterate over all the pages and return all the entries
25+
* ``sudo`` (string or int): run the request as another user (requires admin
26+
permissions)
27+
{% endif %}
28+
29+
{% if cls.canGet %}
30+
{% if cls.getRequiresId %}
31+
.. method:: get(id, **kwargs)
32+
33+
Get a single object of type {{ cls | classref() }} using its ``id``.
34+
{% else %}
35+
.. method:: get(**kwargs)
36+
37+
Get a single object of type {{ cls | classref() }}.
38+
{% endif %}
39+
40+
Available keys for ``kwargs`` are:
41+
42+
{% for k in cls.requiredGetAttrs %}
43+
* ``{{ k }}`` (required)
44+
{% endfor %}
45+
{% for k in cls.optionalGetAttrs %}
46+
* ``{{ k }}`` (optional)
47+
{% endfor %}
48+
* ``sudo`` (string or int): run the request as another user (requires admin
49+
permissions)
50+
{% endif %}
51+
52+
{% if cls.canCreate %}
53+
.. method:: create(data, **kwargs)
54+
55+
Create an object of type {{ cls | classref() }}.
56+
57+
``data`` is a dict defining the object attributes. Available attributes are:
58+
59+
{% for a in cls.requiredUrlAttrs %}
60+
* ``{{ a }}`` (required)
61+
{% endfor %}
62+
{% for a in cls.requiredUrlAttrs %}
63+
* ``{{ a }}`` (required if not discovered on the parent objects)
64+
{% endfor %}
65+
{% for a in cls.optionalCreateAttrs %}
66+
* ``{{ a }}`` (optional)
67+
{% endfor %}
68+
69+
Available keys for ``kwargs`` are:
70+
71+
* ``sudo`` (string or int): run the request as another user (requires admin
72+
permissions)
73+
{% endif %}
74+
75+
{% if cls.canDelete %}
76+
.. method:: delete(id, **kwargs)
77+
78+
Delete the object with ID ``id``.
79+
80+
Available keys for ``kwargs`` are:
81+
82+
* ``sudo`` (string or int): run the request as another user (requires admin
83+
permissions)
84+
{% endif %}

docs/ext/object_tmpl.j2

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
.. method:: save(**kwargs)
2+
3+
Send the modified object to the GitLab server. The following attributes are
4+
sent:
5+
6+
{% if obj.requiredUpdateAttrs or obj.optionalUpdateAttrs %}
7+
{% for a in obj.requiredUpdateAttrs %}
8+
* ``{{ a }}`` (required)
9+
{% endfor %}
10+
{% for a in obj.optionalUpdateAttrs %}
11+
* ``{{ a }}`` (optional)
12+
{% endfor %}
13+
{% else %}
14+
{% for a in obj.requiredCreateAttrs %}
15+
* ``{{ a }}`` (required)
16+
{% endfor %}
17+
{% for a in obj.optionalCreateAttrs %}
18+
* ``{{ a }}`` (optional)
19+
{% endfor %}
20+
{% endif %}
21+
22+
Available keys for ``kwargs`` are:
23+
24+
* ``sudo`` (string or int): run the request as another user (requires admin
25+
permissions)

docs/ext/template.j2

-29
This file was deleted.

test-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ httmock
66
jinja2
77
mock
88
sphinx>=1.3
9+
sphinx_rtd_theme

0 commit comments

Comments
 (0)