jsmath in docstrings

4 views
Skip to first unread message

John H Palmieri

unread,
Mar 29, 2009, 7:14:27 PM3/29/09
to sage-devel
In the notebook, would it be at all feasible to have the math in
docstrings (that is, text in backquotes like `n \times n`) run through
jsmath?

John

William Stein

unread,
Mar 29, 2009, 7:46:57 PM3/29/09
to sage-...@googlegroups.com

Yes, that's definitely possible. Also, something like pygments (?) I
guess could make it nicely highlighted. Doing what you request has
been on "the" todo list ever since the notebook was written.

William

John H Palmieri

unread,
Mar 29, 2009, 8:07:09 PM3/29/09
to sage-devel
On Mar 29, 4:46 pm, William Stein <wst...@gmail.com> wrote:
> On Sun, Mar 29, 2009 at 4:14 PM, John H Palmieri <jhpalmier...@gmail.com> wrote:
>
>
>
> > In the notebook, would it be at all feasible to have the math in
> > docstrings (that is, text in backquotes like `n \times n`) run through
> > jsmath?
>
> Yes, that's definitely possible.  Also, something like pygments (?) I
> guess could make it nicely highlighted.   Doing what you request has
> been on "the" todo list ever since the notebook was written.

Where in the code is the docstring (and its shaded box, etc.)
constructed?

John

William Stein

unread,
Mar 29, 2009, 8:29:53 PM3/29/09
to sage-...@googlegroups.com

In sage/server/support.py the function "docstring" constructs the
docstring for an object.

The reason the introspection (docstring) output appears in a pre
environment is this line in sage/server/notebook/cell.py:

self.__introspect_html = '<pre class="introspection">'+html+'</pre>'

I think if you replace that by

self.__introspect_html = '<div class="introspection">'+html+'</div>'

and were to make the function "docstring" output nice HTML, then that
nice HTML would appear in the notebook.

Note that there is also some introspection css in the file
server/notebook/css.py which is relevant to say changing background
colors, transparency, etc.

-- William

Jason Grout

unread,
Mar 30, 2009, 5:19:56 AM3/30/09
to sage-...@googlegroups.com


At this point, I think it would be even better to just return the
html-formatted documentation for stuff that is written in rest, and
doing this for anything else.

Jason

John H Palmieri

unread,
Mar 31, 2009, 6:12:06 PM3/31/09
to sage-devel
On Mar 29, 4:46 pm, William Stein <wst...@gmail.com> wrote:
> On Sun, Mar 29, 2009 at 4:14 PM, John H Palmieri <jhpalmier...@gmail.com> wrote:
>
> > In the notebook, would it be at all feasible to have the math in
> > docstrings (that is, text in backquotes like `n \times n`) run through
> > jsmath?
>
> Yes, that's definitely possible.  Also, something like pygments (?) I
> guess could make it nicely highlighted.   Doing what you request has
> been on "the" todo list ever since the notebook was written.

See <http://trac.sagemath.org/sage_trac/ticket/5653> for a patch, and
see

<http://sage.math.washington.edu/home/palmieri/misc/docstring.png>

for a picture. It's not perfect but I'm a little stumped about how to
fix the problems, so anyone who is interested, please take a look and
fix it!

John

Pat LeSmithe

unread,
Apr 1, 2009, 2:10:51 AM4/1/09
to sage-...@googlegroups.com

After some manual inspection of Sphinx's cmdline.py, I think I've made
some [crude] progress (screenshot attached). In cell.py, I replaced
Cell.set_introspect_html() with

def set_introspect_html(self, html, completing=False):
if completing:
self.__introspect_html = html
else:
# html = escape(html).strip()
# self.__introspect_html = '<pre
class="introspection">'+html+'</pre>'
from sage.misc.misc import SAGE_ROOT, tmp_dir
temp=tmp_dir()
file_rst = temp + '/index.rst'
f = open(file_rst, 'w')
f.write(html)
f.close()
print file_rst
import sys
from sphinx.application import Sphinx
srcdir = temp
confdir = SAGE_ROOT + '/devel/sage-main/doc/common'
outdir = temp
doctreedir = temp + '/.doctrees'
buildername = 'html'
os.environ['SAGE_DOC_JSMATH'] = "True"
confoverrides = {'html_context': {}}
status = sys.stdout
warning = sys.stderr
freshenv = True
all_files = None
filenames = [file_rst]

app = Sphinx(srcdir, confdir, outdir, doctreedir,
buildername, confoverrides, status, warning, freshenv)
app.build(all_files, filenames)

file_html = temp + '/index.html'
f = open(file_html, 'r')
new_html = f.read()
f.close()
html = new_html.replace('_static','/doc/live/_static')
self.__introspect_html = html


This has many problems:

* It creates a new temporary directory for every non-completing
introspection. I like the ability to introspect recently changed code
on-the-fly, but I'm not familiar with hashes and caches. doctreedir and
freshenv could be useful.
* It needs CSS class-fication, e.g., with class="introspection", to
avoid spontaneously restyling other page elements.
* It doesn't touch completions. Perhaps this is OK.
* ?? output has extra triple quotes.
* It still doesn't get the math right, though I think it does link to
some jsMath code.
* Search doesn't work.
* Links to the source and index are broken. I tried, unsuccessfully, to
move the sidebar to the right (see http://sphinx.pocoo.org/theming.html).
* No cross-links. Maybe doctreedir and freshenv are relevant here, too.

I'm sure I missed something(s).

Here's an analogue with Pygments, mostly copied from their Quickstart
page (http://pygments.org/docs/quickstart/):

def set_introspect_html(self, html, completing=False):
if completing:
self.__introspect_html = html
else:
# html = escape(html).strip()
# self.__introspect_html = '<pre
class="introspection">'+html+'</pre>'
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter
from sphinx.highlighting import SphinxStyle
formatter = HtmlFormatter(style=SphinxStyle, noclasses=True)
html = highlight(html, PythonLexer(), formatter)

Pygments also has a PythonTracebackLexer
(http://pygments.org/docs/lexers/), but I'm not sure how to modify
cell.py's format_exception() and worksheet.py's
Worksheet.preparse_nonswitched_input(). It seems very complicated.

Lots of unexpected spare time today.

Sincerely,
Pat LeSmithe

sphinx.png

John H Palmieri

unread,
Apr 1, 2009, 6:57:10 PM4/1/09
to sage-devel
On Mar 31, 11:10 pm, Pat LeSmithe <qed...@gmail.com> wrote:
> After some manual inspection of Sphinx's cmdline.py, I think I've made
> some [crude] progress (screenshot attached).  In cell.py, I replaced
> Cell.set_introspect_html() with

This is cool. I've modified it a bit: I've deleted some of the html
and I've added some of the style sheet stuff to server/notebook/
css.py. I'll try to add a patch to the trac ticket later today.

> This has many problems:
>
> * It creates a new temporary directory for every non-completing
> introspection.

Right, and I think this makes it a bit slower than the ideal. I don't
know if it's too slow to be usable.

> * It needs CSS class-fication, e.g., with class="introspection", to
> avoid spontaneously restyling other page elements.

I think I've fixed this.

> * It doesn't touch completions.  Perhaps this is OK.

Well, typing

sage.algebras.steenrod_algebra

doesn't even produce a docstring with my version of your patch.

> * ?? output has extra triple quotes.

Hmm. I haven't looked into this.

> * It still doesn't get the math right, though I think it does link to
> some jsMath code.

I've fixed this.

> * Search doesn't work.
> * Links to the source and index are broken.  I tried, unsuccessfully, to
> move the sidebar to the right (seehttp://sphinx.pocoo.org/theming.html).
> * No cross-links.  Maybe doctreedir and freshenv are relevant here, too.

I've deleted all of the extra stuff: just show the docstring.

Here's a link to a new picture: (how do I add links to posts?)

<http://sage.math.washington.edu/home/palmieri/misc/sphinx.png>

John

William Stein

unread,
Apr 1, 2009, 7:06:16 PM4/1/09
to sage-devel
2009/4/1 John H Palmieri <jhpalm...@gmail.com>:

Can you post your new code so I can try it out? :-)

William

John H Palmieri

unread,
Apr 1, 2009, 8:01:05 PM4/1/09
to sage-devel
On Apr 1, 4:06 pm, William Stein <wst...@gmail.com> wrote:
> 2009/4/1 John H Palmieri <jhpalmier...@gmail.com>:
>
> > Here's a link to a new picture: (how do I add links to posts?)
>
> > <http://sage.math.washington.edu/home/palmieri/misc/sphinx.png>
>
> >  John
>
> Can you post your new code so I can try it out? :-)

Okay, there is a new patch at <http://trac.sagemath.org/sage_trac/
ticket/5653>.

John

Pat LeSmithe

unread,
Apr 2, 2009, 10:26:43 AM4/2/09
to sage-...@googlegroups.com

It's another mess --- I'm not very familiar with Python's string methods
--- but the code below seems to work. I've included a few comments.

def SPHINX_set_introspect_html(self, html, completing=False):
if completing:
self.__introspect_html = html
else:

# I think the following check should be in all *_set_introspect_html(),
# because set_introspect_html('') is called in worksheet.py, apparently
# with every cell evaluation.

if html == '':
self.__introspect_html = html
return
html = html.replace('\\\\', '\\')

from sage.misc.misc import SAGE_ROOT, tmp_dir

# [...snip...]
# I pause here because Sphinx "includes" load.js in the output as many
# times as set_introspect_html() has been called, which I daresay is
# a riddle. Even if we discard the header, this could become inefficient.

os.environ['SAGE_DOC_JSMATH'] = "True"

# [...snip...]
# It seems that Sphinx doesn't always use blockquotes, so I've
# added a few checks. I'm sure this could be much simpler.

html = new_html
i = html.find('<div class="body">')
html = html[i:]
i = html.rfind('</blockquote>')
if i == -1:
i = html.rfind('<div class="sphinxsidebar">')
if i == -1:
pass # worst case
else:
html = html[:i]
i = html.rfind('</div>')
html = html[:i]
i = html.rfind('</div>')
html = html[:i]
i = html.rfind('</div>')
html = html[:i]
else:
html = html[:i+13]
html = html.replace('<pre>', '<pre class="literal-block">')
html = '<div class="docstring">' + html + '</div>'
self.__introspect_html = html


With a dedicated "doc" directory in DOT_SAGE and some help from Python's
hashlib module, we might be able to keep a persistent (yet disposable)
cache of documentation, along the lines of ccache. It may be cheaper
for set_introspect_html() to apply a hash function to the incoming data
than to run Sphinx. (Alternatively, we could pass a time stamp as
another argument.) We could use the hash hex values themselves, plus
some human-readable identifiers, as file names. But I'm just speculating.


Sincerely,
Pat LeSmithe

John H Palmieri wrote:

John H Palmieri

unread,
Apr 2, 2009, 12:49:05 PM4/2/09
to sage-devel
On Apr 2, 7:26 am, Pat LeSmithe <qed...@gmail.com> wrote:
> It's another mess --- I'm not very familiar with Python's string methods
> --- but the code below seems to work.  I've included a few comments.

I incorporated the changes (although without the comments) in the
patch on the trac ticket. Unfortunately,

matrix? SHIFT-RETURN

still doesn't behave well, while

matrix? TAB

works fine. Other than that, and other than creating the temporary
directory, etc., this is looking pretty good. (There are still a few
other minor issues, like the triple quotes in the output from
"matrix??".)

John

Pat LeSmithe

unread,
Apr 3, 2009, 3:55:18 AM4/3/09
to sage-...@googlegroups.com
John H Palmieri wrote:
> matrix? SHIFT-RETURN
> still doesn't behave well, while

It seems that Cell.html_out() wraps this output in
div.cell_output_html_wrap. Referring to css.py, I think this accounts
for the different font. Adding font properties to div.docstring may
help. Then, something like

--- a/sage/server/notebook/js.py Wed Apr 01 15:48:21 2009 -0700
+++ b/sage/server/notebook/js.py Thu Apr 02 23:48:03 2009 -0700
@@ -3003,6 +3003,7 @@
cell_output.innerHTML = '';
cell_output_nowrap.innerHTML = '';
cell_output_html.innerHTML = introspect_html;
+ jsMath.ProcessBeforeShowing(cell_output_html);
}
}

typesets the output. It's probably better to use a try/catch block, as
done earlier in the ambient function. Note: I haven't explored the
consequences of these changes for other sorts of output.

A few more thoughts:

* The i = -1 "worst case" in SPHINX_set_instrospect_html() could instead
call the DOCUTILS version or the original, to degrade gracefully.

* It may help to "cp -r" SAGE_ROOT/devel/sage/doc/common to
SAGE_ROOT/devel/sage/doc/introspect and modify the new conf.py and
layout.html. This should simplify and speed up
SPHINX_set_introspect_html().

* If anyone's interested, here's a way to render an input cell as
syntax-highlighted HTML output:

from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter

from pygments.styles import STYLE_MAP
from pygments.styles import get_style_by_name
from sphinx.highlighting import SphinxStyle

class colorize:
def __init__(self, style=SphinxStyle):
self.lexer = PythonLexer(encoding='chardet')
self.formatter = HtmlFormatter(noclasses=True, style=style)
def eval(self, s, globals, locals):
return html(highlight(s, self.lexer, self.formatter))

Then put %colorize('colorful'), say, at the beginning of a cell and
evaluate it, e.g.,

%colorize('colorful')
def f(x):
return x * x
f(3.0)

STYLE_MAP.keys() gives a list of styles. This is adapted from
http://groups.google.com/group/sage-devel/msg/e53caae140cef7df .

John H Palmieri

unread,
Apr 3, 2009, 7:13:01 PM4/3/09
to sage-devel
On Apr 3, 12:55 am, Pat LeSmithe <qed...@gmail.com> wrote:
> John H Palmieri wrote:
> > matrix? SHIFT-RETURN
> > still doesn't behave well, while
>
> It seems that Cell.html_out() wraps this output in
> div.cell_output_html_wrap. Referring to css.py, I think this accounts
> for the different font. Adding font properties to div.docstring may
> help. Then, something like

Great, fixed it. I also added code to handle the display of source
code (e.g., "identity_matrix??") nicely.

> * The i = -1 "worst case" in SPHINX_set_instrospect_html() could instead
> call the DOCUTILS version or the original, to degrade gracefully.

I haven't done this. What are examples where this worst case happens,
so I can try out the various options?

> * It may help to "cp -r" SAGE_ROOT/devel/sage/doc/common to
> SAGE_ROOT/devel/sage/doc/introspect and modify the new conf.py and
> layout.html. This should simplify and speed up
> SPHINX_set_introspect_html().

I created this directory and the new code uses it, although I didn't
play too much with it -- I just made a few little changes to conf.py.
I'm not sure how much speed difference there will be; isn't the main
speed issue the fact that Sphinx is creating, reading, and writing
various files?

> * If anyone's interested, here's a way to render an input cell as
> syntax-highlighted HTML output:

This looked like fun, so I added it: there is now a decorator
"%pygments" which calls your code. (There was already a function
"colorize", and "%pygments" fits with "%html% and "%jsmath": naming,
rather precisely, the way the rest of the cell will be processed.)

John
Reply all
Reply to author
Forward
0 new messages