Ticket #7249: trac_7249-jinja2_v6.patch

File trac_7249-jinja2_v6.patch, 60.1 KB (added by timdumol, 10 years ago)

Fixes a problem with text cells with unicode contents.

  • sagenb/data/sage/css/main.css

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1262813598 28800
    # Node ID c6ea40a1660c8effb509bcaeea18827d30ac3baf
    # Parent  f20b011f30dc307d9f79627a78f01150005db3d3
    #7249 Switch the notebook's templating system to Jinja2
    
    diff --git a/sagenb/data/sage/css/main.css b/sagenb/data/sage/css/main.css
    a b  
    3737
    3838hr.usercontrol { clear: both; float: left; }
    3939
    40 div#user-controls { overflow: hidden; display: inline-block; clear: both; border-bottom: 1px solid #c9d7f1; padding: 10px; }
    41 div#user-controls { display: block; }
     40div#user-main-controls { overflow: hidden; display: inline-block; clear: both; border-bottom: 1px solid #c9d7f1; padding: 10px; }
     41div#user-main-controls { display: block; }
    4242div#worksheet-list-controls { padding: 10px; clear: both; overflow: hidden; display: inline-block; }
    4343div#worksheet-list-controls { display: block; }
    4444div#worksheet-list-controls div.action-buttons { float: left; }
     
    305305
    306306span.worksheet_buttons { position: relative; top: -20ex; right: 0ex; }
    307307
     308
    308309.thin-right { position: absolute; top: auto; right: 0; width: 70%; }
    309310
    310311/* *********** User Home (Worksheet listing) ************************* */
     312#worksheet-listing-page #welcome-message { text-align: center; padding: 1em; }
     313
    311314.ratingmsg { color: #112abb; padding: 0.3em; font-size: 14px; }
    312315
    313316.pubmsg { font-family: sans-serif; color: #112abb; padding: 0.3em; font-size: 12px; }
  • sagenb/data/sage/html/base.html

    diff --git a/sagenb/data/sage/html/base.html b/sagenb/data/sage/html/base.html
    a b  
    1 {%- macro render_title -%}{% block title %}{% endblock %}{%- endmacro -%}
     1{%- macro render_title() -%}{% block title %}{% endblock %}{%- endmacro -%}
    22<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    33<html lang="en">
    44    <head>
  • sagenb/data/sage/html/notebook/cell.html

    diff --git a/sagenb/data/sage/html/notebook/cell.html b/sagenb/data/sage/html/notebook/cell.html
    a b  
    1212        print or not.
    1313#}
    1414{% if do_print %}
    15     {% set wrap = 68 %}
    16     {% set div_wrap = true %}
     15    {% set wrap_ = 68 %}
     16    {% set div_wrap_ = true %}
     17{% else %}
     18    {% set wrap_ = wrap %}
     19    {% set div_wrap_ = div_wrap %}
    1720{% endif %}
    1821{% set cell_cls = "cell_evaluated" if cell.evaluated() or do_print else "cell_not_evaluated" %}
    1922
    20 {% if div_wrap %}
     23{% if div_wrap_ %}
    2124<div id="cell_outer_{{ cell.id() }}" class="cell_visible">
    2225    <div id="cell_{{ cell.id() }}" class="{{ cell_cls }}">
    2326{% endif %}
     
    5659                          onFocus="cell_focused(this, {{ '%r'|format(cell.id()) }}); return true;">{{ cell.input_text().rstrip() }}</textarea>
    5760                <a href="javascript:evaluate_cell({{ '%r'|format(cell.id()) }}, 0);"
    5861                   class="eval_button"
    59                    id="eval_button{{ cell.id() }}"
     62                   id="eval_button{{ cell.id() }}" 
    6063                   alt="Click here or press shift-return to evaluate">
    6164                    evaluate
    6265                </a>
     
    8588                                {% if cell.introspect() %}
    8689                                    {{ cell.output_text(0, html=true) }}
    8790                                {% else %}
    88                                     {{ cell.output_text(wrap, html=true) }}
     91                                    {{ cell.output_text(wrap_, html=true) }}
    8992                                {% endif %}
    9093                            </div>
    9194                            {% if not do_print %}
     
    105108        </div>
    106109        {% endif %}
    107110
    108 {% if div_wrap %}
     111{% if div_wrap_ %}
    109112    </div>
    110113</div>
    111114{% endif %}
  • sagenb/data/sage/html/notebook/text_cell.html

    diff --git a/sagenb/data/sage/html/notebook/text_cell.html b/sagenb/data/sage/html/notebook/text_cell.html
    a b  
    4747            cancel : 'Cancel changes',
    4848            event  : "dblclick",
    4949            style  : "inherit",
    50             data   : {{ '%r'|format(cell.plain_text()) }}
     50            data   : {{ cell.plain_text()|repr_str }}
    5151        });
    5252    </script>
    5353{% endif %}
  • sagenb/data/sage/html/worksheet_listing.html

    diff --git a/sagenb/data/sage/html/worksheet_listing.html b/sagenb/data/sage/html/worksheet_listing.html
    a b  
    132132        </tr>
    133133        {% elif typ == 'active' %}
    134134        <tr>
    135             <td colspan="5">
     135            <td colspan="5" id="welcome-message">
    136136                Welcome to Sage! You can <a href="/new_worksheet">create a new worksheet</a>,
    137137                view <a href="/pub/">published worksheets</a>, or read the
    138138                <a href="/help" target="_new">documentation</a>.
  • sagenb/interfaces/expect.py

    diff --git a/sagenb/interfaces/expect.py b/sagenb/interfaces/expect.py
    a b  
    241241        # The magic comment at the very start of the file allows utf8 characters.
    242242        open(self._filename,'w').write(
    243243            '# -*- coding: utf_8 -*-\nimport sys;sys.ps1="%s";print "START%s"\n'%(
    244             self._prompt, self._number) + displayhook_hack(string))
     244            self._prompt, self._number) + displayhook_hack(string).encode('utf-8', 'ignore'))
    245245        try:
    246246            self._expect.sendline('\nimport os;os.chdir("%s");\nexecfile("%s")'%(
    247247                              remote, sage_input))
    248         except OSError, msg:
     248        except OSError as msg:
    249249            self._is_computing = False
    250250            self._so_far = str(msg)
    251251
  • sagenb/misc/misc.py

    diff --git a/sagenb/misc/misc.py b/sagenb/misc/misc.py
    a b  
     1# -*- coding: utf-8 -*-
    12"""
    23Miscellaneous Notebook Functions
    34"""
     
    384385        # TODO
    385386        raise NotImplementedError, "Curently %cython mode requires Sage."
    386387
    387 
    388388#############################################################
    389389# File permissions
    390390# May need some changes on Windows.
     
    402402             stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | \
    403403             stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP)
    404404
     405def encoded_str(obj, encoding='utf-8'):
     406    """
     407    Takes an object and returns an encoded str human-readable representation.
     408
     409    EXAMPLES::
     410
     411        sage: from sagenb.misc.misc import encoded_str
     412        sage: encoded_str(u'ĀƂḉПΣ')
     413        '\xc3\x84\xc2\x80\xc3\x86\xc2\x82\xc3\xa1\xc2\xb8\xc2\x89\xc3\x90\xc2\x9f\xc3\x8e\xc2\xa3'
     414        sage: encoded_str(u'abc')
     415        'abc'
     416        sage: encoded_str(123)
     417        '123'
     418    """
     419    if isinstance(obj, unicode):
     420        return obj.encode(encoding, 'ignore')
     421    return str(obj)
     422
     423def unicode_str(obj, encoding='utf-8'):
     424    """
     425    Takes an object and returns a unicode human-readable representation.
     426
     427    EXAMPLES::
     428
     429        sage: from sagenb.misc.misc import unicode_str
     430        sage: unicode_str('\xc3\x84\xc2\x80\xc3\x86\xc2\x82\xc3\xa1\xc2\xb8\xc2\x89\xc3\x90\xc2\x9f\xc3\x8e\xc2\xa3')
     431        u'\xc4\x80\xc6\x82\xe1\xb8\x89\xd0\x9f\xce\xa3'
     432        sage: unicode_str('\xc3\x84\xc2\x80\xc3\x86\xc2\x82\xc3\xa1\xc2\xb8\xc2\x89\xc3\x90\xc2\x9f\xc3\x8e\xc2\xa3') == u'ĀƂḉПΣ'
     433        True
     434        sage: unicode_str('abc')
     435        u'abc'
     436        sage: unicode_str(123)
     437        u'123'
     438    """
     439    if isinstance(obj, str):
     440        return obj.decode(encoding, 'ignore')
     441    elif isinstance(obj, unicode):
     442        return obj
     443    return unicode(obj)
     444       
     445
    405446
    406447def ignore_nonexistent_files(curdir, dirlist):
    407448    """
  • sagenb/misc/sageinspect.py

    diff --git a/sagenb/misc/sageinspect.py b/sagenb/misc/sageinspect.py
    a b  
    115115
    116116import inspect
    117117import os
     118from .misc import encoded_str
    118119EMBEDDED_MODE = False
    119120
    120121def isclassinstance(obj):
     
    483484
    484485    if r is None:
    485486        return ''
     487    r = encoded_str(r)
    486488
    487     s = format(str(r), embedded=EMBEDDED_MODE)
     489    s = format(r, embedded=EMBEDDED_MODE)
    488490
    489491    # If there is a Cython embedded position, it needs to be stripped
    490492    pos = _extract_embedded_position(s)
  • sagenb/misc/support.py

    diff --git a/sagenb/misc/support.py b/sagenb/misc/support.py
    a b  
    331331        filename = sageinspect.sage_getfile(obj)
    332332        try:
    333333            lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False)
    334         except IOError, msg:
     334        except IOError as msg:
    335335            return html_markup(str(msg))
    336336        src = indent.join(lines)
    337337        src = indent + format_src(src)
     
    467467    if dir:
    468468        if hasattr(system.__class__, 'chdir'):
    469469            system.chdir(dir)
     470    if isinstance(cmd, unicode):
     471        cmd = cmd.encode('utf-8', 'ignore')
    470472    return system.eval(cmd, sage_globals, locals = sage_globals)
    471473
    472474######################################################################
  • sagenb/notebook/cell.py

    diff --git a/sagenb/notebook/cell.py b/sagenb/notebook/cell.py
    a b  
     1# -*- coding: utf-8 -*-
    12"""
    23A Cell.
    34
     
    1920
    2021from jsmath import math_parse
    2122from sagenb.misc.misc import (word_wrap, SAGE_DOC, strip_string_literals,
    22                               set_restrictive_permissions)
     23                              set_restrictive_permissions, unicode_str,
     24                              encoded_str)
    2325
    2426# Maximum number of characters allowed in output.  This is needed
    2527# avoid overloading web browser.  For example, it should be possible
     
    113115            sage: C == loads(dumps(C))
    114116            True
    115117        """
     118        text = unicode_str(text)
    116119        try:
    117120            self.__id = int(id)
    118121        except ValueError:
     
    133136
    134137            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
    135138            sage: C.__repr__()
    136             'TextCell 0: 2+3'
     139            u'TextCell 0: 2+3'
    137140        """
    138         return "TextCell %s: %s"%(self.__id, self.__text)
     141        return "TextCell %s: %s"%(self.__id, encoded_str(self.__text))
    139142
    140143    def delete_output(self):
    141144        """
     
    170173            sage: C
    171174            TextCell 0: 3+2
    172175        """
     176        input_text = unicode_str(input_text)
    173177        self.__text = input_text
    174178
    175179    def set_worksheet(self, worksheet, id=None):
     
    248252
    249253        EXAMPLES::
    250254
    251             sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
     255            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
     256            sage: nb.add_user('sage','sage','sage@sagemath.org',force=True)
     257            sage: W = nb.create_new_worksheet('Test', 'sage')
     258            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', W)
    252259            sage: C.html()
    253260            u'...text_cell...2+3...'
    254261            sage: C.set_input_text("$2+3$")
     
    278285
    279286            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
    280287            sage: C.plain_text()
    281             '2+3'
     288            u'2+3'
     289            sage: C = sagenb.notebook.cell.TextCell(0, u'ΫäĻƾṀБ', None)
     290            sage: C.plain_text()
     291            u'\xce\xab\xc3\xa4\xc4\xbb\xc6\xbe\xe1\xb9\x80\xd0\x91'
    282292        """
    283293        return self.__text
    284294
     
    295305
    296306            sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None)
    297307            sage: C.edit_text()
    298             '2+3'
     308            u'2+3'
    299309        """
    300310        return self.__text
    301311
     
    402412            sage: C == loads(dumps(C))
    403413            True
    404414        """
     415        out = unicode_str(out)
     416        input = unicode_str(input)
    405417        try:
    406418            self.__id = int(id)
    407419        except ValueError:
    408420            self.__id = id
    409421
    410         self.__out   = str(out).replace('\r','')
     422        self.__out   = out.replace('\r','')
    411423        self.__worksheet = worksheet
    412424        self.__interrupted = False
    413425        self.__completions = False
     
    415427        self.__no_output_cell = False
    416428        self.__asap = False
    417429        self.__version = -1
    418         self.set_input_text(str(input).replace('\r',''))
     430        self.set_input_text(input.replace('\r',''))
    419431
    420432    def set_asap(self, asap):
    421433        """
     
    473485            sage: C
    474486            Cell 0; in=2+3, out=
    475487        """
    476         self.__out = ''
    477         self.__out_html = ''
     488        self.__out = u''
     489        self.__out_html = u''
    478490        self.__evaluated = False
    479491
    480492    def evaluated(self):
     
    705717            sage: nb.delete()
    706718        """
    707719        if self.is_interactive_cell():
    708             self.__out_html = ""
     720            self.__out_html = u""
    709721        else:
    710722            self.__out_html = self.files_html(output)
    711723
     
    887899            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None); C
    888900            Cell 0; in=2+3, out=5
    889901        """
    890         return 'Cell %s; in=%s, out=%s'%(self.__id, self.__in, self.__out)
     902        return 'Cell %s; in=%s, out=%s'%(self.__id, encoded_str(self.__in), encoded_str(self.__out))
    891903
    892904    def word_wrap_cols(self):
    893905        """
     
    944956        """
    945957        if ncols == 0:
    946958            ncols = self.word_wrap_cols()
    947         s = ''
     959        s = u''
     960
     961        self.__in = unicode_str(self.__in)
    948962
    949963        input_lines = self.__in
     964
    950965        pr = 'sage: '
    951966
    952967        if prompts:
     
    10351050
    10361051            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None)
    10371052            sage: C.edit_text()
    1038             '{{{id=0|\n2+3\n///\n5\n}}}'
     1053            u'{{{id=0|\n2+3\n///\n5\n}}}'
     1054            sage: C = sagenb.notebook.cell.Cell(0, u'ΫäĻƾṀБ', u'ΫäĻƾṀБ', None)
     1055            sage: C.edit_text()
     1056            u'{{{id=0|\n\xce\xab\xc3\xa4\xc4\xbb\xc6...\xb9\x80\xd0\x91\n}}}'
    10391057        """
    10401058        s = self.plain_text(ncols, prompts, max_out)
    1041         return '{{{id=%s|\n%s\n}}}'%(self.id(), s)
     1059        return u'{{{id=%s|\n%s\n}}}'%(self.id(), s)
    10421060
    10431061    def is_last(self):
    10441062        """
     
    12481266            0
    12491267            sage: C.set_input_text('3+3')
    12501268            sage: C.input_text()
    1251             '3+3'
     1269            u'3+3'
    12521270            sage: C.evaluated()
    12531271            False
    12541272            sage: C.version()
     
    12571275            sage: nb.delete()
    12581276        """
    12591277        # Stuff to deal with interact
     1278        input = unicode_str(input)
     1279
    12601280        if input.startswith('%__sage_interact__'):
    12611281            self.interact = input[len('%__sage_interact__')+1:]
    12621282            self.__version = self.version() + 1
     
    12921312
    12931313            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None)
    12941314            sage: C.input_text()
    1295             '2+3'
     1315            u'2+3'
    12961316        """
    12971317        return self.__in
    12981318
     
    13101330
    13111331            sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None)
    13121332            sage: C.cleaned_input_text()
    1313             '2+3'
     1333            u'2+3'
    13141334        """
    13151335        if self.is_interacting():
    13161336            return self.interact
     
    13301350
    13311351            sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None)
    13321352            sage: C.parse_percent_directives()
    1333             '2+3'
     1353            u'2+3'
    13341354            sage: C.percent_directives()
    1335             ['hide', 'maxima']
     1355            [u'hide', u'maxima']
    13361356        """
    13371357        self._system = None
    13381358        text = self.input_text().splitlines()
     
    13701390
    13711391            sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None)
    13721392            sage: C.percent_directives()
    1373             ['hide', 'maxima']
     1393            [u'hide', u'maxima']
    13741394        """
    13751395        return self._percent_directives
    13761396
     
    13921412
    13931413            sage: C = sagenb.notebook.cell.Cell(0, '%maxima\n2+3', '5', None)
    13941414            sage: C.system()
    1395             'maxima'
     1415            u'maxima'
    13961416            sage: prefixes = ['%hide', '%time', '']
    13971417            sage: cells = [sagenb.notebook.cell.Cell(0, '%s\n2+3'%prefix, '5', None) for prefix in prefixes]
    13981418            sage: [(C, C.system()) for C in cells if C.system() is not None]
     
    14381458            ''
    14391459            sage: C.set_changed_input_text('3+3')
    14401460            sage: C.input_text()
    1441             '3+3'
     1461            u'3+3'
    14421462            sage: C.changed_input_text()
    1443             '3+3'
     1463            u'3+3'
    14441464            sage: C.changed_input_text()
    14451465            ''
    14461466            sage: C.version()
     
    14681488            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None)
    14691489            sage: C.set_changed_input_text('3+3')
    14701490            sage: C.input_text()
    1471             '3+3'
     1491            u'3+3'
    14721492            sage: C.changed_input_text()
    1473             '3+3'
     1493            u'3+3'
    14741494        """
     1495        new_text = unicode_str(new_text)
     1496
    14751497        self.__changed_input = new_text
    14761498        self.__in = new_text
    14771499
     
    14971519            sage: len(C.plain_text())
    14981520            12
    14991521        """
     1522        output = unicode_str(output)
     1523        html = unicode_str(html)
    15001524        if output.count('<?__SAGE__TEXT>') > 1:
    1501             html = '<h3><font color="red">WARNING: multiple @interacts in one cell disabled (not yet implemented).</font></h3>'
    1502             output = ''
     1525            html = u'<h3><font color="red">WARNING: multiple @interacts in one cell disabled (not yet implemented).</font></h3>'
     1526            output = u''
    15031527
    15041528        # In interacting mode, we just save the computed output
    15051529        # (do not overwrite).
     
    15191543            url = ""
    15201544            if not self.computing():
    15211545                file = os.path.join(self.directory(), "full_output.txt")
    1522                 open(file,"w").write(output)
     1546                open(file,"w").write(output.encode('utf-8', 'ignore'))
    15231547                url = "<a target='_new' href='%s/full_output.txt' class='file_link'>full_output.txt</a>"%(
    15241548                    self.url_to_self())
    15251549                html+="<br>" + url
     
    15701594            ''
    15711595            sage: C.set_output_text('5', '<strong>5</strong>')
    15721596            sage: C.output_html()
    1573             '<strong>5</strong>'
     1597            u'<strong>5</strong>'
    15741598        """
    15751599        try:
    15761600            return self.__out_html
     
    16351659            sage: W = nb.create_new_worksheet('Test', 'sage')
    16361660            sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', W)
    16371661            sage: C.output_text()
    1638             '<pre class="shrunk">5</pre>'
     1662            u'<pre class="shrunk">5</pre>'
    16391663            sage: C.output_text(html=False)
    1640             '<pre class="shrunk">5</pre>'
     1664            u'<pre class="shrunk">5</pre>'
    16411665            sage: C.output_text(raw=True)
    1642             '5'
     1666            u'5'
     1667            sage: C = sagenb.notebook.cell.Cell(0, u'ΫäĻƾṀБ', u'ΫäĻƾṀБ', W)
     1668            sage: C.output_text()
     1669            u'<pre class="shrunk">\xce\xab\xc3\xa4\xc4\xbb\xc6\xbe\xe1\xb9\x80\xd0\x91</pre>'
     1670            sage: C.output_text(raw=True)
     1671            u'\xce\xab\xc3\xa4\xc4\xbb\xc6\xbe\xe1\xb9\x80\xd0\x91'
    16431672        """
    16441673        if allow_interact and hasattr(self, '_interact_output'):
    16451674            # Get the input template
     
    16631692                # wrong output location during interact.
    16641693                return ''
    16651694
     1695        self.__out = unicode_str(self.__out)
     1696
    16661697        is_interact = self.is_interactive_cell()
    16671698        if is_interact and ncols == 0:
    16681699            if 'Traceback (most recent call last)' in self.__out:
    16691700                s = self.__out.replace('cell-interact','')
    16701701                is_interact=False
    16711702            else:
    1672                 return '<h2>Click to the left again to hide and once more to show the dynamic interactive window</h2>'
     1703                return u'<h2>Click to the left again to hide and once more to show the dynamic interactive window</h2>'
    16731704        else:
    16741705            s = self.__out
    16751706
     
    17761807
    17771808            sage: C = sagenb.notebook.cell.Cell(0, "%html\nTest HTML", None, None)
    17781809            sage: C.system()
    1779             'html'
     1810            u'html'
    17801811            sage: C.is_html()
    17811812            True
    17821813            sage: C = sagenb.notebook.cell.Cell(0, "Test HTML", None, None)
     
    18361867            ('d', Cell 0; in=sage?, out=)
    18371868            sage: C.set_introspect_html('foobar')
    18381869            sage: C.introspect_html()
    1839             'foobar'
     1870            u'foobar'
    18401871            sage: C.set_introspect_html('`foobar`')
    18411872            sage: C.introspect_html()
    1842             '`foobar`'
     1873            u'`foobar`'
     1874            sage: C.set_introspect_html(u'ΫäĻƾṀБ')
     1875            sage: C.introspect_html()
     1876            u'\xce\xab\xc3\xa4\xc4\xbb\xc6\xbe\xe1\xb9\x80\xd0\x91'
    18431877            sage: W.quit()
    18441878            sage: nb.delete()
    18451879        """
     1880        html = unicode_str(html)
     1881
    18461882        self.__introspect_html = html
    18471883        self.introspection_status = 'done'
    18481884
     
    18871923        try:
    18881924            return self.__introspect_html
    18891925        except AttributeError:
    1890             self.__introspect_html = ''
    1891             return ''
     1926            self.__introspect_html = u''
     1927            return u''
    18921928
    18931929    def introspect(self):
    18941930        """
     
    19111947            sage: W.check_comp(9999)     # random output -- depends on computer speed
    19121948            ('d', Cell 0; in=sage?, out=)
    19131949            sage: C.introspect()
    1914             ['sage?', '']
     1950            [u'sage?', '']
    19151951            sage: W.quit()
    19161952            sage: nb.delete()
    19171953        """
     
    19361972            sage: W.check_comp(9999)     # random output -- depends on computer speed
    19371973            ('d', Cell 0; in=sage?, out=)
    19381974            sage: C.introspect()
    1939             ['sage?', '']
     1975            [u'sage?', '']
    19401976            sage: C.unset_introspect()
    19411977            sage: C.introspect()
    19421978            False
     
    23112347            files  = ''
    23122348        else:
    23132349            files  = ('&nbsp'*3).join(files)
     2350
     2351        files = unicode_str(files)
     2352        images = unicode_str(images)
     2353
    23142354        return images + files
    23152355
    23162356
  • new file sagenb/notebook/misc.py

    diff --git a/sagenb/notebook/misc.py b/sagenb/notebook/misc.py
    new file mode 100644
    - +  
     1"""
     2Miscellaneus functions used by the Sage Notebook
     3
     4
     5"""
     6
  • sagenb/notebook/notebook.py

    diff --git a/sagenb/notebook/notebook.py b/sagenb/notebook/notebook.py
    a b  
    3232
    3333# Sage libraries
    3434from sagenb.misc.misc import (pad_zeros, cputime, tmp_dir, load, save,
    35                               ignore_nonexistent_files)
     35                              ignore_nonexistent_files, unicode_str)
    3636
    3737# Sage Notebook
    3838import css          # style
     
    934934            return self._user_history[username]
    935935        history = []
    936936        for hunk in self.__storage.load_user_history(username):
    937             if isinstance(hunk, str):
    938                 hunk = unicode(hunk.decode('utf-8', 'ignore'))
     937            hunk = unicode_str(hunk)
    939938            history.append(hunk)
    940939        self._user_history[username] = history
    941940        return history
     
    10521051        W is our newly-created worksheet, with the 2+3 cell in it::
    10531052
    10541053            sage: W.name()
    1055             'foo'
     1054            u'foo'
    10561055            sage: W.cell_list()
    10571056            [TextCell 0: foo, Cell 1; in=2+3, out=]
    10581057        """
     
    12661265            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
    12671266            sage: W = nb.create_new_worksheet('Test', 'admin')
    12681267            sage: W.body()
    1269             '\n\n{{{id=1|\n\n///\n}}}'
     1268            u'\n\n{{{id=1|\n\n///\n}}}'
    12701269            sage: W.save_snapshot('admin')
    12711270            sage: nb.html_worksheet_revision_list('admin', W)
    12721271            u'...Revision...Last Edited...ago...'
     
    12751274
    12761275        return template(os.path.join("html", "notebook", "worksheet_revision_list.html"),
    12771276                        data = data, worksheet = worksheet,
    1278                         worksheet_filename = worksheet.filename(),
     1277                        notebook = self,
    12791278                        username = username)
    12801279
    12811280
     
    13471346
    13481347        return template(os.path.join("html", "notebook", "worksheet_share.html"),
    13491348                        worksheet = worksheet,
    1350                         worksheet_filename = worksheet.filename(),
     1349                        notebook = self,
    13511350                        username = username, other_users = other_users)
    13521351   
    13531352    def html_download_or_delete_datafile(self, ws, username, filename):
     
    13841383            text_file_content = open(os.path.join(ws.data_directory(), filename)).read()
    13851384
    13861385        return template(os.path.join("html", "notebook", "download_or_delete_datafile.html"),
    1387                         worksheet = ws, worksheet_filename = ws.filename(),
     1386                        worksheet = ws, notebook = self,
    13881387                        username = username,
    13891388                        filename_ = filename,
    13901389                        file_is_image = file_is_image,
     
    15041503
    15051504        return template(os.path.join("html", "notebook", "plain_text_window.html"),
    15061505                        worksheet = worksheet,
    1507                         worksheet_filename = worksheet.filename(),
     1506                        notebook = self,
    15081507                        username = username, plain_text = plain_text,
    15091508                        JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE)
    15101509
     
    15321531
    15331532        return template(os.path.join("html", "notebook", "edit_window.html"),
    15341533                        worksheet = worksheet,
    1535                         worksheet_filename = worksheet.filename(),
     1534                        notebook = self,
    15361535                        username = username)
    15371536
    15381537    def html_beforepublish_window(self, worksheet, username):
     
    15691568        """
    15701569        return template(os.path.join("html", "notebook", "beforepublish_window.html"),
    15711570                        worksheet = worksheet,
    1572                         worksheet_filename = worksheet.filename(),
    1573                         username = username,
    1574                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE)
     1571                        notebook = self,
     1572                        username = username)
    15751573
    15761574    def html_afterpublish_window(self, worksheet, username, url, dtime):
    15771575        r"""
     
    15981596
    15991597        return template(os.path.join("html", "notebook", "afterpublish_window.html"),
    16001598                        worksheet = worksheet,
    1601                         worksheet_filename = worksheet.filename(),
    1602                         username = username, url = url, time = time,
    1603                         JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE)
     1599                        notebook = self,
     1600                        username = username, url = url, time = time)
    16041601
    16051602    def html_upload_data_window(self, ws, username):
    16061603        r"""
  • sagenb/notebook/template.py

    diff --git a/sagenb/notebook/template.py b/sagenb/notebook/template.py
    a b  
    1515#                  http://www.gnu.org/licenses/
    1616#############################################################################
    1717
    18 import jinja
    19 
    20 from jinja.filters import stringfilter, simplefilter
     18import jinja2
    2119
    2220import os, re, sys
    2321
    24 from sagenb.misc.misc import SAGE_VERSION, DATA
     22from sagenb.misc.misc import SAGE_VERSION, DATA, unicode_str
    2523from sagenb.notebook.cell import number_of_rows
    2624from sagenb.notebook.jsmath import math_parse
    2725
    2826
    2927TEMPLATE_PATH = os.path.join(DATA, 'sage')
    30 env = jinja.Environment(loader=jinja.FileSystemLoader(TEMPLATE_PATH))
     28env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATE_PATH))
    3129
    3230css_illegal_re = re.compile(r'[^-A-Za-z_0-9]')
    3331
    34 @stringfilter
    3532def css_escape(string):
    3633    r"""
    3734    Returns a string with all characters not legal in a css name
     
    4340
    4441    EXAMPLES::
    4542
    46         sage: from sagenb.notebook.template import env, css_escape
    47         sage: escaper = css_escape()
    48         sage: print(escaper(env, {}, '12abcd'))
    49         12abcd
    50         sage: print(escaper(env, {}, 'abcd'))
    51         abcd
    52         sage: print(escaper(env, {}, r'\'"abcd\'"'))
    53         ---abcd---
    54         sage: print(escaper(env, {}, 'my-invalid/identifier'))
    55         my-invalid-identifier
    56         sage: print(escaper(env, {}, r'quotes"mustbe!escaped'))
    57         quotes-mustbe-escaped
    58 
    59     The following doctests originally accompanied #7269's support for
    60     Jinja2.
    61 
    62         sage: from sagenb.notebook.template import css_escape # not tested
    63         sage: css_escape('abcd')                              # not tested
     43        sage: from sagenb.notebook.template import css_escape
     44        sage: css_escape('abcd')
    6445        'abcd'
    65         sage: css_escape('12abcd')                            # not tested
     46        sage: css_escape('12abcd')
    6647        '12abcd'
    67         sage: css_escape(r'\'"abcd\'"')                       # not tested
     48        sage: css_escape(r'\'"abcd\'"')
    6849        '---abcd---'
    69         sage: css_escape('my-invalid/identifier')             # not tested
     50        sage: css_escape('my-invalid/identifier')
    7051        'my-invalid-identifier'
    71         sage: css_escape(r'quotes"mustbe!escaped')            # not tested
     52        sage: css_escape(r'quotes"mustbe!escaped')
    7253        'quotes-mustbe-escaped'
    7354    """
    7455    return css_illegal_re.sub('-', string)
     
    119100    return ''.join([x if x.isalnum() else '_' for x in name])
    120101
    121102env.filters['css_escape'] = css_escape
    122 env.filters['number_of_rows'] = simplefilter(number_of_rows)
    123 env.filters['clean_name'] = stringfilter(clean_name)
    124 env.filters['prettify_time_ago'] = simplefilter(prettify_time_ago)
    125 env.filters['math_parse'] = stringfilter(math_parse)
    126 env.filters['max'] = simplefilter(max)
     103env.filters['number_of_rows'] = number_of_rows
     104env.filters['clean_name'] = clean_name
     105env.filters['prettify_time_ago'] = prettify_time_ago
     106env.filters['math_parse'] = math_parse
     107env.filters['max'] = max
     108env.filters['repr_str'] = lambda x: repr(unicode_str(x))[1:]
    127109
    128110def template(filename, **user_context):
    129111    """
     
    139121      the file's template variables
    140122
    141123    OUTPUT:
    142    
     124
    143125    - a string - the rendered HTML, CSS, etc.
    144126
    145127    EXAMPLES::
     
    164146                       'conf': notebook.conf() if notebook else None}
    165147    try:
    166148        tmpl = env.get_template(filename)
    167     except jinja.exceptions.TemplateNotFound:
     149    except jinja2.exceptions.TemplateNotFound:
    168150        return "Notebook Bug -- missing template %s"%filename
    169151    context = dict(default_context)
    170152    context.update(user_context)
  • sagenb/notebook/twist.py

    diff --git a/sagenb/notebook/twist.py b/sagenb/notebook/twist.py
    a b  
    5252
    5353from sagenb.misc.misc import (SAGE_DOC, DATA, SAGE_VERSION, walltime,
    5454                              tmp_filename, tmp_dir, is_package_installed,
    55                               jsmath_macros)
     55                              jsmath_macros, encoded_str, unicode_str)
    5656
    5757css_path             = os.path.join(DATA, "sage", "css")
    5858image_path           = os.path.join(DATA, "sage", "images")
     
    8282SEP = '___S_A_G_E___'
    8383
    8484def encode_list(v):
    85     return SEP.join([str(x) for x in v])
     85    seq = []
     86    for x in v:
     87        x = encoded_str(x)
     88        seq.append(x)
     89    return SEP.join(seq)
    8690
    8791
    8892
     
    150154    """
    151155    def __init__(self, code=None, headers=None, stream=None):
    152156        if stream is not None:
    153             if isinstance(stream, unicode):
    154                 stream = stream.encode('utf-8', 'ignore')
     157            stream = encoded_str(stream)
    155158        super(Response, self).__init__(code, headers, stream)
    156159
    157160def HTMLResponse(*args, **kwds):
     
    10971100    def render(self, ctx):
    10981101        id = self.id(ctx)
    10991102        if not ctx.args.has_key('input'):
    1100             input = ''
     1103            input = u''
    11011104        else:
    11021105            input = ctx.args['input'][0]
     1106            input = unicode_str(input)
    11031107
    11041108        cell = self.worksheet.new_cell_before(id, input=input)
    11051109        self.worksheet.increase_state_number()
     
    11161120            input = ''
    11171121        else:
    11181122            input = ctx.args['input'][0]
     1123            input = unicode_str(input)
    11191124
    11201125        cell = self.worksheet.new_text_cell_before(id, input=input)
    11211126        s = encode_list([cell.id(), cell.html(editing=True), id])
     
    11321137            input = ''
    11331138        else:
    11341139            input = ctx.args['input'][0]
     1140            input = unicode_str(input)
     1141
    11351142        cell = self.worksheet.new_cell_after(id, input=input)
    11361143        s = encode_list([cell.id(), cell.html(div_wrap=False), id])
    11371144        return HTMLResponse(stream = s)
     
    11461153            input = ''
    11471154        else:
    11481155            input = ctx.args['input'][0]
     1156            input = unicode_str(input)
    11491157
    11501158        cell = self.worksheet.new_text_cell_after(id, input=input)
    11511159        s = encode_list([cell.id(), cell.html(editing=True), id])
     
    12071215        if status == 'd':
    12081216            new_input = cell.changed_input_text()
    12091217            out_html = cell.output_html()
    1210             try:
    1211                 H = "Worksheet '%s' (%s)\n"%(worksheet.name(), time.strftime("%Y-%m-%d at %H:%M",time.localtime(time.time())))
    1212                 H += cell.edit_text(ncols=HISTORY_NCOLS, prompts=False,
    1213                                     max_out=HISTORY_MAX_OUTPUT)
    1214                 notebook.add_to_user_history(H, self.username)
    1215             except UnicodeDecodeError:
    1216                 pass
     1218            H = "Worksheet '%s' (%s)\n"%(worksheet.name(), time.strftime("%Y-%m-%d at %H:%M",time.localtime(time.time())))
     1219            H += cell.edit_text(ncols=HISTORY_NCOLS, prompts=False,
     1220                                max_out=HISTORY_MAX_OUTPUT)
     1221            notebook.add_to_user_history(H, self.username)
    12171222        else:
    12181223            new_input = ''
    12191224            out_html = ''
     
    12591264    def render(self, ctx):
    12601265        id = self.id(ctx)
    12611266        if not ctx.args.has_key('input'):
    1262             input_text = ''
     1267            input_text = u''
    12631268        else:
    12641269            input_text = ctx.args['input'][0]
    12651270            input_text = input_text.replace('\r\n', '\n')   # DOS
     1271            input_text = unicode_str(input_text)
    12661272
    12671273        W = self.worksheet
    12681274        W.increase_state_number()
     
    15461552    """
    15471553    from sagenb.notebook.notebook import sort_worksheet_list
    15481554    typ = args['typ'][0] if 'typ' in args else 'active'
    1549     search = args['search'][0] if 'search' in args else None
     1555    search = unicode_str(args['search'][0]) if 'search' in args else None
    15501556    sort = args['sort'][0] if 'sort' in args else 'last_edited'
    15511557    reverse = (args['reverse'][0] == 'True') if 'reverse' in args else False
    15521558
  • sagenb/notebook/worksheet.py

    diff --git a/sagenb/notebook/worksheet.py b/sagenb/notebook/worksheet.py
    a b  
     1# -*- coding: utf-8 -*-
    12r"""
    23A Worksheet.
    34
     
    4041                              alarm, cancel_alarm, verbose, DOT_SAGENB,
    4142                              walltime, ignore_nonexistent_files,
    4243                              set_restrictive_permissions,
    43                               set_permissive_permissions)
     44                              set_permissive_permissions,
     45                              encoded_str, unicode_str)
    4446
    4547from sagenb.misc.remote_file import get_remote_file
    4648
     
    190192        EXAMPLES: We test the constructor via an indirect doctest::
    191193
    192194            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
    193             sage: W = nb.create_new_worksheet('Test', 'admin')
     195            sage: W = nb.create_new_worksheet('Test with unicode ΫäĻƾṀБ', 'admin')
    194196            sage: W
    195197            admin/0: [Cell 1; in=, out=]
     198
    196199        """
    197200        if name is None:
    198201            # A fresh worksheet
     
    279282            sage: import sagenb.notebook.worksheet
    280283            sage: W = sagenb.notebook.worksheet.Worksheet('test', 0, tmp_dir(), owner='sage')
    281284            sage: sorted((W.basic().items()))
    282             [('auto_publish', False),
    283               ('collaborators', []),
    284               ('id_number', 0),
    285               ('last_change', ('sage', ...)),
    286               ('name', 'test'),
    287               ('owner', 'sage'),
    288               ('pretty_print', False),
    289               ('published_id_number', None),
    290               ('ratings', []),
    291               ('system', None),
    292               ('tags', {'sage': [1]}),
    293               ('viewers', []),
    294               ('worksheet_that_was_published', ('sage', 0))]
     285            [('auto_publish', False), ('collaborators', []), ('id_number', 0), ('last_change', ('sage', ...)), ('name', u'test'), ('owner', 'sage'), ('pretty_print', False), ('published_id_number', None), ('ratings', []), ('system', None), ('tags', {'sage': [1]}), ('viewers', []), ('worksheet_that_was_published', ('sage', 0))]
    295286        """
    296287        try:
    297288            published_id_number = int(os.path.split(self.__published_version)[1])
     
    455446            sage: W.__repr__()
    456447            'admin/0: [Cell 0; in=2+3, out=\n5, Cell 10; in=2+8, out=\n10]'
    457448        """
    458         return '%s/%s: %s'%(self.owner(), self.id_number(), str(self.cell_list()))
     449        return '%s/%s: %s' % (self.owner(), self.id_number(), self.cell_list())
    459450    def __len__(self):
    460451        r"""
    461452        Return the number of cells in this worksheet.
     
    698689            sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb')
    699690            sage: W = nb.create_new_worksheet('A Test Worksheet', 'admin')
    700691            sage: W.name()
    701             'A Test Worksheet'
     692            u'A Test Worksheet'
     693            sage: W = nb.create_new_worksheet('ΫäĻƾṀБ', 'admin')
     694            sage: W.name()
     695            u'\u03ab\xe4\u013b\u01be\u1e40\u0411'
    702696        """
    703697        try:
    704698            return self.__name
    705699        except AttributeError:
    706             self.__name = "Untitled"
     700            self.__name = u"Untitled"
    707701            return self.__name
    708702
    709703    def set_name(self, name):
     
    720714            sage: W = nb.create_new_worksheet('A Test Worksheet', 'admin')
    721715            sage: W.set_name('A renamed worksheet')
    722716            sage: W.name()
    723             'A renamed worksheet'
     717            u'A renamed worksheet'
    724718        """
    725719        if len(name.strip()) == 0:
    726             name = 'Untitled'
     720            name = u'Untitled'
     721        name = unicode_str(name)
    727722        self.__name = name
    728723
    729724    def set_filename_without_owner(self, nm):
     
    19081903        """
    19091904        # Load the worksheet data file from disk.
    19101905        filename = self.worksheet_html_filename()
    1911         r = (self.owner().lower() + ' ' + self.publisher().lower() + ' '
    1912              + self.name().lower() + ' ' + open(filename).read().lower())
     1906        r = (self.owner().lower() + ' ' + self.publisher().lower() + ' ' +
     1907             self.name().lower() + ' ' + open(filename).read().decode('utf-8', 'ignore').lower())
    19131908        # Check that every single word is in the file from disk.
    19141909        for W in split_search_string_into_keywords(search):
     1910            W = unicode_str(W)
    19151911            if W.lower() not in r:
    19161912                # Some word from the text is not in the search list, so
    19171913                # we return False.
     
    19341930        if os.path.exists(worksheet_html) and open(worksheet_html).read() == E:
    19351931            # we already wrote it out...
    19361932            return
    1937         open(filename, 'w').write(bz2.compress(E))
    1938         open(worksheet_html, 'w').write(self.body())
     1933        open(filename, 'w').write(bz2.compress(E.encode('utf-8', 'ignore')))
     1934        open(worksheet_html, 'w').write(self.body().encode('utf-8', 'ignore'))
    19391935        self.limit_snapshots()
    19401936        try:
    19411937            X = self.__saved_by_info
     
    21672163            5, Cell 1; in=2+8, out=
    21682164            10]
    21692165            sage: W.name()
    2170             'Test Edit Save'
     2166            u'Test Edit Save'
    21712167        """
    21722168        # Clear any caching.
    21732169        try:
     
    34853481        """
    34863482        # The extra newline below is necessary, since otherwise source
    34873483        # code introspection doesn't include the last line.
    3488         return 'open("%s","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("%s"),globals())+"\\n"); execfile(os.path.abspath("%s"))'%(CODE_PY, base64.b64encode(s), CODE_PY)
     3484        return 'open("%s","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("%s"),globals())+"\\n"); execfile(os.path.abspath("%s"))'%(CODE_PY, base64.b64encode(s.encode('utf-8', 'ignore')), CODE_PY)
    34893485
    34903486    ##########################################################
    34913487    # Loading and attaching files
     
    36393635            sage: W.get_cell_system(c0)
    36403636            'sage'
    36413637            sage: W.get_cell_system(c1)
    3642             'gap'
     3638            u'gap'
    36433639            sage: W.edit_save('{{{\n%sage\n2+3\n}}}\n\n{{{\nSymmetricGroup(5)\n}}}')
    36443640            sage: W.set_system('gap')
    36453641            sage: c0, c1 = W.cell_list()
    36463642            sage: W.get_cell_system(c0)
    3647             'sage'
     3643            u'sage'
    36483644            sage: W.get_cell_system(c1)
    36493645            'gap'
    36503646        """
     
    36713667            os.makedirs(code)
    36723668        spyx = os.path.abspath(os.path.join(code, 'sage%s.spyx'%id))
    36733669        if not (os.path.exists(spyx) and open(spyx).read() == cmd):
    3674             open(spyx,'w').write(cmd)
     3670            open(spyx,'w').write(cmd.encode('utf-8', 'ignore'))
    36753671        return '_support_.cython_import_all("%s", globals())'%spyx
    36763672
    36773673    def check_for_system_switching(self, input, cell):
     
    37023698            sage: W.edit_save('{{{\n2+3\n}}}\n\n{{{\n%gap\nSymmetricGroup(5)\n}}}')
    37033699            sage: c0, c1 = W.cell_list()
    37043700            sage: W.check_for_system_switching(c0.cleaned_input_text(), c0)
    3705             (False, '2+3')
     3701            (False, u'2+3')
    37063702            sage: W.check_for_system_switching(c1.cleaned_input_text(), c1)
    3707             (True, "print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
     3703            (True, u"print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
    37083704
    37093705        ::
    37103706
     
    37283724            sage: W.set_system('gap')
    37293725            sage: c0, c1 = W.cell_list()
    37303726            sage: W.check_for_system_switching(c0.cleaned_input_text(), c0)
    3731             (False, '2+3')
     3727            (False, u'2+3')
    37323728            sage: W.check_for_system_switching(c1.cleaned_input_text(), c1)
    3733             (True,
    3734              "print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
     3729            (True, u"print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')")
    37353730            sage: c0.evaluate()
    37363731            sage: W.check_comp()  #random output -- depends on the computer's speed
    37373732            ('d', Cell 0; in=%sage
  • sagenb/storage/filesystem_storage.py

    diff --git a/sagenb/storage/filesystem_storage.py b/sagenb/storage/filesystem_storage.py
    a b  
    3939import os
    4040
    4141from abstract_storage import Datastore
    42 from sagenb.misc.misc import set_restrictive_permissions
     42from sagenb.misc.misc import set_restrictive_permissions, encoded_str
    4343
    4444def is_safe(a):
    4545    """
     
    291291            # only save if loaded
    292292            # todo -- add check if changed
    293293            filename = self._worksheet_html_filename(username, id_number)
    294             open(self._abspath(filename),'w').write(worksheet.body())
     294            open(self._abspath(filename),'w').write(worksheet.body().encode('utf-8', 'ignore'))
    295295
    296296    def load_worksheet(self, username, id_number):
    297297        """
     
    339339        if title:
    340340            # change the title
    341341            basic['name'] = title
    342 
     342        basic['name'] = encoded_str(basic['name'])
    343343        # Remove metainformation that perhaps shouldn't be distributed
    344344        for k in ['owner', 'ratings', 'worksheet_that_was_published', 'viewers', 'tags', 'published_id_number',
    345345                  'collaborators', 'auto_publish']:
     
    397397
    398398        worksheet_txt = members[0].name
    399399        W = self.load_worksheet(username, id_number)
    400         W.edit_save_old_format(T.extractfile(worksheet_txt).read())
     400        W.edit_save_old_format(T.extractfile(worksheet_txt).read().decode('utf-8', 'ignore'))
    401401        # '/' is right, since old worksheets always unix
    402402        dir = worksheet_txt.split('/')[0]
    403403           
  • sagenb/testing/notebook_test_case.py

    diff --git a/sagenb/testing/notebook_test_case.py b/sagenb/testing/notebook_test_case.py
    a b  
    380380        is at list page.
    381381        """
    382382        sel = self.selenium
    383         self.wait_in_window('return this.$("a.worksheetname").attr("title").indexOf("{0}") != -1'.format(name),
     383        self.wait_in_window(u'return this.$("a.worksheetname").attr("title").indexOf("{0}") != -1'.format(name),
    384384                           30000)
    385         sel.click('//a[contains(@class, "worksheetname") and contains(@title, "{0}")]'.format(name))
     385        sel.click(u'//a[contains(@class, "worksheetname") and contains(@title, "{0}")]'.format(name))
    386386        sel.wait_for_page_to_load(30000)
    387387
    388388    def share_worksheet(self, collaborators):
  • sagenb/testing/tests/test_worksheet.py

    diff --git a/sagenb/testing/tests/test_worksheet.py b/sagenb/testing/tests/test_worksheet.py
    a b  
    2626        title of corresponding published worksheet has been fixed.
    2727        """
    2828        sel = self.selenium
    29         self.rename_worksheet('To be published')
     29        self.rename_worksheet(u'To be publishedЋĉƸḾ﹢Յй')
    3030        self.publish_worksheet()
    3131        self.save_and_quit()
    3232
    3333        sel.click('link=Published')
    3434        sel.wait_for_page_to_load(30000)
    35         self.open_worksheet_with_name('To be published')
    36         self.assert_(sel.is_element_present('//h1[contains(@class, "title") and contains(text(), "To be published")]'))
     35        self.open_worksheet_with_name(u'To be publishedЋĉƸḾ﹢Յй')
     36        self.assert_(sel.is_element_present(u'//h1[contains(@class, "title") and contains(text(), "To be publishedЋĉƸḾ﹢Յй")]'))
    3737
    3838        sel.open('/home/admin')
    3939        sel.wait_for_page_to_load(30000)
    40         self.open_worksheet_with_name('To be published')
     40        self.open_worksheet_with_name(u'To be publishedЋĉƸḾ﹢Յй')
    4141        self.rename_worksheet('This has been published')
    4242        self.save_and_quit()
    4343
     
    5454        sel.wait_for_page_to_load("30000")
    5555
    5656        sel.type('//textarea[@id="cell_intext"]',
    57                  '''
     57                 u'''
    5858{{{id=1|
    5959print(5 + 5)
     60print(u'ЋĉƸḾ﹢Յй')
    6061///
    616215
     63ЋĉƸḾ﹢Յй
    6264}}}
    6365
    6466{{{id=2|
     
    6971        sel.click('id=button_save')
    7072        sel.wait_for_page_to_load(30000)
    7173
    72         self.assert_(sel.is_element_present('//textarea[@id="cell_input_1" and contains(text(),"print(5 + 5)")]'))
     74        self.assert_(sel.is_element_present(u'//textarea[@id="cell_input_1" and '
     75                                            u'contains(text(),"print(5 + 5)") and '
     76                                            u'contains(text(), "ЋĉƸḾ﹢Յй")]'))
    7377        self.assert_(sel.is_element_present('//textarea[@id="cell_input_2" and contains(text(),"print(13)")]'))
    7478
    75         self.assertEqual(self.get_cell_output(1), u'15')
     79        self.assertEqual(self.get_cell_output(1), u'15\nЋĉƸḾ﹢Յй')
    7680
    7781    def test_7341(self):
    7882        sel = self.selenium
  • sagenb/testing/tests/test_worksheet_list.py

    diff --git a/sagenb/testing/tests/test_worksheet_list.py b/sagenb/testing/tests/test_worksheet_list.py
    a b  
    3131        Tests worksheet creation.
    3232        """
    3333        sel = self.selenium
    34         self.create_new_worksheet('Creating a Worksheet')
     34        self.create_new_worksheet(u'Worksheet Creation - ΫäĻƾṀБ')
    3535
    3636        # Verify that the page has all the requisite elements.
    3737        elements = ('link=Home', 'link=Help', 'link=Worksheet', 'link=Sign out',
     
    5959        sel = self.selenium
    6060
    6161        worksheet_names = [
    62             'Did you just say wondeeerful?',
    63             'My wonderful search phrase',
     62            u'Did you just say ЋĉƸḾ﹢Յй?',
     63            u'My ЋĉƸḾ﹢Յй search phrase',
    6464            'Not a search target'
    6565            ]
    6666
     
    7070            self.save_and_quit()
    7171
    7272        pages = ('/home/admin/', '/pub')
    73 
     73        import pdb; pdb.set_trace()
    7474        for page in pages:
    7575            sel.open(page)
    76             self._search('wonderful')
    77             self.assert_(sel.is_element_present('//a[@class="worksheetname" and contains(text(), "My wonderful search phrase")]'),
     76            self._search(u'ЋĉƸḾ﹢Յй')
     77            self.assert_(sel.is_element_present(u'//a[@class="worksheetname" and contains(text(), "My ЋĉƸḾ﹢Յй search phrase")]'),
    7878                         'Search phrase not found on %s' % page)
    7979            self.failIf(sel.is_element_present('//a[@class="worksheetname" and contains(text(), "Not a search target")]'),
    8080                        'Non-matching search results found on %s' % page)
  • sagenb/todo.txt

    diff --git a/sagenb/todo.txt b/sagenb/todo.txt
    a b  
    77    sage: notebook()  # then let the notebook start up, then hit ctrl-c
    88    sage: pwd -->  '/Users/palmieri/.sage' 
    99
    10 [ ] rate a worksheet -- note that the top of the browser (title) says
    11 error, though in fact there is no error.
    12 
    1310[ ] admin should *NOT* see all users worksheets.  This is not good, e.g.,
    1411when there are 50,000 worksheets!
    1512
     
    7067[ ] "untitled renaming".  Make it an option in the user confs, which
    7168is on by default, by you can turn it off.
    7269
    73 [ ] add message to the top of each *old* sage notebook .py file
    74  stating that one should work on sagenb instead.  This is a patch to
    75  the core Sage library.
    76 
    77 [ ] fix all doctests in sagenb code and make a patch against core
    78 sage library that imports enough of sagenb by default so I can
    79 run all these doctests. 
    8070
    8171[ ] get coverage to 100%.
    8272
    83 [ ] change to 100% html format for worksheets.
    8473
    8574[ ] we can make it so that if worksheet.html file changes on disk but
    8675not currently open, then when reopen it uses the new version from
     
    10998
    11099[ ] Jonathan Gutow -- redo how jmol works
    111100
    112 [ ] notebook docs -- something in "doc/en/sagenb"
     101
    113102
    114103[ ] maybe get rid of list of 'Sage Users' when publishing worksheets --
    115104that's not appropriate given how sage has grown.
     
    139128[ ] ldap support (see, eg., http://math.univ-lyon1.fr/~tdumont/sage)  but make sure to first
    140129    abstract away authentication first so it is much CLEARER.
    141130
    142 [ ] automated testing -- "Windmill seems to be more popular now -- especially with Python stuff "
    143131
    144132[ ] find a way to provide same info as data directory but without making it super-permissive.
    145133    Maybe I can make an api for getting files from a data location or something...
     
    483471
    484472[x] When saving a worksheet, the default filename has "..." in it.
    485473
     474[x] add message to the top of each *old* sage notebook .py file
     475 stating that one should work on sagenb instead.  This is a patch to
     476 the core Sage library.
     477
     478[x] fix all doctests in sagenb code and make a patch against core
     479sage library that imports enough of sagenb by default so I can
     480run all these doctests. 
     481
     482[x] rate a worksheet -- note that the top of the browser (title) says
     483error, though in fact there is no error.
     484
     485[x] change to 100% html format for worksheets.
     486
     487[x] notebook docs -- something in "doc/en/sagenb"
     488
     489[x] automated testing -- "Windmill seems to be more popular now -- especially with Python stuff "
  • sass/src/_topbar.sass

    diff --git a/sass/src/_topbar.sass b/sass/src/_topbar.sass
    a b  
    8787
    8888
    8989div
    90   &#user-controls
     90  &#user-main-controls
    9191    +clearfix
    9292    :clear both
    9393    :border-bottom 1px solid #c9d7f1
  • new file sass/src/_worksheet_listing.sass

    diff --git a/sass/src/_worksheet_listing.sass b/sass/src/_worksheet_listing.sass
    new file mode 100644
    - +  
     1/************ User Home (Worksheet listing) **************************/
     2
     3#worksheet-listing-page
     4  #welcome-message
     5    :text-align center
     6    :padding 1em
     7
     8.ratingmsg
     9  :color #112abb
     10  :padding 0.3em
     11  :font-size 14px
     12
     13.pubmsg
     14  :font-family sans-serif
     15  :color #112abb
     16  :padding 0.3em
     17  :font-size 12px
     18
     19#worksheet-list
     20  :clear both
     21  :width 100%
     22  thead
     23    :background-color #e8eef7
     24  td.checkbox
     25    :padding 4px
     26
     27.controls a, .usercontrol
     28  :color #112abb
     29  :font-size 14px
     30  :text-decoration underline
     31
     32  &:hover
     33    :cursor pointer
     34
     35.controls
     36  span
     37    :color #112abb
     38    :padding 0.3em
     39    :font-size 14px
     40
     41
     42.user-controls a, .boldusercontrol
     43  :color #112abb
     44  :font-weight bold
     45  :font-size 14px
     46
     47.user-controls a, .controls a, .controls span
     48  :padding 0.3em
     49
     50a
     51  &.control, &.control-select
     52    :background-color #7799bb
     53    :font-family sans-serif
     54    :color #ffffff
     55    :padding-top 0.25em
     56    :padding-bottom 0.25em
     57    :padding-left 0.5em
     58    :padding-right 0.5em
     59    :font-size 15px
     60    :font-weight bold
     61    :text-decoration none
     62
     63  &.control:hover
     64    :cursor pointer
     65
     66  &.control-select
     67    :background-color #4477aa
     68
     69    &:hover
     70      :cursor pointer
     71
     72
     73.sharebar
     74  :background-color #4477aa
     75  :font-family sans-serif
     76  :color #ffffff
     77  :padding-top 0.5em
     78  :padding-bottom 0.5em
     79  :padding-left 2em
     80  :font-size 1.25em
     81  :font-weight bold
     82
     83
     84textarea.edit
     85  :font-family courier, monospace
     86  :font-size 10pt
     87  :border 1px solid #8cacbb
     88  :color black
     89  :background-color white
     90  :padding 3px
     91  :overflow auto
     92  :margin-top 0.5em
     93
     94
     95a.listcontrol
     96  :padding 1ex
     97  :color #112abb
     98  :font-weight bold
     99  :font-size 14px
     100  :text-decoration none
     101
     102
     103hr
     104  &.usercontrol
     105    :border 0
     106    :width 99%
     107    :color #c9d7f1
     108    :background-color #c9d7f1
     109    :height 1px
     110
     111  &.greybar hr.negative_greybar
     112    :border 0
     113    :width 99%
     114    :color #aaa
     115    :background-color #aaa
     116    :height 1px
     117
     118  &.negative_greybar
     119    :top -1em
     120    :position relative
     121
     122
     123span
     124  &.checkcol
     125    :position relative
     126    :left 0%
     127    :width 10%
     128
     129  &.leftcol
     130    :position relative
     131    :left 10%
     132    :width 20%
     133
     134  &.middlecol
     135    :position relative
     136    :left 30%
     137    :width 20%
     138
     139  &.rightcol
     140    :position relative
     141    :left 50%
     142    :width 20%
     143
     144
     145tr.greybox
     146  :background-color #e8eef7
     147
     148
     149td.entry
     150  :padding 4px
     151
     152
     153div.thinspace
     154  :border 0
     155  :height 2px
     156
     157
     158tr.thingreybox
     159  :background-color #aaa
     160
     161
     162div.ultrathinspace
     163  :border 0
     164  :height 0px
     165
     166
     167.lastedit
     168  :font-family sans-serif
     169  :font-size 10px
     170  :color #717171
     171
     172.revs
     173  :font-family sans-serif
     174  :font-size 12px
     175  :font-weight bold
     176  :color #333333
     177
     178.users
     179  :font-family sans-serif
     180  :font-size 13px
     181  :color #222222
     182
     183
     184a.share
     185  :font-family sans-serif
     186  :font-size 10px
     187  :color #7777cc
     188
     189
     190select
     191  &.worksheet
     192    :width 6em
     193    :border #aaaaaa
     194    :border-style solid
     195    :border-top-width 1px
     196    :border-right-width 1px
     197    :border-bottom-width 1px
     198    :border-left-width 1px
     199
     200  &.worksheet_list, &.worksheet_edit
     201    :width 5em
     202    :border #aaaaaa
     203    :border-style solid
     204    :border-top-width 1px
     205    :border-right-width 1px
     206    :border-bottom-width 1px
     207    :border-left-width 1px
     208
     209
     210td
     211  &.worksheet_link
     212    :font-family sans-serif
     213    :font-size 12px
     214    :font-weight bold
     215    :color #000000
     216
     217  &.archived_worksheet_link, &.owner_collab, &.last_edited
     218    :font-family sans-serif
     219    :font-size 12px
     220    :color #000000
     221
     222
     223span.addtext
     224  :font-family sans-serif
     225  :font-size 13px
     226  :color #222
     227
     228
     229textarea.plaintextedit
     230  :font-family courier, monospace
     231  :font-size 10pt
     232  :border 1px solid #8cacbb
     233  :color black
     234  :background-color white
     235  :overflow auto
     236  :width 99%
     237  :height 60%
     238
     239
     240pre.plaintext
     241  :overflow auto
     242  :font-family courier, monospace
     243  :font-size 10pt
     244  :border 1px solid #8cacbb
     245  :color black
     246  :background-color white
     247  :margin-top 0.5em
     248
     249
     250div.docidx
     251  :text-align center
     252  :font-family sans-serif
     253  :font-size 16px
     254  :color #222
     255  :font-weight bold
     256
     257
     258span
     259  &.ping
     260    :display none
     261
     262  &.pingdown
     263    :font-family sans-serif
     264    :font-size 15px
     265    :font-weight bold
     266    :color white
     267    :background-color #990000
     268    :margin-left 1em
  • sass/src/main.sass

    diff --git a/sass/src/main.sass b/sass/src/main.sass
    a b  
    11841184  :position relative
    11851185  :top -20ex
    11861186  :right 0ex
    1187 
     1187t
    11881188
    11891189.thin-right
    11901190  :position absolute
     
    11921192  :right 0
    11931193  :width 70%
    11941194
    1195 /************ User Home (Worksheet listing) **************************/
    1196 
    1197 .ratingmsg
    1198   :color #112abb
    1199   :padding 0.3em
    1200   :font-size 14px
    1201 
    1202 .pubmsg
    1203   :font-family sans-serif
    1204   :color #112abb
    1205   :padding 0.3em
    1206   :font-size 12px
    1207 
    1208 #worksheet-list
    1209   :clear both
    1210   :width 100%
    1211   thead
    1212     :background-color #e8eef7
    1213   td.checkbox
    1214     :padding 4px
    1215 
    1216 .controls a, .usercontrol
    1217   :color #112abb
    1218   :font-size 14px
    1219   :text-decoration underline
    1220 
    1221   &:hover
    1222     :cursor pointer
    1223 
    1224 .controls
    1225   span
    1226     :color #112abb
    1227     :padding 0.3em
    1228     :font-size 14px
    1229 
    1230 
    1231 .user-controls a, .boldusercontrol
    1232   :color #112abb
    1233   :font-weight bold
    1234   :font-size 14px
    1235 
    1236 .user-controls a, .controls a, .controls span
    1237   :padding 0.3em
    1238 
    1239 a
    1240   &.control, &.control-select
    1241     :background-color #7799bb
    1242     :font-family sans-serif
    1243     :color #ffffff
    1244     :padding-top 0.25em
    1245     :padding-bottom 0.25em
    1246     :padding-left 0.5em
    1247     :padding-right 0.5em
    1248     :font-size 15px
    1249     :font-weight bold
    1250     :text-decoration none
    1251 
    1252   &.control:hover
    1253     :cursor pointer
    1254 
    1255   &.control-select
    1256     :background-color #4477aa
    1257 
    1258     &:hover
    1259       :cursor pointer
    1260 
    1261 
    1262 .sharebar
    1263   :background-color #4477aa
    1264   :font-family sans-serif
    1265   :color #ffffff
    1266   :padding-top 0.5em
    1267   :padding-bottom 0.5em
    1268   :padding-left 2em
    1269   :font-size 1.25em
    1270   :font-weight bold
    1271 
    1272 
    1273 textarea.edit
    1274   :font-family courier, monospace
    1275   :font-size 10pt
    1276   :border 1px solid #8cacbb
    1277   :color black
    1278   :background-color white
    1279   :padding 3px
    1280   :overflow auto
    1281   :margin-top 0.5em
    1282 
    1283 
    1284 a.listcontrol
    1285   :padding 1ex
    1286   :color #112abb
    1287   :font-weight bold
    1288   :font-size 14px
    1289   :text-decoration none
    1290 
    1291 
    1292 hr
    1293   &.usercontrol
    1294     :border 0
    1295     :width 99%
    1296     :color #c9d7f1
    1297     :background-color #c9d7f1
    1298     :height 1px
    1299 
    1300   &.greybar hr.negative_greybar
    1301     :border 0
    1302     :width 99%
    1303     :color #aaa
    1304     :background-color #aaa
    1305     :height 1px
    1306 
    1307   &.negative_greybar
    1308     :top -1em
    1309     :position relative
    1310 
    1311 
    1312 span
    1313   &.checkcol
    1314     :position relative
    1315     :left 0%
    1316     :width 10%
    1317 
    1318   &.leftcol
    1319     :position relative
    1320     :left 10%
    1321     :width 20%
    1322 
    1323   &.middlecol
    1324     :position relative
    1325     :left 30%
    1326     :width 20%
    1327 
    1328   &.rightcol
    1329     :position relative
    1330     :left 50%
    1331     :width 20%
    1332 
    1333 
    1334 tr.greybox
    1335   :background-color #e8eef7
    1336 
    1337 
    1338 td.entry
    1339   :padding 4px
    1340 
    1341 
    1342 div.thinspace
    1343   :border 0
    1344   :height 2px
    1345 
    1346 
    1347 tr.thingreybox
    1348   :background-color #aaa
    1349 
    1350 
    1351 div.ultrathinspace
    1352   :border 0
    1353   :height 0px
    1354 
    1355 
    1356 .lastedit
    1357   :font-family sans-serif
    1358   :font-size 10px
    1359   :color #717171
    1360 
    1361 .revs
    1362   :font-family sans-serif
    1363   :font-size 12px
    1364   :font-weight bold
    1365   :color #333333
    1366 
    1367 .users
    1368   :font-family sans-serif
    1369   :font-size 13px
    1370   :color #222222
    1371 
    1372 
    1373 a.share
    1374   :font-family sans-serif
    1375   :font-size 10px
    1376   :color #7777cc
    1377 
    1378 
    1379 select
    1380   &.worksheet
    1381     :width 6em
    1382     :border #aaaaaa
    1383     :border-style solid
    1384     :border-top-width 1px
    1385     :border-right-width 1px
    1386     :border-bottom-width 1px
    1387     :border-left-width 1px
    1388 
    1389   &.worksheet_list, &.worksheet_edit
    1390     :width 5em
    1391     :border #aaaaaa
    1392     :border-style solid
    1393     :border-top-width 1px
    1394     :border-right-width 1px
    1395     :border-bottom-width 1px
    1396     :border-left-width 1px
    1397 
    1398 
    1399 td
    1400   &.worksheet_link
    1401     :font-family sans-serif
    1402     :font-size 12px
    1403     :font-weight bold
    1404     :color #000000
    1405 
    1406   &.archived_worksheet_link, &.owner_collab, &.last_edited
    1407     :font-family sans-serif
    1408     :font-size 12px
    1409     :color #000000
    1410 
    1411 
    1412 span.addtext
    1413   :font-family sans-serif
    1414   :font-size 13px
    1415   :color #222
    1416 
    1417 
    1418 textarea.plaintextedit
    1419   :font-family courier, monospace
    1420   :font-size 10pt
    1421   :border 1px solid #8cacbb
    1422   :color black
    1423   :background-color white
    1424   :overflow auto
    1425   :width 99%
    1426   :height 60%
    1427 
    1428 
    1429 pre.plaintext
    1430   :overflow auto
    1431   :font-family courier, monospace
    1432   :font-size 10pt
    1433   :border 1px solid #8cacbb
    1434   :color black
    1435   :background-color white
    1436   :margin-top 0.5em
    1437 
    1438 
    1439 div.docidx
    1440   :text-align center
    1441   :font-family sans-serif
    1442   :font-size 16px
    1443   :color #222
    1444   :font-weight bold
    1445 
    1446 
    1447 span
    1448   &.ping
    1449     :display none
    1450 
    1451   &.pingdown
    1452     :font-family sans-serif
    1453     :font-size 15px
    1454     :font-weight bold
    1455     :color white
    1456     :background-color #990000
    1457     :margin-left 1em
    1458 
     1195@import worksheet_listing.sass
    14591196@import prettify.sass
    14601197@import source.sass
    14611198@import print_worksheet.sass