1
# -*- coding: utf-8 -*-
6
The Percona Server domain.
8
:copyright: Copyright 2011 by Percona Inc.
9
:license: GPL3, see LICENSE for details.
15
from docutils import nodes
16
from docutils.parsers.rst import directives
18
from sphinx import addnodes
19
from sphinx.roles import XRefRole
20
from sphinx.locale import l_, _
21
from sphinx.domains import Domain, ObjType, Index
22
from sphinx.directives import ObjectDescription
23
from sphinx.util.nodes import make_refnode
24
from sphinx.util.compat import Directive
25
from sphinx.util.docfields import Field, GroupedField, TypedField
28
# RE to split at word boundaries
29
wsplit_re = re.compile(r'\W+')
30
tern_re = re.compile(r'.*(\.|\:\:).*(\.).*')
32
class PSschemaObject(ObjectDescription):
34
Description of a general PS object.
37
'noindex': directives.flag,
41
def handle_signature(self, sig, signode):
42
"""Transform a PSschema signature into RST nodes."""
43
# first try the function pointer signature regex, it's more specific
47
# signode += addnodes.desc_name('', '')
49
objectname = self.env.temp_data.get('psdom:object')
51
ws = wsplit_re.split(sig)
54
sig_prefix = "database "
58
signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
60
# for part in filter(None, ws):
61
# tnode = nodes.Text(part, part)
62
# pnode = addnodes.pending_xref(
63
# '', refdomain='psdom', reftype='type', reftarget=part,
64
# modname=None, classname=None)
69
dbname, tablename, columnname = ws
71
fullname = tablename + "." + columnname
74
dbname, tablename = ws
77
signode['table'] = tablename
78
signode += addnodes.desc_addname(dbname, dbname)
79
signode += addnodes.desc_name(tablename, tablename)
80
fullname = dbname + "." + tablename
82
tablename, columnname = ws
84
signode += addnodes.desc_addname(tablename, tablename)
85
signode += addnodes.desc_name(columnname, columnname)
86
signode['table'] = tablename
87
fullname = tablename + "." + columnname
91
signode['table'] = tablename
92
dbname = self.options.get(
93
'db', self.env.temp_data.get('psdom:db'))
95
self.env.temp_data['psdom:table'] = tablename
96
signode += addnodes.desc_addname(dbname, dbname)
97
signode += addnodes.desc_name(tablename, tablename)
98
signode['table'] = tablename
101
signode['column'] = columnname
102
tablename = self.options.get(
103
'table', self.env.temp_data.get('psdom:table'))
105
signode += addnodes.desc_addname(tablename, tablename)
106
signode += addnodes.desc_name(columnname, columnname)
109
signode['db'] = dbname
111
self.env.temp_data['psdom:db'] = dbname
112
signode += addnodes.desc_name(dbname, dbname)
115
signode['fullname'] = fullname
120
def get_index_text(self, name):
121
if self.objtype == 'db':
122
return _('%s (database)') % name
123
elif self.objtype == 'table':
124
return _('%s (table)') % name
125
elif self.objtype == 'column':
126
return _('%s (column)') % name
130
def add_target_and_index(self, name, sig, signode):
132
if name not in self.state.document.ids:
133
signode['names'].append(name)
134
signode['ids'].append(name)
135
signode['first'] = (not self.names)
136
self.state.document.note_explicit_target(signode)
137
inv = self.env.domaindata['c']['objects']
141
'duplicate C object description of %s, ' % name +
142
'other instance in ' + self.env.doc2path(inv[name][0]),
144
inv[name] = (self.env.docname, self.objtype)
146
indextext = self.get_index_text(name)
148
self.indexnode['entries'].append(('single', indextext, name, ''))
151
class PSconfigObject(ObjectDescription):
153
Description of a general PS object.
156
'noindex': directives.flag,
159
def handle_signature(self, sig, signode):
160
"""Transform a PSschema signature into RST nodes."""
161
# first try the function pointer signature regex, it's more specific
166
sig_prefix = ot + " "
167
signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
169
signode += addnodes.desc_name(name, name)
170
signode['fullname'] = name
174
def get_index_text(self, name):
175
if self.objtype == 'option':
176
return _('%s (option)') % name
177
elif self.objtype == 'variable':
178
return _('%s (variable)') % name
182
def add_target_and_index(self, name, sig, signode):
184
if name not in self.state.document.ids:
185
signode['names'].append(name)
186
signode['ids'].append(name)
187
signode['first'] = (not self.names)
188
self.state.document.note_explicit_target(signode)
189
inv = self.env.domaindata['psdom']['objects']
193
'duplicate C object description of %s, ' % name +
194
'other instance in ' + self.env.doc2path(inv[name][0]),
196
inv[name] = (self.env.docname, self.objtype)
198
indextext = self.get_index_text(name)
200
self.indexnode['entries'].append(('single', indextext, name, ''))
203
class PSTable(PSschemaObject):
206
TypedField('tbl', label=l_('Tables'),
207
names=('tbl', 'table',),
208
typerolename='obj', typenames=('paramtype', 'type'),
210
TypedField('variable', label=l_('Variables'), rolename='obj',
211
names=('var', 'ivar', 'cvar'),
212
typerolename='obj', typenames=('vartype',),
214
TypedField('column', label=l_('Columns'), rolename='obj',
215
names=('col', 'column', 'cols'),
216
typerolename='obj', typenames=('paramtype', 'type'),
218
Field('engine', label=l_('Storage Engine'), has_arg=False,
220
Field('inpatch', label=l_('Included in Patch'), has_arg=False,
222
TypedField('versioninfo', label=l_('Version Info'), rolename='obj',
223
names=('version', 'versioninfo'),
224
typerolename='obj', typenames=('paramtype', 'type'),
228
class PSDatabase(PSschemaObject):
231
TypedField('tbl', label=l_('Tables'),
232
names=('tbl', 'table',),
233
typerolename='obj', typenames=('paramtype', 'type'),
235
Field('engine', label=l_('Storage Engine'), has_arg=False,
237
Field('inpatch', label=l_('Included in Patch'), has_arg=False,
241
class PSColumn(PSschemaObject):
244
TypedField('coltype', label=l_('Type'), rolename='obj',
245
names=('coltype', 'type'),
246
typerolename='obj', typenames=('paramtype', 'type'),
248
Field('inpatch', label=l_('Included in Patch'), has_arg=False,
252
class PSVariable(PSconfigObject):
255
Field('scope', label=l_('Scope'), has_arg=False,
256
names=('scope', 'varscope')),
257
Field('cmdline', label=l_('Command Line'), has_arg=False,
258
names=('cmdline', 'cline', 'cli')),
259
Field('configfile', label=l_('Config File'), has_arg=False,
260
names=('conffile', 'configfile', 'conf', 'cfile')),
261
Field('dynamic', label=l_('Dynamic'), has_arg=False,
262
names=('dynvar', 'dyn')),
263
Field('vartype', label=l_('Variable Type'), has_arg=False,
264
names=('vartype', 'vtype')),
265
Field('default', label=l_('Default Value'), has_arg=False,
266
names=('default', 'df')),
267
Field('range', label=l_('Range'), has_arg=False,
268
names=('range', 'range')),
269
Field('allowed', label=l_('Allowed Values'), has_arg=False,
270
names=('allowed', 'av')),
271
Field('unit', label=l_('Units'), has_arg=False,
272
names=('unit', 'un')),
273
Field('inpatch', label=l_('Included in Patch'), has_arg=False,
275
TypedField('versioninfo', label=l_('Version Info'), rolename='obj',
276
names=('version', 'versioninfo'),
277
typerolename='obj', typenames=('paramtype', 'type'),
281
class PSOption(PSconfigObject):
284
TypedField('tbl', label=l_('Tables'),
285
names=('tbl', 'table',),
286
typerolename='obj', typenames=('paramtype', 'type'),
288
TypedField('variable', label=l_('Variables'), rolename='obj',
289
names=('var', 'ivar', 'cvar'),
290
typerolename='obj', typenames=('vartype',),
292
TypedField('column', label=l_('Columns'), rolename='obj',
293
names=('col', 'column', 'cols'),
294
typerolename='obj', typenames=('paramtype', 'type'),
296
Field('engine', label=l_('Storage Engine'), has_arg=False,
298
Field('inpatch', label=l_('Included in Patch'), has_arg=False,
302
class PSXRefRole(XRefRole):
303
def process_link(self, env, refnode, has_explicit_title, title, target):
304
if not has_explicit_title:
305
target = target.lstrip('~') # only has a meaning for the title
306
# if the first character is a tilde, don't display the module/class
307
# parts of the contents
308
if title[0:1] == '~':
310
dot = title.rfind('.')
312
title = title[dot+1:]
316
class PerconaServerDomain(Domain):
317
"""Percona Server domain."""
319
label = 'Percona Server'
321
'db': ObjType(l_('db'), 'db'),
322
'table': ObjType(l_('table'), 'table'),
323
'column': ObjType(l_('column'), 'column'),
324
'option': ObjType(l_('option'), 'option'),
325
'variable': ObjType(l_('variable'), 'data'),
333
'variable': PSVariable,
337
'table': PSXRefRole(),
338
'column': PSXRefRole(),
339
'option': PSXRefRole(),
340
'variable': PSXRefRole(),
343
'objects': {}, # fullname -> docname, objtype
346
def clear_doc(self, docname):
347
for fullname, (fn, _) in self.data['objects'].items():
349
del self.data['objects'][fullname]
351
def resolve_xref(self, env, fromdocname, builder,
352
typ, target, node, contnode):
353
# strip pointer asterisk
354
target = target.rstrip(' *')
355
if target not in self.data['objects']:
357
obj = self.data['objects'][target]
358
return make_refnode(builder, fromdocname, obj[0], target,
361
def get_objects(self):
362
for refname, (docname, type) in self.data['objects'].iteritems():
363
yield (refname, refname, type, docname, refname, 1)
365
def find_obj(self, env, obj, name, typ, searchorder=0):
366
if name[-2:] == '()':
368
objects = self.data['objects']
371
if obj and obj + '.' + name in objects:
372
newname = obj + '.' + name
378
elif obj and obj + '.' + name in objects:
379
newname = obj + '.' + name
380
return newname, objects.get(newname)
383
app.add_config_value('databases', {}, 'env')
384
app.add_domain(PerconaServerDomain)