~ubuntu-branches/debian/experimental/spyder/experimental

« back to all changes in this revision

Viewing changes to spyderlib/utils/sphinxify.py

  • Committer: Package Import Robot
  • Author(s): Picca Frédéric-Emmanuel
  • Date: 2013-01-20 12:19:54 UTC
  • mfrom: (1.1.16)
  • Revision ID: package-import@ubuntu.com-20130120121954-1jt1xa924bshhvh0
Tags: 2.2.0~beta1+dfsg-2
fix typo ipython-qtconsol -> ipython-qtconsole

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*
2
 
#!/usr/bin/env python
3
 
r"""
4
 
Process docstrings with Sphinx
5
 
 
6
 
Processes docstrings with Sphinx. Can also be used as a commandline script:
7
 
 
8
 
``python sphinxify.py <text>``
9
 
 
10
 
AUTHORS:
11
 
 
12
 
- Tim Joseph Dumol (2009-09-29): initial version
13
 
- Carlos Cordoba (2010-09-21): Some changes to make it work with Spyder
14
 
 
15
 
Taken from the Sage project
16
 
http://www.sagemath.org/
17
 
"""
18
 
#**************************************************
19
 
# Copyright (C) 2009 Tim Dumol <tim@timdumol.com>
20
 
#
21
 
# Distributed under the terms of the BSD License
22
 
#**************************************************
23
 
 
24
 
import os
25
 
import re
26
 
import shutil
27
 
import os.path as osp
28
 
from tempfile import mkdtemp
29
 
import codecs
30
 
 
31
 
from sphinx.application import Sphinx #@UnusedImport
32
 
from docutils.utils import SystemMessage as SystemMessage
33
 
 
34
 
# Local imports
35
 
from spyderlib.baseconfig import get_module_source_path
36
 
from spyderlib.utils import encoding
37
 
 
38
 
# Note: we do not use __file__ because it won't be working in the stand-alone
39
 
# version of Spyder (i.e. the py2exe or cx_Freeze build)
40
 
CSS_PATH = osp.join(get_module_source_path('spyderlib.utils'), 'css')
41
 
 
42
 
 
43
 
def is_sphinx_markup(docstring):
44
 
    """
45
 
    Returns whether a string that contains Sphinx-style ReST markup.
46
 
 
47
 
    INPUT:
48
 
 
49
 
    - ``docstring`` - string to test for markup
50
 
 
51
 
    OUTPUT:
52
 
 
53
 
    - boolean
54
 
    """
55
 
    # this could be made much more clever
56
 
    return ("`" in docstring or "::" in docstring)
57
 
 
58
 
 
59
 
def sphinxify(docstring, format='html'):
60
 
    r"""
61
 
    Runs Sphinx on a ``docstring``, and outputs the processed
62
 
    documentation.
63
 
 
64
 
    INPUT:
65
 
 
66
 
    - ``docstring`` -- string -- a ReST-formatted docstring
67
 
 
68
 
    - ``format`` -- string (optional, default 'html') -- either 'html' or
69
 
      'text'
70
 
 
71
 
    OUTPUT:
72
 
 
73
 
    - string -- Sphinx-processed documentation, in either HTML or
74
 
      plain text format, depending on the value of ``format``
75
 
 
76
 
    EXAMPLES::
77
 
 
78
 
        >>> from spyderlib.plugins.sphinxify import sphinxify
79
 
        >>> sphinxify('A test')
80
 
        '\n<div class="docstring">\n    \n  <p>A test</p>\n\n\n</div>'
81
 
        >>> sphinxify('**Testing**\n`monospace`')
82
 
        '\n<div class="docstring">\n    \n  <p><strong>Testing</strong>\n<span class="math">monospace</span></p>\n\n\n</div>'
83
 
        >>> sphinxify('`x=y`')
84
 
        '\n<div class="docstring">\n    \n  <p><span class="math">x=y</span></p>\n\n\n</div>'
85
 
        >>> sphinxify('`x=y`', format='text')
86
 
        'x=y\n'
87
 
        >>> sphinxify(':math:`x=y`', format='text')
88
 
        'x=y\n'
89
 
    """
90
 
    global Sphinx
91
 
    if not Sphinx:
92
 
        from sphinx.application import Sphinx
93
 
 
94
 
    srcdir = mkdtemp()
95
 
    srcdir = encoding.to_unicode_from_fs(srcdir)
96
 
 
97
 
    base_name = os.path.join(srcdir, 'docstring')
98
 
    rst_name = base_name + '.rst'
99
 
 
100
 
    if format == 'html':
101
 
        suffix = '.html'
102
 
    else:
103
 
        suffix = '.txt'
104
 
    output_name = base_name + suffix
105
 
 
106
 
    # This is needed for jsMath to work.
107
 
    docstring = docstring.replace('\\\\', '\\')
108
 
 
109
 
    filed = codecs.open(rst_name, 'w', encoding='utf-8')
110
 
    filed.write(docstring)
111
 
    filed.close()
112
 
 
113
 
    # Sphinx constructor: Sphinx(srcdir, confdir, outdir, doctreedir,
114
 
    # buildername, confoverrides, status, warning, freshenv).
115
 
    
116
 
    # This may be inefficient.  TODO: Find a faster way to do this.
117
 
    temp_confdir = True
118
 
    confdir = mkdtemp()
119
 
    confdir = encoding.to_unicode_from_fs(confdir)
120
 
    generate_configuration(confdir)
121
 
 
122
 
    doctreedir = os.path.join(srcdir, 'doctrees')
123
 
    confoverrides = {'html_context': {}, 'master_doc': 'docstring'}
124
 
 
125
 
    sphinx_app = Sphinx(srcdir, confdir, srcdir, doctreedir, format,
126
 
                        confoverrides, None, None, True)
127
 
    try:
128
 
        sphinx_app.build(None, [rst_name])
129
 
    except SystemMessage:
130
 
        output = '<div id=\"warning\"> \
131
 
        It\'s not possible to generate rich text help for this object. \
132
 
        Please see it in plain text. \
133
 
        </div>'
134
 
        return output
135
 
 
136
 
    if os.path.exists(output_name):
137
 
        output = codecs.open(output_name, 'r', encoding='utf-8').read()
138
 
        output = output.replace('<pre>', '<pre class="literal-block">')
139
 
 
140
 
        # Translate URLs for media from something like
141
 
        #    "../../media/...path.../blah.png"
142
 
        # or
143
 
        #    "/media/...path.../blah.png"
144
 
        # to
145
 
        #    "/doc/static/reference/media/...path.../blah.png"
146
 
        output = re.sub("""src=['"](/?\.\.)*/?media/([^"']*)['"]""",
147
 
                          'src="/doc/static/reference/media/\\2"',
148
 
                          output)
149
 
    else:
150
 
        print "BUG -- Sphinx error"
151
 
        if format == 'html':
152
 
            output = '<pre class="introspection">%s</pre>' % docstring
153
 
        else:
154
 
            output = docstring
155
 
 
156
 
    if temp_confdir:
157
 
        shutil.rmtree(confdir, ignore_errors=True)
158
 
    shutil.rmtree(srcdir, ignore_errors=True)
159
 
 
160
 
    return output
161
 
 
162
 
 
163
 
def generate_configuration(directory):
164
 
    r"""
165
 
    Generates a Sphinx configuration in ``directory``.
166
 
 
167
 
    INPUT:
168
 
 
169
 
    - ``directory`` - string, base directory to use
170
 
 
171
 
    EXAMPLES::
172
 
 
173
 
        >>> from spyderlib.plugins.sphinxify import generate_configuration
174
 
        >>> import tempfile, os
175
 
        >>> tmpdir = tempfile.mkdtemp()
176
 
        >>> generate_configuration(tmpdir)
177
 
        >>> open(os.path.join(tmpdir, 'conf.py')).read()
178
 
        '\n...extensions =...templates_path...source = False\n...'
179
 
    """
180
 
    conf = r'''
181
 
###########################################################
182
 
# Taken from  `$SAGE_ROOT$/devel/sage/doc/common/conf.py` #
183
 
###########################################################
184
 
import sys, os
185
 
# If your extensions are in another directory, add it here. If the directory
186
 
# is relative to the documentation root, use os.path.abspath to make it
187
 
# absolute, like shown here.
188
 
#sys.path.append(os.path.abspath('.'))
189
 
 
190
 
# General configuration
191
 
# ---------------------
192
 
 
193
 
# Add any Sphinx extension module names here, as strings. They can be extensions
194
 
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
195
 
extensions = ['sphinx.ext.autodoc']
196
 
 
197
 
jsmath_path = 'easy/load.js'
198
 
 
199
 
# The suffix of source filenames.
200
 
source_suffix = '.rst'
201
 
 
202
 
# The master toctree document.
203
 
master_doc = 'index'
204
 
 
205
 
# General information about the project.
206
 
project = u""
207
 
copyright = u'2009--2011, The Spyder Development Team'
208
 
 
209
 
#version = '3.1.2'
210
 
# The full version, including alpha/beta/rc tags.
211
 
#release = '3.1.2'
212
 
 
213
 
# The language for content autogenerated by Sphinx. Refer to documentation
214
 
# for a list of supported languages.
215
 
#language = None
216
 
 
217
 
# There are two options for replacing |today|: either, you set today to some
218
 
# non-false value, then it is used:
219
 
#today = ''
220
 
# Else, today_fmt is used as the format for a strftime call.
221
 
#today_fmt = '%B %d, %Y'
222
 
 
223
 
# List of documents that shouldn't be included in the build.
224
 
#unused_docs = []
225
 
 
226
 
# List of directories, relative to source directory, that shouldn't be searched
227
 
# for source files.
228
 
exclude_trees = ['.build']
229
 
 
230
 
# The reST default role (used for this markup: `text`) to use for all documents.
231
 
default_role = 'math'
232
 
 
233
 
# If true, '()' will be appended to :func: etc. cross-reference text.
234
 
#add_function_parentheses = True
235
 
 
236
 
# If true, the current module name will be prepended to all description
237
 
# unit titles (such as .. function::).
238
 
#add_module_names = True
239
 
 
240
 
# If true, sectionauthor and moduleauthor directives will be shown in the
241
 
# output. They are ignored by default.
242
 
#show_authors = False
243
 
 
244
 
# The name of the Pygments (syntax highlighting) style to use.
245
 
pygments_style = 'sphinx'
246
 
 
247
 
 
248
 
# Options for HTML output
249
 
# -----------------------
250
 
 
251
 
# The style sheet to use for HTML and HTML Help pages. A file of that name
252
 
# must exist either in Sphinx' static/ path, or in one of the custom paths
253
 
# given in html_static_path.
254
 
html_style = 'default.css'
255
 
 
256
 
# The name for this set of Sphinx documents.  If None, it defaults to
257
 
# "<project> v<release> documentation".
258
 
#html_title = None
259
 
 
260
 
# A shorter title for the navigation bar.  Default is the same as html_title.
261
 
#html_short_title = None
262
 
 
263
 
# The name of an image file (within the static path) to place at the top of
264
 
# the sidebar.
265
 
#html_logo = ''
266
 
 
267
 
# The name of an image file (within the static path) to use as favicon of the
268
 
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
269
 
# pixels large.
270
 
#html_favicon = 'favicon.ico'
271
 
 
272
 
# If we're using jsMath, we prepend its location to the static path
273
 
# array.  We can override / overwrite selected files by putting them
274
 
# in the remaining paths.
275
 
#if 'SAGE_DOC_JSMATH' in os.environ:
276
 
#    jsmath_static = os.path.join(SAGE_ROOT, 'local/notebook/javascript/jsmath')
277
 
#    html_static_path.insert(0, jsmath_static)
278
 
 
279
 
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
280
 
# using the given strftime format.
281
 
#html_last_updated_fmt = '%b %d, %Y'
282
 
 
283
 
# If true, SmartyPants will be used to convert quotes and dashes to
284
 
# typographically correct entities.
285
 
#html_use_smartypants = True
286
 
 
287
 
# Custom sidebar templates, maps document names to template names.
288
 
#html_sidebars = {}
289
 
 
290
 
# Additional templates that should be rendered to pages, maps page names to
291
 
# template names.
292
 
#html_additional_pages = {}
293
 
 
294
 
# If false, no module index is generated.
295
 
#html_use_modindex = True
296
 
 
297
 
# If false, no index is generated.
298
 
#html_use_index = True
299
 
 
300
 
# If true, the reST sources are included in the HTML build as _sources/<name>.
301
 
#html_copy_source = True
302
 
 
303
 
# If true, an OpenSearch description file will be output, and all pages will
304
 
# contain a <link> tag referring to it.  The value of this option must be the
305
 
# base URL from which the finished HTML is served.
306
 
#html_use_opensearch = ''
307
 
 
308
 
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
309
 
#html_file_suffix = ''
310
 
 
311
 
# Output file base name for HTML help builder.
312
 
#htmlhelp_basename = ''
313
 
 
314
 
 
315
 
# Options for LaTeX output
316
 
# ------------------------
317
 
 
318
 
# The paper size ('letter' or 'a4').
319
 
#latex_paper_size = 'letter'
320
 
 
321
 
# The font size ('10pt', '11pt' or '12pt').
322
 
#latex_font_size = '10pt'
323
 
 
324
 
# Grouping the document tree into LaTeX files. List of tuples
325
 
# (source start file, target name, title, author, document class [howto/manual]).
326
 
latex_documents = []
327
 
 
328
 
# The name of an image file (relative to this directory) to place at the top of
329
 
# the title page.
330
 
#latex_logo = ''
331
 
 
332
 
# For "manual" documents, if this is true, then toplevel headings are parts,
333
 
# not chapters.
334
 
#latex_use_parts = False
335
 
 
336
 
# Additional stuff for the LaTeX preamble.
337
 
#latex_preamble = ''
338
 
latex_preamble = '\usepackage{amsmath}\n\usepackage{amsfonts}\n'
339
 
 
340
 
# Documents to append as an appendix to all manuals.
341
 
#latex_appendices = []
342
 
 
343
 
# If false, no module index is generated.
344
 
#latex_use_modindex = True
345
 
 
346
 
#####################################################
347
 
# add LaTeX macros for Sage
348
 
#try:
349
 
#    from sage.misc.latex_macros import sage_latex_macros
350
 
#except ImportError:
351
 
sage_latex_macros = []
352
 
 
353
 
try:
354
 
    pngmath_latex_preamble  # check whether this is already defined
355
 
except NameError:
356
 
    pngmath_latex_preamble = ""
357
 
 
358
 
for macro in sage_latex_macros:
359
 
    # used when building latex and pdf versions
360
 
    latex_preamble += macro + '\n'
361
 
    # used when building html version
362
 
    pngmath_latex_preamble += macro + '\n'
363
 
 
364
 
#####################################################
365
 
def process_docstring_aliases(app, what, name, obj, options, docstringlines):
366
 
    """
367
 
    Change the docstrings for aliases to point to the original object.
368
 
    """
369
 
    basename = name.rpartition('.')[2]
370
 
    if hasattr(obj, '__name__') and obj.__name__ != basename:
371
 
        docstringlines[:] = ['See :obj:`%s`.' % name]
372
 
 
373
 
def process_directives(app, what, name, obj, options, docstringlines):
374
 
    """
375
 
    Remove 'nodetex' and other directives from the first line of any
376
 
    docstring where they appear.
377
 
    """
378
 
    if len(docstringlines) == 0:
379
 
        return
380
 
    first_line = docstringlines[0]
381
 
    directives = [ d.lower() for d in first_line.split(',') ]
382
 
    if 'nodetex' in directives:
383
 
        docstringlines.pop(0)
384
 
 
385
 
def process_docstring_cython(app, what, name, obj, options, docstringlines):
386
 
    """
387
 
    Remove Cython's filename and location embedding.
388
 
    """
389
 
    if len(docstringlines) <= 1:
390
 
        return
391
 
 
392
 
    first_line = docstringlines[0]
393
 
    if first_line.startswith('File:') and '(starting at' in first_line:
394
 
        #Remove the first two lines
395
 
        docstringlines.pop(0)
396
 
        docstringlines.pop(0)
397
 
 
398
 
def process_docstring_module_title(app, what, name, obj, options, docstringlines):
399
 
    """
400
 
    Removes the first line from the beginning of the module's docstring.  This
401
 
    corresponds to the title of the module's documentation page.
402
 
    """
403
 
    if what != "module":
404
 
        return
405
 
 
406
 
    #Remove any additional blank lines at the beginning
407
 
    title_removed = False
408
 
    while len(docstringlines) > 1 and not title_removed:
409
 
        if docstringlines[0].strip() != "":
410
 
            title_removed = True
411
 
        docstringlines.pop(0)
412
 
 
413
 
    #Remove any additional blank lines at the beginning
414
 
    while len(docstringlines) > 1:
415
 
        if docstringlines[0].strip() == "":
416
 
            docstringlines.pop(0)
417
 
        else:
418
 
            break
419
 
 
420
 
def setup(app):
421
 
    app.connect('autodoc-process-docstring', process_docstring_cython)
422
 
    app.connect('autodoc-process-docstring', process_directives)
423
 
    app.connect('autodoc-process-docstring', process_docstring_module_title)
424
 
 
425
 
#################################################################
426
 
# Taken from `$SAGE_ROOT$/devel/sage/doc/en/introspect/conf.py` #
427
 
#################################################################
428
 
 
429
 
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.jsmath']
430
 
 
431
 
templates_path = ['templates']
432
 
html_static_path = ['static']
433
 
 
434
 
html_use_modindex = False
435
 
html_use_index = False
436
 
html_split_index = False
437
 
html_copy_source = False
438
 
'''
439
 
 
440
 
    # From SAGE_DOC/en/introspect/templates/layout.html:
441
 
    layout = r"""
442
 
<div class="docstring">
443
 
    {% block body %}{% endblock %}
444
 
</div>
445
 
"""
446
 
    os.makedirs(os.path.join(directory, 'templates'))
447
 
    os.makedirs(os.path.join(directory, 'static'))
448
 
    open(os.path.join(directory, 'conf.py'), 'w').write(conf)
449
 
    open(os.path.join(directory, '__init__.py'), 'w').write('')
450
 
    open(os.path.join(directory, 'templates', 'layout.html'),
451
 
         'w').write(layout)
452
 
    open(os.path.join(directory, 'static', 'empty'), 'w').write('')
453
 
 
454
 
if __name__ == '__main__':
455
 
    import sys
456
 
    if len(sys.argv) == 2:
457
 
        print sphinxify(sys.argv[1])
458
 
    else:
459
 
        print """Usage:
460
 
%s 'docstring'
461
 
 
462
 
docstring -- docstring to be processed
463
 
"""