Skip to content

Commit

Permalink
meta: mongodb domain for sphinx, and other minor non-textual changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Kleinman committed Jan 6, 2012
1 parent 71955f6 commit 4e3403a
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 8 deletions.
219 changes: 219 additions & 0 deletions .ext/mongodb_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
# -*- coding: utf-8 -*-
"""
MongoDB Domain for Sphinx
~~~~~~~~~~~~~~~~~~~~~~~~~
Based on the default JavaScript domain distributed with Sphinx.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
Additional work to adapt for MongoDB purposes done by 10gen,
inc. (Sam Kleinman, et al.)
"""

from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.locale import l_, _
from sphinx.directives import ObjectDescription
from sphinx.roles import XRefRole
from sphinx.domains.python import _pseudo_parse_arglist
from sphinx.util.nodes import make_refnode
from sphinx.util.docfields import Field, GroupedField, TypedField


class MongoDBObject(ObjectDescription):
"""
Description of a MongoDB object.
"""
#: If set to ``True`` this object is callable and a `desc_parameterlist` is
#: added
has_arguments = False

#: what is displayed right before the documentation entry
display_prefix = None

def handle_signature(self, sig, signode):
sig = sig.strip()
if '(' in sig and sig[-1:] == ')':
prefix, arglist = sig.split('(', 1)
prefix = prefix.strip()
arglist = arglist[:-1].strip()
else:
prefix = sig
arglist = None
if '.' in prefix:
nameprefix, name = prefix.rsplit('.', 1)
else:
nameprefix = None
name = prefix

objectname = self.env.temp_data.get('mongodb:object')
if nameprefix:
if objectname:
# someone documenting the method of an attribute of the current
# object? shouldn't happen but who knows...
nameprefix = objectname + '.' + nameprefix
fullname = nameprefix + '.' + name
elif objectname:
fullname = objectname + '.' + name
else:
# just a function or constructor
objectname = ''
fullname = name

signode['object'] = objectname
signode['fullname'] = fullname

if self.display_prefix:
signode += addnodes.desc_annotation(self.display_prefix,
self.display_prefix)
if nameprefix:
signode += addnodes.desc_addname(nameprefix + '.', nameprefix + '.')
signode += addnodes.desc_name(name, name)
if self.has_arguments:
if not arglist:
signode += addnodes.desc_parameterlist()
else:
_pseudo_parse_arglist(signode, arglist)
return fullname, nameprefix

def add_target_and_index(self, name_obj, sig, signode):
objectname = self.options.get(
'object', self.env.temp_data.get('mongodb:object'))
fullname = name_obj[0]
if fullname not in self.state.document.ids:
signode['names'].append(fullname)
signode['ids'].append(fullname.replace('$', '_S_'))
signode['first'] = not self.names
self.state.document.note_explicit_target(signode)
objects = self.env.domaindata['mongodb']['objects']
# if fullname in objects:
# self.state_machine.reporter.warning(
# 'duplicate object description of %s, ' % fullname +
# 'other instance in ' +
# self.env.doc2path(objects[fullname][0]),
# line=self.lineno)
objects[fullname] = self.env.docname, self.objtype

indextext = self.get_index_text(objectname, name_obj)
if indextext:
self.indexnode['entries'].append(('single', indextext,
fullname.replace('$', '_S_'),
''))

def get_index_text(self, objectname, name_obj):
name, obj = name_obj
if self.objtype == 'command':
return _('%s (database command)') % name
elif self.objtype == 'operator':
return _('%s (operator)') % name
elif self.objtype == 'setting':
return _('%s (setting)') % (name)
elif self.objtype == 'status':
return _('%s (status)') % (name)
return ''

class MongoDBCallable(MongoDBObject):
"""Description of a JavaScript function, method or constructor."""
has_arguments = False

doc_field_types = [
TypedField('arguments', label=l_('Arguments'),
names=('argument', 'arg', 'parameter', 'param'),
typerolename='func', typenames=('paramtype', 'type')),
GroupedField('errors', label=l_('Throws'), rolename='err',
names=('throws', ),
can_collapse=True),
Field('returnvalue', label=l_('Returns'), has_arg=False,
names=('returns', 'return')),
Field('returntype', label=l_('Return type'), has_arg=False,
names=('rtype',)),
]


class MongoDBXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# basically what sphinx.domains.python.PyXRefRole does
refnode['mongodb:object'] = env.temp_data.get('mongodb:object')
if not has_explicit_title:
title = title.lstrip('.')
target = target.lstrip('~')
if title[0:1] == '~':
title = title[1:]
dot = title.rfind('.')
if dot != -1:
title = title[dot+1:]
if target[0:1] == '.':
target = target[1:]
refnode['refspecific'] = True
return title, target


class MongoDBDomain(Domain):
"""MongoDB Documentation domain."""
name = 'mongodb'
label = 'MongoDB'
# if you add a new object type make sure to edit MongoDBObject.get_index_string
object_types = {
'command': ObjType(l_('command'), 'command'),
'operator': ObjType(l_('operator'), 'operator'),
'setting': ObjType(l_('setting'), 'setting'),
'status': ObjType(l_('status'), 'status'),
}
directives = {
'command': MongoDBCallable,
'operator': MongoDBCallable,
'setting': MongoDBCallable,
'status': MongoDBCallable,
}
roles = {
'command': MongoDBXRefRole(),
'operator': MongoDBXRefRole(),
'setting': MongoDBXRefRole(),
'status': MongoDBXRefRole(),
}
initial_data = {
'objects': {}, # fullname -> docname, objtype
}

# def clear_doc(self, docname):
# for fullname, (fn, _) in self.data['objects'].items():
# if fn == docname:
# del self.data['objects'][fullname]

def find_obj(self, env, obj, name, typ, searchorder=0):
if name[-2:] == '()':
name = name[:-2]
objects = self.data['objects']
newname = None
if searchorder == 1:
if obj and obj + '.' + name in objects:
newname = obj + '.' + name
else:
newname = name
else:
if name in objects:
newname = name
elif obj and obj + '.' + name in objects:
newname = obj + '.' + name
return newname, objects.get(newname)

def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
objectname = node.get('mongodb:object')
searchorder = node.hasattr('refspecific') and 1 or 0
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
if not obj:
return None
return make_refnode(builder, fromdocname, obj[0],
name.replace('$', '_S_'), contnode, name)

def get_objects(self):
for refname, (docname, type) in self.data['objects'].items():
# yield refname, refname, type, docname, refname.replace('$', '_S_'), 1
yield refname, refname, type, docname, refname, 1
print(refname)

def setup(app):
app.add_domain(MongoDBDomain)
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mongodb/build
mms/build
build/*
*.swp
.#*
\#*#
*__pycache__*
File renamed without changes.
14 changes: 8 additions & 6 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# serve to show the default.

import sys, os

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".ext")))
# 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
# documentation root, use os.path.abspath to make it absolute, like shown here.
Expand All @@ -25,10 +25,10 @@

# 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.todo']
extensions = ['sphinx.ext.todo', 'mongodb_docs']

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

# The suffix of source filenames.
source_suffix = '.rst'
Expand Down Expand Up @@ -128,7 +128,8 @@

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

html_use_smartypants = True

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

# If false, no index is generated.
#html_use_index = True

html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False
html_split_index = True

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

0 comments on commit 4e3403a

Please sign in to comment.