Skip to content

Commit 4e3403a

Browse files
author
Sam Kleinman
committed
meta: mongodb domain for sphinx, and other minor non-textual changes
1 parent 71955f6 commit 4e3403a

File tree

4 files changed

+229
-8
lines changed

4 files changed

+229
-8
lines changed

.ext/mongodb_docs.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
MongoDB Domain for Sphinx
4+
~~~~~~~~~~~~~~~~~~~~~~~~~
5+
6+
Based on the default JavaScript domain distributed with Sphinx.
7+
8+
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
9+
:license: BSD, see LICENSE for details.
10+
11+
Additional work to adapt for MongoDB purposes done by 10gen,
12+
inc. (Sam Kleinman, et al.)
13+
"""
14+
15+
from sphinx import addnodes
16+
from sphinx.domains import Domain, ObjType
17+
from sphinx.locale import l_, _
18+
from sphinx.directives import ObjectDescription
19+
from sphinx.roles import XRefRole
20+
from sphinx.domains.python import _pseudo_parse_arglist
21+
from sphinx.util.nodes import make_refnode
22+
from sphinx.util.docfields import Field, GroupedField, TypedField
23+
24+
25+
class MongoDBObject(ObjectDescription):
26+
"""
27+
Description of a MongoDB object.
28+
"""
29+
#: If set to ``True`` this object is callable and a `desc_parameterlist` is
30+
#: added
31+
has_arguments = False
32+
33+
#: what is displayed right before the documentation entry
34+
display_prefix = None
35+
36+
def handle_signature(self, sig, signode):
37+
sig = sig.strip()
38+
if '(' in sig and sig[-1:] == ')':
39+
prefix, arglist = sig.split('(', 1)
40+
prefix = prefix.strip()
41+
arglist = arglist[:-1].strip()
42+
else:
43+
prefix = sig
44+
arglist = None
45+
if '.' in prefix:
46+
nameprefix, name = prefix.rsplit('.', 1)
47+
else:
48+
nameprefix = None
49+
name = prefix
50+
51+
objectname = self.env.temp_data.get('mongodb:object')
52+
if nameprefix:
53+
if objectname:
54+
# someone documenting the method of an attribute of the current
55+
# object? shouldn't happen but who knows...
56+
nameprefix = objectname + '.' + nameprefix
57+
fullname = nameprefix + '.' + name
58+
elif objectname:
59+
fullname = objectname + '.' + name
60+
else:
61+
# just a function or constructor
62+
objectname = ''
63+
fullname = name
64+
65+
signode['object'] = objectname
66+
signode['fullname'] = fullname
67+
68+
if self.display_prefix:
69+
signode += addnodes.desc_annotation(self.display_prefix,
70+
self.display_prefix)
71+
if nameprefix:
72+
signode += addnodes.desc_addname(nameprefix + '.', nameprefix + '.')
73+
signode += addnodes.desc_name(name, name)
74+
if self.has_arguments:
75+
if not arglist:
76+
signode += addnodes.desc_parameterlist()
77+
else:
78+
_pseudo_parse_arglist(signode, arglist)
79+
return fullname, nameprefix
80+
81+
def add_target_and_index(self, name_obj, sig, signode):
82+
objectname = self.options.get(
83+
'object', self.env.temp_data.get('mongodb:object'))
84+
fullname = name_obj[0]
85+
if fullname not in self.state.document.ids:
86+
signode['names'].append(fullname)
87+
signode['ids'].append(fullname.replace('$', '_S_'))
88+
signode['first'] = not self.names
89+
self.state.document.note_explicit_target(signode)
90+
objects = self.env.domaindata['mongodb']['objects']
91+
# if fullname in objects:
92+
# self.state_machine.reporter.warning(
93+
# 'duplicate object description of %s, ' % fullname +
94+
# 'other instance in ' +
95+
# self.env.doc2path(objects[fullname][0]),
96+
# line=self.lineno)
97+
objects[fullname] = self.env.docname, self.objtype
98+
99+
indextext = self.get_index_text(objectname, name_obj)
100+
if indextext:
101+
self.indexnode['entries'].append(('single', indextext,
102+
fullname.replace('$', '_S_'),
103+
''))
104+
105+
def get_index_text(self, objectname, name_obj):
106+
name, obj = name_obj
107+
if self.objtype == 'command':
108+
return _('%s (database command)') % name
109+
elif self.objtype == 'operator':
110+
return _('%s (operator)') % name
111+
elif self.objtype == 'setting':
112+
return _('%s (setting)') % (name)
113+
elif self.objtype == 'status':
114+
return _('%s (status)') % (name)
115+
return ''
116+
117+
class MongoDBCallable(MongoDBObject):
118+
"""Description of a JavaScript function, method or constructor."""
119+
has_arguments = False
120+
121+
doc_field_types = [
122+
TypedField('arguments', label=l_('Arguments'),
123+
names=('argument', 'arg', 'parameter', 'param'),
124+
typerolename='func', typenames=('paramtype', 'type')),
125+
GroupedField('errors', label=l_('Throws'), rolename='err',
126+
names=('throws', ),
127+
can_collapse=True),
128+
Field('returnvalue', label=l_('Returns'), has_arg=False,
129+
names=('returns', 'return')),
130+
Field('returntype', label=l_('Return type'), has_arg=False,
131+
names=('rtype',)),
132+
]
133+
134+
135+
class MongoDBXRefRole(XRefRole):
136+
def process_link(self, env, refnode, has_explicit_title, title, target):
137+
# basically what sphinx.domains.python.PyXRefRole does
138+
refnode['mongodb:object'] = env.temp_data.get('mongodb:object')
139+
if not has_explicit_title:
140+
title = title.lstrip('.')
141+
target = target.lstrip('~')
142+
if title[0:1] == '~':
143+
title = title[1:]
144+
dot = title.rfind('.')
145+
if dot != -1:
146+
title = title[dot+1:]
147+
if target[0:1] == '.':
148+
target = target[1:]
149+
refnode['refspecific'] = True
150+
return title, target
151+
152+
153+
class MongoDBDomain(Domain):
154+
"""MongoDB Documentation domain."""
155+
name = 'mongodb'
156+
label = 'MongoDB'
157+
# if you add a new object type make sure to edit MongoDBObject.get_index_string
158+
object_types = {
159+
'command': ObjType(l_('command'), 'command'),
160+
'operator': ObjType(l_('operator'), 'operator'),
161+
'setting': ObjType(l_('setting'), 'setting'),
162+
'status': ObjType(l_('status'), 'status'),
163+
}
164+
directives = {
165+
'command': MongoDBCallable,
166+
'operator': MongoDBCallable,
167+
'setting': MongoDBCallable,
168+
'status': MongoDBCallable,
169+
}
170+
roles = {
171+
'command': MongoDBXRefRole(),
172+
'operator': MongoDBXRefRole(),
173+
'setting': MongoDBXRefRole(),
174+
'status': MongoDBXRefRole(),
175+
}
176+
initial_data = {
177+
'objects': {}, # fullname -> docname, objtype
178+
}
179+
180+
# def clear_doc(self, docname):
181+
# for fullname, (fn, _) in self.data['objects'].items():
182+
# if fn == docname:
183+
# del self.data['objects'][fullname]
184+
185+
def find_obj(self, env, obj, name, typ, searchorder=0):
186+
if name[-2:] == '()':
187+
name = name[:-2]
188+
objects = self.data['objects']
189+
newname = None
190+
if searchorder == 1:
191+
if obj and obj + '.' + name in objects:
192+
newname = obj + '.' + name
193+
else:
194+
newname = name
195+
else:
196+
if name in objects:
197+
newname = name
198+
elif obj and obj + '.' + name in objects:
199+
newname = obj + '.' + name
200+
return newname, objects.get(newname)
201+
202+
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
203+
contnode):
204+
objectname = node.get('mongodb:object')
205+
searchorder = node.hasattr('refspecific') and 1 or 0
206+
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
207+
if not obj:
208+
return None
209+
return make_refnode(builder, fromdocname, obj[0],
210+
name.replace('$', '_S_'), contnode, name)
211+
212+
def get_objects(self):
213+
for refname, (docname, type) in self.data['objects'].items():
214+
# yield refname, refname, type, docname, refname.replace('$', '_S_'), 1
215+
yield refname, refname, type, docname, refname, 1
216+
print(refname)
217+
218+
def setup(app):
219+
app.add_domain(MongoDBDomain)

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
mongodb/build
2-
mms/build
1+
build/*
32
*.swp
43
.#*
54
\#*#
5+
*__pycache__*
File renamed without changes.

conf.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# serve to show the default.
1313

1414
import sys, os
15-
15+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".ext")))
1616
# If extensions (or modules to document with autodoc) are in another directory,
1717
# add these directories to sys.path here. If the directory is relative to the
1818
# documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -25,10 +25,10 @@
2525

2626
# Add any Sphinx extension module names here, as strings. They can be extensions
2727
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28-
extensions = ['sphinx.ext.todo']
28+
extensions = ['sphinx.ext.todo', 'mongodb_docs']
2929

3030
# Add any paths that contain templates here, relative to this directory.
31-
templates_path = ['templates']
31+
templates_path = ['.templates']
3232

3333
# The suffix of source filenames.
3434
source_suffix = '.rst'
@@ -128,7 +128,8 @@
128128

129129
# If true, SmartyPants will be used to convert quotes and dashes to
130130
# typographically correct entities.
131-
#html_use_smartypants = True
131+
132+
html_use_smartypants = True
132133

133134
# Custom sidebar templates, maps document names to template names.
134135
#html_sidebars = {}
@@ -141,10 +142,11 @@
141142
#html_domain_indices = True
142143

143144
# If false, no index is generated.
144-
#html_use_index = True
145+
146+
html_use_index = True
145147

146148
# If true, the index is split into individual pages for each letter.
147-
#html_split_index = False
149+
html_split_index = True
148150

149151
# If true, links to the reST sources are added to the pages.
150152
#html_show_sourcelink = True

0 commit comments

Comments
 (0)