# HG changeset patch # User Mitesh Patel # Date 1262813598 28800 # Node ID 20feb0805203f18d1eca6c8a1aadc5b63e2ed335 # Parent 9e305f6f7fb9b491ed72225cbcb00e158e47200f [mq]: trac_7249_jinja2.patch diff --git a/sagenb/data/sage/html/base.html b/sagenb/data/sage/html/base.html --- a/sagenb/data/sage/html/base.html +++ b/sagenb/data/sage/html/base.html @@ -1,4 +1,4 @@ -{%- macro render_title -%}{% block title %}{% endblock %}{%- endmacro -%} +{%- macro render_title() -%}{% block title %}{% endblock %}{%- endmacro -%} diff --git a/sagenb/data/sage/html/notebook/cell.html b/sagenb/data/sage/html/notebook/cell.html --- a/sagenb/data/sage/html/notebook/cell.html +++ b/sagenb/data/sage/html/notebook/cell.html @@ -12,12 +12,14 @@ INPUT: print or not. #} {% if do_print %} - {% set wrap = 68 %} - {% set div_wrap = 68 %} + {% set wrap_ = 68 %} + {% set div_wrap_ = 68 %} +{% else %} + {% set wrap_ = wrap %} + {% set div_wrap_ = div_wrap %} {% endif %} {% set cell_cls = "cell_evaluated" if cell.evaluated() or do_print else "cell_not_evaluated" %} - -{% if div_wrap %} +{% if div_wrap_ %}
{% endif %} @@ -50,7 +52,7 @@ INPUT: onFocus="cell_focused(this, {{ cell.id() }}); return true;">{{ cell.input_text().rstrip() }} evaluate @@ -79,7 +81,7 @@ INPUT: {% if cell.introspect() %} {{ cell.output_text(0, html=true) }} {% else %} - {{ cell.output_text(wrap, html=true) }} + {{ cell.output_text(wrap_, html=true) }} {% endif %}
{% if not do_print %} @@ -99,7 +101,7 @@ INPUT:
{% endif %} -{% if div_wrap %} +{% if div_wrap_ %} {% endif %} diff --git a/sagenb/interfaces/expect.py b/sagenb/interfaces/expect.py --- a/sagenb/interfaces/expect.py +++ b/sagenb/interfaces/expect.py @@ -241,11 +241,11 @@ class WorksheetProcess_ExpectImplementat # The magic comment at the very start of the file allows utf8 characters. open(self._filename,'w').write( '# -*- coding: utf_8 -*-\nimport sys;sys.ps1="%s";print "START%s"\n'%( - self._prompt, self._number) + displayhook_hack(string)) + self._prompt, self._number) + displayhook_hack(string).encode('utf-8', 'ignore')) try: self._expect.sendline('\nimport os;os.chdir("%s");\nexecfile("%s")'%( remote, sage_input)) - except OSError, msg: + except OSError as msg: self._is_computing = False self._so_far = str(msg) diff --git a/sagenb/misc/sageinspect.py b/sagenb/misc/sageinspect.py --- a/sagenb/misc/sageinspect.py +++ b/sagenb/misc/sageinspect.py @@ -483,8 +483,11 @@ def sage_getdoc(obj, obj_name=''): if r is None: return '' - - s = format(str(r), embedded=EMBEDDED_MODE) + if isinstance(r, unicode): + r = r.encode('utf-8', 'ignore') + else: + r = str(r) + s = format(r, embedded=EMBEDDED_MODE) # If there is a Cython embedded position, it needs to be stripped pos = _extract_embedded_position(s) diff --git a/sagenb/misc/support.py b/sagenb/misc/support.py --- a/sagenb/misc/support.py +++ b/sagenb/misc/support.py @@ -331,7 +331,7 @@ def source_code(s, globs, system='sage') filename = sageinspect.sage_getfile(obj) try: lines, lineno = sageinspect.sage_getsourcelines(obj, is_binary=False) - except IOError, msg: + except IOError as msg: return html_markup(str(msg)) src = indent.join(lines) src = indent + format_src(src) @@ -467,6 +467,8 @@ def syseval(system, cmd, dir=None): if dir: if hasattr(system.__class__, 'chdir'): system.chdir(dir) + if isinstance(cmd, unicode): + cmd = cmd.encode('utf-8', 'ignore') return system.eval(cmd, sage_globals, locals = sage_globals) ###################################################################### diff --git a/sagenb/notebook/cell.py b/sagenb/notebook/cell.py --- a/sagenb/notebook/cell.py +++ b/sagenb/notebook/cell.py @@ -91,6 +91,8 @@ class TextCell(Cell_generic): sage: C == loads(dumps(C)) True """ + if isinstance(text, str): + text = text.decode('utf-8', 'ignore') self.__id = int(id) self.__text = text self.__worksheet = worksheet @@ -103,7 +105,7 @@ class TextCell(Cell_generic): sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None) sage: C.__repr__() - 'TextCell 0: 2+3' + u'TextCell 0: 2+3' """ return "TextCell %s: %s"%(self.__id, self.__text) @@ -136,6 +138,8 @@ class TextCell(Cell_generic): sage: C TextCell 0: 3+2 """ + if isinstance(input_text, str): + input_text = input_text.decode('utf-8', 'ignore') self.__text = input_text def set_worksheet(self, worksheet, id=None): @@ -192,7 +196,10 @@ class TextCell(Cell_generic): EXAMPLES:: - sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None) + sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') + sage: nb.add_user('sage','sage','sage@sagemath.org',force=True) + sage: W = nb.create_new_worksheet('Test', 'sage') + sage: C = sagenb.notebook.cell.TextCell(0, '2+3', W) sage: C.html() u'...text_cell...2+3...' sage: C.set_input_text("$2+3$") @@ -214,7 +221,7 @@ class TextCell(Cell_generic): sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None) sage: C.plain_text() - '2+3' + u'2+3' """ return self.__text @@ -226,7 +233,7 @@ class TextCell(Cell_generic): sage: C = sagenb.notebook.cell.TextCell(0, '2+3', None) sage: C.edit_text() - '2+3' + u'2+3' """ return self.__text @@ -297,8 +304,17 @@ class Cell(Cell_generic): sage: C == loads(dumps(C)) True """ + if isinstance(out, str): + out = out.encode('utf-8', 'ignore') + else: + out = unicode(out) + if isinstance(input, str): + input = input.encode('utf-8', 'ignore') + else: + input = unicode(input) + self.__id = int(id) - self.__out = str(out).replace('\r','') + self.__out = out.replace('\r','') self.__worksheet = worksheet self.__interrupted = False self.__completions = False @@ -355,8 +371,8 @@ class Cell(Cell_generic): sage: C Cell 0; in=2+3, out= """ - self.__out = '' - self.__out_html = '' + self.__out = u'' + self.__out_html = u'' self.__evaluated = False def evaluated(self): @@ -555,7 +571,7 @@ class Cell(Cell_generic): sage: nb.delete() """ if self.is_interactive_cell(): - self.__out_html = "" + self.__out_html = u"" else: self.__out_html = self.files_html(output) @@ -735,9 +751,13 @@ class Cell(Cell_generic): """ if ncols == 0: ncols = self.word_wrap_cols() - s = '' - + s = u'' + + if isinstance(self.__in, str): + self.__in = self.__in.decode('utf-8', 'ignore') + input_lines = self.__in + pr = 'sage: ' if prompts: @@ -810,10 +830,10 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None) sage: C.edit_text() - '{{{id=0|\n2+3\n///\n5\n}}}' + u'{{{id=0|\n2+3\n///\n5\n}}}' """ s = self.plain_text(ncols, prompts, max_out) - return '{{{id=%s|\n%s\n}}}'%(self.id(), s) + return u'{{{id=%s|\n%s\n}}}'%(self.id(), s) def is_last(self): """ @@ -988,7 +1008,7 @@ class Cell(Cell_generic): 0 sage: C.set_input_text('3+3') sage: C.input_text() - '3+3' + u'3+3' sage: C.evaluated() False sage: C.version() @@ -997,6 +1017,9 @@ class Cell(Cell_generic): sage: nb.delete() """ # Stuff to deal with interact + if isinstance(input, str): + input = input.decode('utf-8', 'ignore') + if input.startswith('%__sage_interact__'): self.interact = input[len('%__sage_interact__')+1:] self.__version = self.version() + 1 @@ -1028,7 +1051,7 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None) sage: C.input_text() - '2+3' + u'2+3' """ return self.__in @@ -1042,7 +1065,7 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None) sage: C.cleaned_input_text() - '2+3' + u'2+3' """ if self.is_interacting(): return self.interact @@ -1060,9 +1083,9 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None) sage: C.parse_percent_directives() - '2+3' + u'2+3' sage: C.percent_directives() - ['hide', 'maxima'] + [u'hide', u'maxima'] """ self._system = None text = self.input_text().splitlines() @@ -1097,7 +1120,7 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '%hide\n%maxima\n2+3', '5', None) sage: C.percent_directives() - ['hide', 'maxima'] + [u'hide', u'maxima'] """ return self._percent_directives @@ -1115,7 +1138,7 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '%maxima\n2+3', '5', None) sage: C.system() - 'maxima' + u'maxima' sage: prefixes = ['%hide', '%time', ''] sage: cells = [sagenb.notebook.cell.Cell(0, '%s\n2+3'%prefix, '5', None) for prefix in prefixes] sage: [(C, C.system()) for C in cells if C.system() is not None] @@ -1155,9 +1178,9 @@ class Cell(Cell_generic): '' sage: C.set_changed_input_text('3+3') sage: C.input_text() - '3+3' + u'3+3' sage: C.changed_input_text() - '3+3' + u'3+3' sage: C.changed_input_text() '' sage: C.version() @@ -1180,10 +1203,12 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', None) sage: C.set_changed_input_text('3+3') sage: C.input_text() - '3+3' + u'3+3' sage: C.changed_input_text() - '3+3' + u'3+3' """ + if isinstance(new_text,str): + new_text = new_text.decode('utf-8', 'ignore') self.__changed_input = new_text self.__in = new_text @@ -1200,9 +1225,13 @@ class Cell(Cell_generic): sage: len(C.plain_text()) 12 """ + if isinstance(output, str): + output = output.decode('utf-8', 'ignore') + if isinstance(html, str): + html = html.decode('utf-8', 'ignore') if output.count('') > 1: - html = '

WARNING: multiple @interacts in one cell disabled (not yet implemented).

' - output = '' + html = u'

WARNING: multiple @interacts in one cell disabled (not yet implemented).

' + output = u'' # In interacting mode, we just save the computed output # (do not overwrite). @@ -1222,7 +1251,7 @@ class Cell(Cell_generic): url = "" if not self.computing(): file = os.path.join(self.directory(), "full_output.txt") - open(file,"w").write(output) + open(file,"w").write(output.encode('utf-8', 'ignore')) url = "full_output.txt"%( self.url_to_self()) html+="
" + url @@ -1265,7 +1294,7 @@ class Cell(Cell_generic): '' sage: C.set_output_text('5', '5') sage: C.output_html() - '5' + u'5' """ try: return self.__out_html @@ -1320,11 +1349,11 @@ class Cell(Cell_generic): sage: W = nb.create_new_worksheet('Test', 'sage') sage: C = sagenb.notebook.cell.Cell(0, '2+3', '5', W) sage: C.output_text() - '
5
' + u'
5
' sage: C.output_text(html=False) - '
5
' + u'
5
' sage: C.output_text(raw=True) - '5' + u'5' """ if allow_interact and hasattr(self, '_interact_output'): # Get the input template @@ -1348,13 +1377,16 @@ class Cell(Cell_generic): # during interact. return '' + if isinstance(self.__out, str): + self.__out = self.__out.decode('utf-8', 'ignore') + is_interact = self.is_interactive_cell() if is_interact and ncols == 0: if 'Traceback (most recent call last)' in self.__out: s = self.__out.replace('cell-interact','') is_interact=False else: - return '

Click to the left again to hide and once more to show the dynamic interactive window

' + return u'

Click to the left again to hide and once more to show the dynamic interactive window

' else: s = self.__out @@ -1448,7 +1480,7 @@ class Cell(Cell_generic): sage: C = sagenb.notebook.cell.Cell(0, "%html\nTest HTML", None, None) sage: C.system() - 'html' + u'html' sage: C.is_html() True sage: C = sagenb.notebook.cell.Cell(0, "Test HTML", None, None) @@ -1495,13 +1527,15 @@ class Cell(Cell_generic): ('d', Cell 0; in=sage?, out=) sage: C.set_introspect_html('foobar') sage: C.introspect_html() - 'foobar' + u'foobar' sage: C.set_introspect_html('`foobar`') sage: C.introspect_html() - '`foobar`' + u'`foobar`' sage: W.quit() sage: nb.delete() """ + if isinstance(html, str): + html = html.decode('utf-8', 'ignore') self.__introspect_html = html self.introspection_status = 'done' @@ -1542,8 +1576,8 @@ class Cell(Cell_generic): try: return self.__introspect_html except AttributeError: - self.__introspect_html = '' - return '' + self.__introspect_html = u'' + return u'' def introspect(self): """ @@ -1561,7 +1595,7 @@ class Cell(Cell_generic): sage: W.check_comp(9999) # random output -- depends on computer speed ('d', Cell 0; in=sage?, out=) sage: C.introspect() - ['sage?', ''] + [u'sage?', ''] sage: W.quit() sage: nb.delete() """ @@ -1586,7 +1620,7 @@ class Cell(Cell_generic): sage: W.check_comp(9999) # random output -- depends on computer speed ('d', Cell 0; in=sage?, out=) sage: C.introspect() - ['sage?', ''] + [u'sage?', ''] sage: C.unset_introspect() sage: C.introspect() False @@ -1908,6 +1942,10 @@ class Cell(Cell_generic): files = '' else: files = (' '*3).join(files) + if isinstance(files, str): + files = files.decode('utf-8', 'ignore') + if isinstance(images, str): + iamges = images.decode('utf-8', 'ignore') return images + files ######## diff --git a/sagenb/notebook/notebook.py b/sagenb/notebook/notebook.py --- a/sagenb/notebook/notebook.py +++ b/sagenb/notebook/notebook.py @@ -1052,7 +1052,7 @@ class Notebook(object): W is our newly-created worksheet, with the 2+3 cell in it:: sage: W.name() - 'foo' + u'foo' sage: W.cell_list() [TextCell 0: foo, Cell 1; in=2+3, out=] """ @@ -1266,7 +1266,7 @@ class Notebook(object): sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') sage: W = nb.create_new_worksheet('Test', 'admin') sage: W.body() - '\n\n{{{id=1|\n\n///\n}}}' + u'\n\n{{{id=1|\n\n///\n}}}' sage: W.save_snapshot('admin') sage: nb.html_worksheet_revision_list('admin', W) u'...Revision...Last Edited...seconds...ago...' @@ -1275,7 +1275,7 @@ class Notebook(object): return template(os.path.join("html", "notebook", "worksheet_revision_list.html"), data = data, worksheet = worksheet, - worksheet_filename = worksheet.filename(), + notebook = self, username = username) @@ -1347,7 +1347,7 @@ class Notebook(object): return template(os.path.join("html", "notebook", "worksheet_share.html"), worksheet = worksheet, - worksheet_filename = worksheet.filename(), + notebook = self, username = username, other_users = other_users) def html_download_or_delete_datafile(self, ws, username, filename): @@ -1384,7 +1384,7 @@ class Notebook(object): text_file_content = open(os.path.join(ws.data_directory(), filename)).read() return template(os.path.join("html", "notebook", "download_or_delete_datafile.html"), - worksheet = ws, worksheet_filename = ws.filename(), + worksheet = ws, notebook = self, username = username, filename_ = filename, file_is_image = file_is_image, @@ -1504,7 +1504,7 @@ class Notebook(object): return template(os.path.join("html", "notebook", "plain_text_window.html"), worksheet = worksheet, - worksheet_filename = worksheet.filename(), + notebook = self, username = username, plain_text = plain_text, JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) @@ -1532,7 +1532,7 @@ class Notebook(object): return template(os.path.join("html", "notebook", "edit_window.html"), worksheet = worksheet, - worksheet_filename = worksheet.filename(), + notebook = self, username = username) def html_beforepublish_window(self, worksheet, username): @@ -1569,9 +1569,8 @@ class Notebook(object): """ return template(os.path.join("html", "notebook", "beforepublish_window.html"), worksheet = worksheet, - worksheet_filename = worksheet.filename(), - username = username, - JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) + notebook = self, + username = username) def html_afterpublish_window(self, worksheet, username, url, dtime): r""" @@ -1598,9 +1597,8 @@ class Notebook(object): return template(os.path.join("html", "notebook", "afterpublish_window.html"), worksheet = worksheet, - worksheet_filename = worksheet.filename(), - username = username, url = url, time = time, - JSMATH = JSMATH, JEDITABLE_TINYMCE = JEDITABLE_TINYMCE) + notebook = self, + username = username, url = url, time = time) def html_upload_data_window(self, ws, username): r""" diff --git a/sagenb/notebook/template.py b/sagenb/notebook/template.py --- a/sagenb/notebook/template.py +++ b/sagenb/notebook/template.py @@ -15,9 +15,7 @@ AUTHORS: # http://www.gnu.org/licenses/ ############################################################################# -import jinja - -from jinja.filters import stringfilter, simplefilter +import jinja2 import os, re, sys @@ -27,11 +25,10 @@ from sagenb.notebook.jsmath import math_ TEMPLATE_PATH = os.path.join(DATA, 'sage') -env = jinja.Environment(loader=jinja.FileSystemLoader(TEMPLATE_PATH)) +env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATE_PATH)) css_illegal_re = re.compile(r'[^-A-Za-z_0-9]') -@stringfilter def css_escape(string): r""" Returns a string with all characters not legal in a css name @@ -43,32 +40,16 @@ def css_escape(string): EXAMPLES:: - sage: from sagenb.notebook.template import env, css_escape - sage: escaper = css_escape() - sage: print(escaper(env, {}, '12abcd')) - 12abcd - sage: print(escaper(env, {}, 'abcd')) - abcd - sage: print(escaper(env, {}, r'\'"abcd\'"')) - ---abcd--- - sage: print(escaper(env, {}, 'my-invalid/identifier')) - my-invalid-identifier - sage: print(escaper(env, {}, r'quotes"mustbe!escaped')) - quotes-mustbe-escaped - - The following doctests originally accompanied #7269's support for - Jinja2. - - sage: from sagenb.notebook.template import css_escape # not tested - sage: css_escape('abcd') # not tested + sage: from sagenb.notebook.template import css_escape + sage: css_escape('abcd') 'abcd' - sage: css_escape('12abcd') # not tested + sage: css_escape('12abcd') '12abcd' - sage: css_escape(r'\'"abcd\'"') # not tested + sage: css_escape(r'\'"abcd\'"') '---abcd---' - sage: css_escape('my-invalid/identifier') # not tested + sage: css_escape('my-invalid/identifier') 'my-invalid-identifier' - sage: css_escape(r'quotes"mustbe!escaped') # not tested + sage: css_escape(r'quotes"mustbe!escaped') 'quotes-mustbe-escaped' """ return css_illegal_re.sub('-', string) @@ -119,11 +100,11 @@ def clean_name(name): return ''.join([x if x.isalnum() else '_' for x in name]) env.filters['css_escape'] = css_escape -env.filters['number_of_rows'] = simplefilter(number_of_rows) -env.filters['clean_name'] = stringfilter(clean_name) -env.filters['prettify_time_ago'] = simplefilter(prettify_time_ago) -env.filters['math_parse'] = stringfilter(math_parse) -env.filters['max'] = simplefilter(max) +env.filters['number_of_rows'] = number_of_rows +env.filters['clean_name'] = clean_name +env.filters['prettify_time_ago'] = prettify_time_ago +env.filters['math_parse'] = math_parse +env.filters['max'] = max def template(filename, **user_context): """ @@ -164,9 +145,10 @@ def template(filename, **user_context): 'conf': notebook.conf() if notebook else None} try: tmpl = env.get_template(filename) - except jinja.exceptions.TemplateNotFound: + except jinja2.exceptions.TemplateNotFound: return "Notebook Bug -- missing template %s"%filename context = dict(default_context) context.update(user_context) r = tmpl.render(**context) return r + diff --git a/sagenb/notebook/twist.py b/sagenb/notebook/twist.py --- a/sagenb/notebook/twist.py +++ b/sagenb/notebook/twist.py @@ -82,7 +82,14 @@ def word_wrap_cols(): SEP = '___S_A_G_E___' def encode_list(v): - return SEP.join([str(x) for x in v]) + seq = [] + for x in v: + if isinstance(x, unicode): + x = x.encode('utf-8', 'ignore') + else: + x = str(x) + seq.append(x) + return SEP.join(seq) @@ -1090,9 +1097,11 @@ class Worksheet_new_cell_before(Workshee def render(self, ctx): id = self.id(ctx) if not ctx.args.has_key('input'): - input = '' + input = u'' else: input = ctx.args['input'][0] + if isinstance(input, str): + input = input.decode('utf-8') cell = self.worksheet.new_cell_before(id, input=input) self.worksheet.increase_state_number() @@ -1109,6 +1118,8 @@ class Worksheet_new_text_cell_before(Wor input = '' else: input = ctx.args['input'][0] + if isinstance(input, str): + input = input.decode('utf-8') cell = self.worksheet.new_text_cell_before(id, input=input) s = encode_list([cell.id(), cell.html(editing=True), id]) @@ -1125,6 +1136,8 @@ class Worksheet_new_cell_after(Worksheet input = '' else: input = ctx.args['input'][0] + if isinstance(input, str): + input = input.decode('utf-8') cell = self.worksheet.new_cell_after(id, input=input) s = encode_list([cell.id(), cell.html(div_wrap=False), id]) return HTMLResponse(stream = s) @@ -1139,6 +1152,8 @@ class Worksheet_new_text_cell_after(Work input = '' else: input = ctx.args['input'][0] + if isinstance(input, str): + input = input.decode('utf-8') cell = self.worksheet.new_text_cell_after(id, input=input) s = encode_list([cell.id(), cell.html(editing=True), id]) @@ -1249,10 +1264,13 @@ class Worksheet_eval(WorksheetResource, def render(self, ctx): id = self.id(ctx) if not ctx.args.has_key('input'): - input_text = '' + input_text = u'' else: input_text = ctx.args['input'][0] input_text = input_text.replace('\r\n', '\n') # DOS + if isinstance(input_text, str): + input_text = input_text.decode('utf-8') + W = self.worksheet W.increase_state_number() diff --git a/sagenb/notebook/worksheet.py b/sagenb/notebook/worksheet.py --- a/sagenb/notebook/worksheet.py +++ b/sagenb/notebook/worksheet.py @@ -271,19 +271,7 @@ class Worksheet(object): sage: import sagenb.notebook.worksheet sage: W = sagenb.notebook.worksheet.Worksheet('test', 0, tmp_dir(), owner='sage') sage: sorted((W.basic().items())) - [('auto_publish', False), - ('collaborators', []), - ('id_number', 0), - ('last_change', ('sage', ...)), - ('name', 'test'), - ('owner', 'sage'), - ('pretty_print', False), - ('published_id_number', None), - ('ratings', []), - ('system', None), - ('tags', {'sage': [1]}), - ('viewers', []), - ('worksheet_that_was_published', ('sage', 0))] + [('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))] """ try: published_id_number = int(os.path.split(self.__published_version)[1]) @@ -690,7 +678,7 @@ class Worksheet(object): sage: nb = sagenb.notebook.notebook.Notebook(tmp_dir()+'.sagenb') sage: W = nb.create_new_worksheet('A Test Worksheet', 'admin') sage: W.name() - 'A Test Worksheet' + u'A Test Worksheet' """ try: return self.__name @@ -712,10 +700,12 @@ class Worksheet(object): sage: W = nb.create_new_worksheet('A Test Worksheet', 'admin') sage: W.set_name('A renamed worksheet') sage: W.name() - 'A renamed worksheet' + u'A renamed worksheet' """ if len(name.strip()) == 0: - name = 'Untitled' + name = u'Untitled' + if isinstance(name, str): + name = name.decode('utf-8', 'ignore') self.__name = name def set_filename_without_owner(self, nm): @@ -1913,8 +1903,8 @@ class Worksheet(object): if os.path.exists(worksheet_html) and open(worksheet_html).read() == E: # we already wrote it out... return - open(filename, 'w').write(bz2.compress(E)) - open(worksheet_html, 'w').write(self.body()) + open(filename, 'w').write(bz2.compress(E.encode('utf-8', 'ignore'))) + open(worksheet_html, 'w').write(self.body().encode('utf-8', 'ignore')) self.limit_snapshots() try: X = self.__saved_by_info @@ -2141,7 +2131,7 @@ class Worksheet(object): 5, Cell 1; in=2+8, out= 10] sage: W.name() - 'Test Edit Save' + u'Test Edit Save' """ # Clear any caching. try: @@ -3439,7 +3429,7 @@ from sagenb.notebook.all import * """ # The extra newline below is necessary, since otherwise source # code introspection doesn't include the last line. - 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) + 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) ########################################################## # Loading and attaching files @@ -3596,12 +3586,12 @@ from sagenb.notebook.all import * sage: W.get_cell_system(c0) 'sage' sage: W.get_cell_system(c1) - 'gap' + u'gap' sage: W.edit_save('{{{\n%sage\n2+3\n}}}\n\n{{{\nSymmetricGroup(5)\n}}}') sage: W.set_system('gap') sage: c0, c1 = W.cell_list() sage: W.get_cell_system(c0) - 'sage' + u'sage' sage: W.get_cell_system(c1) 'gap' """ @@ -3626,7 +3616,7 @@ from sagenb.notebook.all import * os.makedirs(code) spyx = os.path.abspath(os.path.join(code, 'sage%s.spyx'%id)) if not (os.path.exists(spyx) and open(spyx).read() == cmd): - open(spyx,'w').write(cmd) + open(spyx,'w').write(cmd.encode('utf-8', 'ignore')) return '_support_.cython_import_all("%s", globals())'%spyx def check_for_system_switching(self, input, cell): @@ -3653,9 +3643,9 @@ from sagenb.notebook.all import * sage: W.edit_save('{{{\n2+3\n}}}\n\n{{{\n%gap\nSymmetricGroup(5)\n}}}') sage: c0, c1 = W.cell_list() sage: W.check_for_system_switching(c0.cleaned_input_text(), c0) - (False, '2+3') + (False, u'2+3') sage: W.check_for_system_switching(c1.cleaned_input_text(), c1) - (True, "print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')") + (True, u"print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')") :: @@ -3677,10 +3667,9 @@ from sagenb.notebook.all import * sage: W.set_system('gap') sage: c0, c1 = W.cell_list() sage: W.check_for_system_switching(c0.cleaned_input_text(), c0) - (False, '2+3') + (False, u'2+3') sage: W.check_for_system_switching(c1.cleaned_input_text(), c1) - (True, - "print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')") + (True, u"print _support_.syseval(gap, ur'''SymmetricGroup(5)''', '...')") sage: c0.evaluate() sage: W.check_comp() #random output -- depends on the computer's speed ('d', Cell 0; in=%sage diff --git a/sagenb/storage/filesystem_storage.py b/sagenb/storage/filesystem_storage.py --- a/sagenb/storage/filesystem_storage.py +++ b/sagenb/storage/filesystem_storage.py @@ -291,7 +291,7 @@ class FilesystemDatastore(Datastore): # only save if loaded # todo -- add check if changed filename = self._worksheet_html_filename(username, id_number) - open(self._abspath(filename),'w').write(worksheet.body()) + open(self._abspath(filename),'w').write(worksheet.body().encode('utf-8', 'ignore')) def load_worksheet(self, username, id_number): """ @@ -339,7 +339,8 @@ class FilesystemDatastore(Datastore): if title: # change the title basic['name'] = title - + if isinstance(basic['name'], unicode): + basic['name'] = basic['name'].encode('utf-8', 'ignore') # Remove metainformation that perhaps shouldn't be distributed for k in ['owner', 'ratings', 'worksheet_that_was_published', 'viewers', 'tags', 'published_id_number', 'collaborators', 'auto_publish']: @@ -397,7 +398,7 @@ class FilesystemDatastore(Datastore): worksheet_txt = members[0].name W = self.load_worksheet(username, id_number) - W.edit_save_old_format(T.extractfile(worksheet_txt).read()) + W.edit_save_old_format(T.extractfile(worksheet_txt).read().decode('utf-8', 'ignore')) # '/' is right, since old worksheets always unix dir = worksheet_txt.split('/')[0]