Show More
@@ -0,0 +1,63 b'' | |||||
|
1 | # -*- coding: utf8 -*- | |||
|
2 | import io | |||
|
3 | import os | |||
|
4 | import shutil | |||
|
5 | import tempfile | |||
|
6 | ||||
|
7 | pjoin = os.path.join | |||
|
8 | ||||
|
9 | from ..nbbase import ( | |||
|
10 | NotebookNode, | |||
|
11 | new_code_cell, new_text_cell, new_worksheet, new_notebook | |||
|
12 | ) | |||
|
13 | ||||
|
14 | from ..nbpy import reads, writes, read, write | |||
|
15 | from .nbexamples import nb0, nb0_py | |||
|
16 | ||||
|
17 | ||||
|
18 | def open_utf8(fname, mode): | |||
|
19 | return io.open(fname, mode=mode, encoding='utf-8') | |||
|
20 | ||||
|
21 | class NBFormatTest: | |||
|
22 | """Mixin for writing notebook format tests""" | |||
|
23 | ||||
|
24 | # override with appropriate values in subclasses | |||
|
25 | nb0_ref = None | |||
|
26 | ext = None | |||
|
27 | mod = None | |||
|
28 | ||||
|
29 | def setUp(self): | |||
|
30 | self.wd = tempfile.mkdtemp() | |||
|
31 | ||||
|
32 | def tearDown(self): | |||
|
33 | shutil.rmtree(self.wd) | |||
|
34 | ||||
|
35 | def assertNBEquals(self, nba, nbb): | |||
|
36 | self.assertEquals(nba, nbb) | |||
|
37 | ||||
|
38 | def test_writes(self): | |||
|
39 | s = self.mod.writes(nb0) | |||
|
40 | if self.nb0_ref: | |||
|
41 | self.assertEquals(s, self.nb0_ref) | |||
|
42 | ||||
|
43 | def test_reads(self): | |||
|
44 | s = self.mod.writes(nb0) | |||
|
45 | nb = self.mod.reads(s) | |||
|
46 | ||||
|
47 | def test_roundtrip(self): | |||
|
48 | s = self.mod.writes(nb0) | |||
|
49 | self.assertNBEquals(self.mod.reads(s),nb0) | |||
|
50 | ||||
|
51 | def test_write_file(self): | |||
|
52 | with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), 'w') as f: | |||
|
53 | self.mod.write(nb0, f) | |||
|
54 | ||||
|
55 | def test_read_file(self): | |||
|
56 | with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), 'w') as f: | |||
|
57 | self.mod.write(nb0, f) | |||
|
58 | ||||
|
59 | with open_utf8(pjoin(self.wd, "nb0.%s" % self.ext), 'r') as f: | |||
|
60 | nb = self.mod.read(f) | |||
|
61 | ||||
|
62 | ||||
|
63 |
@@ -20,6 +20,7 b' import __future__' | |||||
20 | import bdb |
|
20 | import bdb | |
21 | import inspect |
|
21 | import inspect | |
22 | import imp |
|
22 | import imp | |
|
23 | import io | |||
23 | import os |
|
24 | import os | |
24 | import sys |
|
25 | import sys | |
25 | import shutil |
|
26 | import shutil | |
@@ -2222,7 +2223,7 b' Currently the magic system has the following functions:\\n"""' | |||||
2222 | except (TypeError, ValueError) as e: |
|
2223 | except (TypeError, ValueError) as e: | |
2223 | print e.args[0] |
|
2224 | print e.args[0] | |
2224 | return |
|
2225 | return | |
2225 |
with |
|
2226 | with io.open(fname,'w', encoding="utf-8") as f: | |
2226 | f.write(u"# coding: utf-8\n") |
|
2227 | f.write(u"# coding: utf-8\n") | |
2227 | f.write(py3compat.cast_unicode(cmds)) |
|
2228 | f.write(py3compat.cast_unicode(cmds)) | |
2228 | print 'The following commands were written to file `%s`:' % fname |
|
2229 | print 'The following commands were written to file `%s`:' % fname | |
@@ -3663,7 +3664,7 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3663 | cells.append(current.new_code_cell(prompt_number=prompt_number, input=input)) |
|
3664 | cells.append(current.new_code_cell(prompt_number=prompt_number, input=input)) | |
3664 | worksheet = current.new_worksheet(cells=cells) |
|
3665 | worksheet = current.new_worksheet(cells=cells) | |
3665 | nb = current.new_notebook(name=name,worksheets=[worksheet]) |
|
3666 | nb = current.new_notebook(name=name,worksheets=[worksheet]) | |
3666 | with open(fname, 'w') as f: |
|
3667 | with io.open(fname, 'w', encoding='utf-8') as f: | |
3667 | current.write(nb, f, format); |
|
3668 | current.write(nb, f, format); | |
3668 | elif args.format is not None: |
|
3669 | elif args.format is not None: | |
3669 | old_fname, old_name, old_format = current.parse_filename(args.filename) |
|
3670 | old_fname, old_name, old_format = current.parse_filename(args.filename) | |
@@ -3677,13 +3678,9 b' Defaulting color scheme to \'NoColor\'"""' | |||||
3677 | new_fname = old_name + u'.py' |
|
3678 | new_fname = old_name + u'.py' | |
3678 | else: |
|
3679 | else: | |
3679 | raise ValueError('Invalid notebook format: %s' % new_format) |
|
3680 | raise ValueError('Invalid notebook format: %s' % new_format) | |
3680 | with open(old_fname, 'r') as f: |
|
3681 | with io.open(old_fname, 'r', encoding='utf-8') as f: | |
3681 |
|
|
3682 | nb = current.read(f, old_format) | |
3682 | try: |
|
3683 | with io.open(new_fname, 'w', encoding='utf-8') as f: | |
3683 | nb = current.reads(s, old_format) |
|
|||
3684 | except: |
|
|||
3685 | nb = current.reads(s, u'xml') |
|
|||
3686 | with open(new_fname, 'w') as f: |
|
|||
3687 | current.write(nb, f, new_format) |
|
3684 | current.write(nb, f, new_format) | |
3688 |
|
3685 | |||
3689 | def magic_config(self, s): |
|
3686 | def magic_config(self, s): |
@@ -1,3 +1,4 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
1 | """Tests for various magic functions. |
|
2 | """Tests for various magic functions. | |
2 |
|
3 | |||
3 | Needs to be run by nose (to make ipython session available). |
|
4 | Needs to be run by nose (to make ipython session available). | |
@@ -8,12 +9,15 b' from __future__ import absolute_import' | |||||
8 | # Imports |
|
9 | # Imports | |
9 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
10 |
|
11 | |||
|
12 | import io | |||
11 | import os |
|
13 | import os | |
12 | import sys |
|
14 | import sys | |
13 | from StringIO import StringIO |
|
15 | from StringIO import StringIO | |
14 |
|
16 | |||
15 | import nose.tools as nt |
|
17 | import nose.tools as nt | |
16 |
|
18 | |||
|
19 | from IPython.nbformat.v3.tests.nbexamples import nb0 | |||
|
20 | from IPython.nbformat import current | |||
17 | from IPython.testing import decorators as dec |
|
21 | from IPython.testing import decorators as dec | |
18 | from IPython.testing import tools as tt |
|
22 | from IPython.testing import tools as tt | |
19 | from IPython.utils import py3compat |
|
23 | from IPython.utils import py3compat | |
@@ -23,6 +27,7 b' from IPython.utils.tempdir import TemporaryDirectory' | |||||
23 | # Test functions begin |
|
27 | # Test functions begin | |
24 | #----------------------------------------------------------------------------- |
|
28 | #----------------------------------------------------------------------------- | |
25 |
|
29 | |||
|
30 | ||||
26 | def test_rehashx(): |
|
31 | def test_rehashx(): | |
27 | # clear up everything |
|
32 | # clear up everything | |
28 | _ip = get_ipython() |
|
33 | _ip = get_ipython() | |
@@ -431,3 +436,34 b' def test_extension():' | |||||
431 | finally: |
|
436 | finally: | |
432 | _ip.ipython_dir = orig_ipython_dir |
|
437 | _ip.ipython_dir = orig_ipython_dir | |
433 |
|
438 | |||
|
439 | def test_notebook_export_json(): | |||
|
440 | with TemporaryDirectory() as td: | |||
|
441 | outfile = os.path.join(td, "nb.ipynb") | |||
|
442 | _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) | |||
|
443 | _ip.magic("notebook -e %s" % outfile) | |||
|
444 | ||||
|
445 | def test_notebook_export_py(): | |||
|
446 | with TemporaryDirectory() as td: | |||
|
447 | outfile = os.path.join(td, "nb.py") | |||
|
448 | _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) | |||
|
449 | _ip.magic("notebook -e %s" % outfile) | |||
|
450 | ||||
|
451 | def test_notebook_reformat_py(): | |||
|
452 | with TemporaryDirectory() as td: | |||
|
453 | infile = os.path.join(td, "nb.ipynb") | |||
|
454 | with io.open(infile, 'w') as f: | |||
|
455 | current.write(nb0, f, 'json') | |||
|
456 | ||||
|
457 | _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) | |||
|
458 | _ip.magic("notebook -f py %s" % infile) | |||
|
459 | ||||
|
460 | def test_notebook_reformat_json(): | |||
|
461 | with TemporaryDirectory() as td: | |||
|
462 | infile = os.path.join(td, "nb.py") | |||
|
463 | with io.open(infile, 'w') as f: | |||
|
464 | current.write(nb0, f, 'py') | |||
|
465 | ||||
|
466 | _ip.ex(py3compat.u_format(u"u = {u}'héllo'")) | |||
|
467 | _ip.magic("notebook -f ipynb %s" % infile) | |||
|
468 | _ip.magic("notebook -f json %s" % infile) | |||
|
469 |
@@ -146,7 +146,7 b' def new_worksheet(name=None, cells=None):' | |||||
146 | return ws |
|
146 | return ws | |
147 |
|
147 | |||
148 |
|
148 | |||
149 | def new_notebook(metadata=None, worksheets=None): |
|
149 | def new_notebook(name=None, metadata=None, worksheets=None): | |
150 | """Create a notebook by name, id and a list of worksheets.""" |
|
150 | """Create a notebook by name, id and a list of worksheets.""" | |
151 | nb = NotebookNode() |
|
151 | nb = NotebookNode() | |
152 | nb.nbformat = nbformat |
|
152 | nb.nbformat = nbformat | |
@@ -158,6 +158,8 b' def new_notebook(metadata=None, worksheets=None):' | |||||
158 | nb.metadata = new_metadata() |
|
158 | nb.metadata = new_metadata() | |
159 | else: |
|
159 | else: | |
160 | nb.metadata = NotebookNode(metadata) |
|
160 | nb.metadata = NotebookNode(metadata) | |
|
161 | if name is not None: | |||
|
162 | nb.metadata.name = unicode(name) | |||
161 | return nb |
|
163 | return nb | |
162 |
|
164 | |||
163 |
|
165 |
@@ -24,6 +24,8 b' from .rwbase import (' | |||||
24 | NotebookReader, NotebookWriter, restore_bytes, rejoin_lines, split_lines |
|
24 | NotebookReader, NotebookWriter, restore_bytes, rejoin_lines, split_lines | |
25 | ) |
|
25 | ) | |
26 |
|
26 | |||
|
27 | from IPython.utils import py3compat | |||
|
28 | ||||
27 | #----------------------------------------------------------------------------- |
|
29 | #----------------------------------------------------------------------------- | |
28 | # Code |
|
30 | # Code | |
29 | #----------------------------------------------------------------------------- |
|
31 | #----------------------------------------------------------------------------- | |
@@ -56,7 +58,7 b' class JSONWriter(NotebookWriter):' | |||||
56 | kwargs['separators'] = (',',': ') |
|
58 | kwargs['separators'] = (',',': ') | |
57 | if kwargs.pop('split_lines', True): |
|
59 | if kwargs.pop('split_lines', True): | |
58 | nb = split_lines(copy.deepcopy(nb)) |
|
60 | nb = split_lines(copy.deepcopy(nb)) | |
59 | return json.dumps(nb, **kwargs) |
|
61 | return py3compat.str_to_unicode(json.dumps(nb, **kwargs), 'utf-8') | |
60 |
|
62 | |||
61 |
|
63 | |||
62 | _reader = JSONReader() |
|
64 | _reader = JSONReader() |
@@ -19,7 +19,9 b' Authors:' | |||||
19 | from base64 import encodestring, decodestring |
|
19 | from base64 import encodestring, decodestring | |
20 | import pprint |
|
20 | import pprint | |
21 |
|
21 | |||
22 |
from IPython.utils |
|
22 | from IPython.utils import py3compat | |
|
23 | ||||
|
24 | str_to_bytes = py3compat.str_to_bytes | |||
23 |
|
25 | |||
24 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
25 | # Code |
|
27 | # Code | |
@@ -84,17 +86,17 b' def split_lines(nb):' | |||||
84 | for cell in ws.cells: |
|
86 | for cell in ws.cells: | |
85 | if cell.cell_type == 'code': |
|
87 | if cell.cell_type == 'code': | |
86 | if 'input' in cell and isinstance(cell.input, basestring): |
|
88 | if 'input' in cell and isinstance(cell.input, basestring): | |
87 | cell.input = cell.input.splitlines() |
|
89 | cell.input = (cell.input + '\n').splitlines() | |
88 | for output in cell.outputs: |
|
90 | for output in cell.outputs: | |
89 | for key in _multiline_outputs: |
|
91 | for key in _multiline_outputs: | |
90 | item = output.get(key, None) |
|
92 | item = output.get(key, None) | |
91 | if isinstance(item, basestring): |
|
93 | if isinstance(item, basestring): | |
92 | output[key] = item.splitlines() |
|
94 | output[key] = (item + '\n').splitlines() | |
93 | else: # text, heading cell |
|
95 | else: # text, heading cell | |
94 | for key in ['source', 'rendered']: |
|
96 | for key in ['source', 'rendered']: | |
95 | item = cell.get(key, None) |
|
97 | item = cell.get(key, None) | |
96 | if isinstance(item, basestring): |
|
98 | if isinstance(item, basestring): | |
97 | cell[key] = item.splitlines() |
|
99 | cell[key] = (item + '\n').splitlines() | |
98 | return nb |
|
100 | return nb | |
99 |
|
101 | |||
100 | # b64 encode/decode are never actually used, because all bytes objects in |
|
102 | # b64 encode/decode are never actually used, because all bytes objects in | |
@@ -147,7 +149,10 b' class NotebookReader(object):' | |||||
147 |
|
149 | |||
148 | def read(self, fp, **kwargs): |
|
150 | def read(self, fp, **kwargs): | |
149 | """Read a notebook from a file like object""" |
|
151 | """Read a notebook from a file like object""" | |
150 | return self.read(fp.read(), **kwargs) |
|
152 | nbs = fp.read() | |
|
153 | if not py3compat.PY3 and not isinstance(nbs, unicode): | |||
|
154 | nbs = py3compat.str_to_unicode(nbs) | |||
|
155 | return self.reads(nbs, **kwargs) | |||
151 |
|
156 | |||
152 |
|
157 | |||
153 | class NotebookWriter(object): |
|
158 | class NotebookWriter(object): | |
@@ -159,7 +164,11 b' class NotebookWriter(object):' | |||||
159 |
|
164 | |||
160 | def write(self, nb, fp, **kwargs): |
|
165 | def write(self, nb, fp, **kwargs): | |
161 | """Write a notebook to a file like object""" |
|
166 | """Write a notebook to a file like object""" | |
162 |
|
|
167 | nbs = self.writes(nb,**kwargs) | |
|
168 | if not py3compat.PY3 and not isinstance(nbs, unicode): | |||
|
169 | # this branch is likely only taken for JSON on Python 2 | |||
|
170 | nbs = py3compat.str_to_unicode(nbs) | |||
|
171 | return fp.write(nbs) | |||
163 |
|
172 | |||
164 |
|
173 | |||
165 |
|
174 |
@@ -1,3 +1,5 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
1 | import os |
|
3 | import os | |
2 | from base64 import encodestring |
|
4 | from base64 import encodestring | |
3 |
|
5 | |||
@@ -47,9 +49,17 b' ws.cells.append(new_code_cell(' | |||||
47 | prompt_number=2, |
|
49 | prompt_number=2, | |
48 | collapsed=True |
|
50 | collapsed=True | |
49 | )) |
|
51 | )) | |
|
52 | ws.cells.append(new_code_cell( | |||
|
53 | input='a = 10\nb = 5\n', | |||
|
54 | prompt_number=3, | |||
|
55 | )) | |||
|
56 | ws.cells.append(new_code_cell( | |||
|
57 | input='a = 10\nb = 5', | |||
|
58 | prompt_number=4, | |||
|
59 | )) | |||
50 |
|
60 | |||
51 | ws.cells.append(new_code_cell( |
|
61 | ws.cells.append(new_code_cell( | |
52 |
input='print |
|
62 | input=u'print "ünîcødé"', | |
53 | prompt_number=3, |
|
63 | prompt_number=3, | |
54 | collapsed=False, |
|
64 | collapsed=False, | |
55 | outputs=[new_output( |
|
65 | outputs=[new_output( | |
@@ -91,7 +101,7 b' nb0 = new_notebook(' | |||||
91 | metadata=md |
|
101 | metadata=md | |
92 | ) |
|
102 | ) | |
93 |
|
103 | |||
94 | nb0_py = """# -*- coding: utf-8 -*- |
|
104 | nb0_py = u"""# -*- coding: utf-8 -*- | |
95 | # <nbformat>%i</nbformat> |
|
105 | # <nbformat>%i</nbformat> | |
96 |
|
106 | |||
97 | # <htmlcell> |
|
107 | # <htmlcell> | |
@@ -120,7 +130,17 b' a = numpy.random.rand(100)' | |||||
120 |
|
130 | |||
121 | # <codecell> |
|
131 | # <codecell> | |
122 |
|
132 | |||
123 | print a |
|
133 | a = 10 | |
|
134 | b = 5 | |||
|
135 | ||||
|
136 | # <codecell> | |||
|
137 | ||||
|
138 | a = 10 | |||
|
139 | b = 5 | |||
|
140 | ||||
|
141 | # <codecell> | |||
|
142 | ||||
|
143 | print "ünîcødé" | |||
124 |
|
144 | |||
125 | """ % nbformat |
|
145 | """ % nbformat | |
126 |
|
146 |
@@ -2,33 +2,32 b' import pprint' | |||||
2 | from unittest import TestCase |
|
2 | from unittest import TestCase | |
3 |
|
3 | |||
4 | from ..nbjson import reads, writes |
|
4 | from ..nbjson import reads, writes | |
|
5 | from .. import nbjson | |||
5 | from .nbexamples import nb0 |
|
6 | from .nbexamples import nb0 | |
6 |
|
7 | |||
|
8 | from . import formattest | |||
7 |
|
9 | |||
8 | class TestJSON(TestCase): |
|
10 | from .nbexamples import nb0 | |
|
11 | ||||
|
12 | ||||
|
13 | class TestJSON(formattest.NBFormatTest, TestCase): | |||
|
14 | ||||
|
15 | nb0_ref = None | |||
|
16 | ext = 'ipynb' | |||
|
17 | mod = nbjson | |||
9 |
|
18 | |||
10 | def test_roundtrip(self): |
|
|||
11 | s = writes(nb0) |
|
|||
12 |
|
||||
13 | # print pprint.pformat(nb0,indent=2) |
|
|||
14 |
|
||||
15 | # print pprint.pformat(reads(s),indent=2) |
|
|||
16 |
|
||||
17 | # print s |
|
|||
18 | self.assertEquals(reads(s),nb0) |
|
|||
19 |
|
||||
20 | def test_roundtrip_nosplit(self): |
|
19 | def test_roundtrip_nosplit(self): | |
21 | """Ensure that multiline blobs are still readable""" |
|
20 | """Ensure that multiline blobs are still readable""" | |
22 | # ensures that notebooks written prior to splitlines change |
|
21 | # ensures that notebooks written prior to splitlines change | |
23 | # are still readable. |
|
22 | # are still readable. | |
24 | s = writes(nb0, split_lines=False) |
|
23 | s = writes(nb0, split_lines=False) | |
25 | self.assertEquals(reads(s),nb0) |
|
24 | self.assertEquals(nbjson.reads(s),nb0) | |
26 |
|
25 | |||
27 | def test_roundtrip_split(self): |
|
26 | def test_roundtrip_split(self): | |
28 | """Ensure that splitting multiline blocks is safe""" |
|
27 | """Ensure that splitting multiline blocks is safe""" | |
29 | # This won't differ from test_roundtrip unless the default changes |
|
28 | # This won't differ from test_roundtrip unless the default changes | |
30 | s = writes(nb0, split_lines=True) |
|
29 | s = writes(nb0, split_lines=True) | |
31 | self.assertEquals(reads(s),nb0) |
|
30 | self.assertEquals(nbjson.reads(s),nb0) | |
32 |
|
31 | |||
33 |
|
32 | |||
34 |
|
33 |
@@ -112,6 +112,13 b' class TestNotebook(TestCase):' | |||||
112 | self.assertEquals(nb.worksheets,worksheets) |
|
112 | self.assertEquals(nb.worksheets,worksheets) | |
113 | self.assertEquals(nb.nbformat,nbformat) |
|
113 | self.assertEquals(nb.nbformat,nbformat) | |
114 |
|
114 | |||
|
115 | def test_notebook_name(self): | |||
|
116 | worksheets = [new_worksheet(),new_worksheet()] | |||
|
117 | nb = new_notebook(name='foo',worksheets=worksheets) | |||
|
118 | self.assertEquals(nb.metadata.name,u'foo') | |||
|
119 | self.assertEquals(nb.worksheets,worksheets) | |||
|
120 | self.assertEquals(nb.nbformat,nbformat) | |||
|
121 | ||||
115 | class TestMetadata(TestCase): |
|
122 | class TestMetadata(TestCase): | |
116 |
|
123 | |||
117 | def test_empty_metadata(self): |
|
124 | def test_empty_metadata(self): |
@@ -1,17 +1,46 b'' | |||||
|
1 | # -*- coding: utf8 -*- | |||
|
2 | ||||
1 | from unittest import TestCase |
|
3 | from unittest import TestCase | |
2 |
|
4 | |||
3 |
from . |
|
5 | from . import formattest | |
4 | NotebookNode, |
|
|||
5 | new_code_cell, new_text_cell, new_worksheet, new_notebook |
|
|||
6 | ) |
|
|||
7 |
|
6 | |||
8 | from ..nbpy import reads, writes |
|
7 | from .. import nbpy | |
9 | from .nbexamples import nb0, nb0_py |
|
8 | from .nbexamples import nb0, nb0_py | |
10 |
|
9 | |||
11 |
|
10 | |||
12 | class TestPy(TestCase): |
|
11 | class TestPy(formattest.NBFormatTest, TestCase): | |
13 |
|
12 | |||
14 | def test_write(self): |
|
13 | nb0_ref = nb0_py | |
15 | s = writes(nb0) |
|
14 | ext = 'py' | |
16 | self.assertEquals(s,nb0_py) |
|
15 | mod = nbpy | |
|
16 | ignored_keys = ['collapsed', 'outputs', 'prompt_number', 'metadata'] | |||
17 |
|
17 | |||
|
18 | def assertSubset(self, da, db): | |||
|
19 | """assert that da is a subset of db, ignoring self.ignored_keys. | |||
|
20 | ||||
|
21 | Called recursively on containers, ultimately comparing individual | |||
|
22 | elements. | |||
|
23 | """ | |||
|
24 | if isinstance(da, dict): | |||
|
25 | for k,v in da.iteritems(): | |||
|
26 | if k in self.ignored_keys: | |||
|
27 | continue | |||
|
28 | self.assertTrue(k in db) | |||
|
29 | self.assertSubset(v, db[k]) | |||
|
30 | elif isinstance(da, list): | |||
|
31 | for a,b in zip(da, db): | |||
|
32 | self.assertSubset(a,b) | |||
|
33 | else: | |||
|
34 | if isinstance(da, basestring) and isinstance(db, basestring): | |||
|
35 | # pyfile is not sensitive to preserving leading/trailing | |||
|
36 | # newlines in blocks through roundtrip | |||
|
37 | da = da.strip('\n') | |||
|
38 | db = db.strip('\n') | |||
|
39 | self.assertEquals(da, db) | |||
|
40 | return True | |||
|
41 | ||||
|
42 | def assertNBEquals(self, nba, nbb): | |||
|
43 | # since roundtrip is lossy, only compare keys that are preserved | |||
|
44 | # assumes nba is read from my file format | |||
|
45 | return self.assertSubset(nba, nbb) | |||
|
46 |
@@ -32,7 +32,7 b' def cast_bytes(s, encoding=None):' | |||||
32 | def _modify_str_or_docstring(str_change_func): |
|
32 | def _modify_str_or_docstring(str_change_func): | |
33 | @functools.wraps(str_change_func) |
|
33 | @functools.wraps(str_change_func) | |
34 | def wrapper(func_or_str): |
|
34 | def wrapper(func_or_str): | |
35 | if isinstance(func_or_str, str): |
|
35 | if isinstance(func_or_str, basestring): | |
36 | func = None |
|
36 | func = None | |
37 | doc = func_or_str |
|
37 | doc = func_or_str | |
38 | else: |
|
38 | else: |
General Comments 0
You need to be logged in to leave comments.
Login now