Show More
@@ -1,150 +1,161 b'' | |||||
1 | """The IPython notebook format |
|
1 | """The IPython notebook format | |
2 |
|
2 | |||
3 | Use this module to read or write notebook files as particular nbformat versions. |
|
3 | Use this module to read or write notebook files as particular nbformat versions. | |
4 | """ |
|
4 | """ | |
5 |
|
5 | |||
6 | # Copyright (c) IPython Development Team. |
|
6 | # Copyright (c) IPython Development Team. | |
7 | # Distributed under the terms of the Modified BSD License. |
|
7 | # Distributed under the terms of the Modified BSD License. | |
|
8 | import io | |||
|
9 | from IPython.utils import py3compat | |||
8 |
|
10 | |||
9 | from IPython.utils.log import get_logger |
|
11 | from IPython.utils.log import get_logger | |
10 |
|
12 | |||
11 | from . import v1 |
|
13 | from . import v1 | |
12 | from . import v2 |
|
14 | from . import v2 | |
13 | from . import v3 |
|
15 | from . import v3 | |
14 | from . import v4 |
|
16 | from . import v4 | |
15 |
|
17 | |||
16 | __all__ = ['versions', 'validate', 'ValidationError', 'convert', 'from_dict', |
|
18 | __all__ = ['versions', 'validate', 'ValidationError', 'convert', 'from_dict', | |
17 | 'NotebookNode', 'current_nbformat', 'current_nbformat_minor', |
|
19 | 'NotebookNode', 'current_nbformat', 'current_nbformat_minor', | |
18 | 'NBFormatError', 'NO_CONVERT', 'reads', 'read', 'writes', 'write'] |
|
20 | 'NBFormatError', 'NO_CONVERT', 'reads', 'read', 'writes', 'write'] | |
19 |
|
21 | |||
20 | versions = { |
|
22 | versions = { | |
21 | 1: v1, |
|
23 | 1: v1, | |
22 | 2: v2, |
|
24 | 2: v2, | |
23 | 3: v3, |
|
25 | 3: v3, | |
24 | 4: v4, |
|
26 | 4: v4, | |
25 | } |
|
27 | } | |
26 |
|
28 | |||
27 | from .validator import validate, ValidationError |
|
29 | from .validator import validate, ValidationError | |
28 | from .converter import convert |
|
30 | from .converter import convert | |
29 | from . import reader |
|
31 | from . import reader | |
30 | from .notebooknode import from_dict, NotebookNode |
|
32 | from .notebooknode import from_dict, NotebookNode | |
31 |
|
33 | |||
32 | from .v4 import ( |
|
34 | from .v4 import ( | |
33 | nbformat as current_nbformat, |
|
35 | nbformat as current_nbformat, | |
34 | nbformat_minor as current_nbformat_minor, |
|
36 | nbformat_minor as current_nbformat_minor, | |
35 | ) |
|
37 | ) | |
36 |
|
38 | |||
37 | class NBFormatError(ValueError): |
|
39 | class NBFormatError(ValueError): | |
38 | pass |
|
40 | pass | |
39 |
|
41 | |||
40 | # no-conversion singleton |
|
42 | # no-conversion singleton | |
41 | NO_CONVERT = object() |
|
43 | NO_CONVERT = object() | |
42 |
|
44 | |||
43 | def reads(s, as_version, **kwargs): |
|
45 | def reads(s, as_version, **kwargs): | |
44 | """Read a notebook from a string and return the NotebookNode object as the given version. |
|
46 | """Read a notebook from a string and return the NotebookNode object as the given version. | |
45 |
|
47 | |||
46 | The string can contain a notebook of any version. |
|
48 | The string can contain a notebook of any version. | |
47 | The notebook will be returned `as_version`, converting, if necessary. |
|
49 | The notebook will be returned `as_version`, converting, if necessary. | |
48 |
|
50 | |||
49 | Notebook format errors will be logged. |
|
51 | Notebook format errors will be logged. | |
50 |
|
52 | |||
51 | Parameters |
|
53 | Parameters | |
52 | ---------- |
|
54 | ---------- | |
53 | s : unicode |
|
55 | s : unicode | |
54 | The raw unicode string to read the notebook from. |
|
56 | The raw unicode string to read the notebook from. | |
55 | as_version : int |
|
57 | as_version : int | |
56 | The version of the notebook format to return. |
|
58 | The version of the notebook format to return. | |
57 | The notebook will be converted, if necessary. |
|
59 | The notebook will be converted, if necessary. | |
58 | Pass nbformat.NO_CONVERT to prevent conversion. |
|
60 | Pass nbformat.NO_CONVERT to prevent conversion. | |
59 |
|
61 | |||
60 | Returns |
|
62 | Returns | |
61 | ------- |
|
63 | ------- | |
62 | nb : NotebookNode |
|
64 | nb : NotebookNode | |
63 | The notebook that was read. |
|
65 | The notebook that was read. | |
64 | """ |
|
66 | """ | |
65 | nb = reader.reads(s, **kwargs) |
|
67 | nb = reader.reads(s, **kwargs) | |
66 | if as_version is not NO_CONVERT: |
|
68 | if as_version is not NO_CONVERT: | |
67 | nb = convert(nb, as_version) |
|
69 | nb = convert(nb, as_version) | |
68 | try: |
|
70 | try: | |
69 | validate(nb) |
|
71 | validate(nb) | |
70 | except ValidationError as e: |
|
72 | except ValidationError as e: | |
71 | get_logger().error("Notebook JSON is invalid: %s", e) |
|
73 | get_logger().error("Notebook JSON is invalid: %s", e) | |
72 | return nb |
|
74 | return nb | |
73 |
|
75 | |||
74 |
|
76 | |||
75 | def writes(nb, version=NO_CONVERT, **kwargs): |
|
77 | def writes(nb, version=NO_CONVERT, **kwargs): | |
76 | """Write a notebook to a string in a given format in the given nbformat version. |
|
78 | """Write a notebook to a string in a given format in the given nbformat version. | |
77 |
|
79 | |||
78 | Any notebook format errors will be logged. |
|
80 | Any notebook format errors will be logged. | |
79 |
|
81 | |||
80 | Parameters |
|
82 | Parameters | |
81 | ---------- |
|
83 | ---------- | |
82 | nb : NotebookNode |
|
84 | nb : NotebookNode | |
83 | The notebook to write. |
|
85 | The notebook to write. | |
84 | version : int, optional |
|
86 | version : int, optional | |
85 | The nbformat version to write. |
|
87 | The nbformat version to write. | |
86 | If unspecified, or specified as nbformat.NO_CONVERT, |
|
88 | If unspecified, or specified as nbformat.NO_CONVERT, | |
87 | the notebook's own version will be used and no conversion performed. |
|
89 | the notebook's own version will be used and no conversion performed. | |
88 |
|
90 | |||
89 | Returns |
|
91 | Returns | |
90 | ------- |
|
92 | ------- | |
91 | s : unicode |
|
93 | s : unicode | |
92 | The notebook as a JSON string. |
|
94 | The notebook as a JSON string. | |
93 | """ |
|
95 | """ | |
94 | if version is not NO_CONVERT: |
|
96 | if version is not NO_CONVERT: | |
95 | nb = convert(nb, version) |
|
97 | nb = convert(nb, version) | |
96 | else: |
|
98 | else: | |
97 | version, _ = reader.get_version(nb) |
|
99 | version, _ = reader.get_version(nb) | |
98 | try: |
|
100 | try: | |
99 | validate(nb) |
|
101 | validate(nb) | |
100 | except ValidationError as e: |
|
102 | except ValidationError as e: | |
101 | get_logger().error("Notebook JSON is invalid: %s", e) |
|
103 | get_logger().error("Notebook JSON is invalid: %s", e) | |
102 | return versions[version].writes_json(nb, **kwargs) |
|
104 | return versions[version].writes_json(nb, **kwargs) | |
103 |
|
105 | |||
104 |
|
106 | |||
105 | def read(fp, as_version, **kwargs): |
|
107 | def read(fp, as_version, **kwargs): | |
106 | """Read a notebook from a file as a NotebookNode of the given version. |
|
108 | """Read a notebook from a file as a NotebookNode of the given version. | |
107 |
|
109 | |||
108 | The string can contain a notebook of any version. |
|
110 | The string can contain a notebook of any version. | |
109 | The notebook will be returned `as_version`, converting, if necessary. |
|
111 | The notebook will be returned `as_version`, converting, if necessary. | |
110 |
|
112 | |||
111 | Notebook format errors will be logged. |
|
113 | Notebook format errors will be logged. | |
112 |
|
114 | |||
113 | Parameters |
|
115 | Parameters | |
114 | ---------- |
|
116 | ---------- | |
115 | fp : file |
|
117 | fp : file or str | |
116 | Any file-like object with a read method. |
|
118 | Any file-like object with a read method, or a path to a file. | |
117 | as_version: int |
|
119 | as_version: int | |
118 | The version of the notebook format to return. |
|
120 | The version of the notebook format to return. | |
119 | The notebook will be converted, if necessary. |
|
121 | The notebook will be converted, if necessary. | |
120 | Pass nbformat.NO_CONVERT to prevent conversion. |
|
122 | Pass nbformat.NO_CONVERT to prevent conversion. | |
121 |
|
123 | |||
122 | Returns |
|
124 | Returns | |
123 | ------- |
|
125 | ------- | |
124 | nb : NotebookNode |
|
126 | nb : NotebookNode | |
125 | The notebook that was read. |
|
127 | The notebook that was read. | |
126 | """ |
|
128 | """ | |
|
129 | if isinstance(fp, py3compat.string_types): | |||
|
130 | with io.open(fp, encoding='utf-8') as f: | |||
|
131 | return read(f, as_version, **kwargs) | |||
|
132 | ||||
127 | return reads(fp.read(), as_version, **kwargs) |
|
133 | return reads(fp.read(), as_version, **kwargs) | |
128 |
|
134 | |||
129 |
|
135 | |||
130 | def write(nb, fp, version=NO_CONVERT, **kwargs): |
|
136 | def write(nb, fp, version=NO_CONVERT, **kwargs): | |
131 | """Write a notebook to a file in a given nbformat version. |
|
137 | """Write a notebook to a file in a given nbformat version. | |
132 |
|
138 | |||
133 | The file-like object must accept unicode input. |
|
139 | The file-like object must accept unicode input. | |
134 |
|
140 | |||
135 | Parameters |
|
141 | Parameters | |
136 | ---------- |
|
142 | ---------- | |
137 | nb : NotebookNode |
|
143 | nb : NotebookNode | |
138 | The notebook to write. |
|
144 | The notebook to write. | |
139 | fp : file |
|
145 | fp : file or str | |
140 |
Any file-like object with a write method that accepts unicode |
|
146 | Any file-like object with a write method that accepts unicode, or | |
|
147 | a path to write a file. | |||
141 | version : int, optional |
|
148 | version : int, optional | |
142 | The nbformat version to write. |
|
149 | The nbformat version to write. | |
143 | If nb is not this version, it will be converted. |
|
150 | If nb is not this version, it will be converted. | |
144 | If unspecified, or specified as nbformat.NO_CONVERT, |
|
151 | If unspecified, or specified as nbformat.NO_CONVERT, | |
145 | the notebook's own version will be used and no conversion performed. |
|
152 | the notebook's own version will be used and no conversion performed. | |
146 | """ |
|
153 | """ | |
|
154 | if isinstance(fp, py3compat.string_types): | |||
|
155 | with open(fp, 'w', encoding='utf-8') as f: | |||
|
156 | return write(nb, f, version=version, **kwargs) | |||
|
157 | ||||
147 | s = writes(nb, version, **kwargs) |
|
158 | s = writes(nb, version, **kwargs) | |
148 | if isinstance(s, bytes): |
|
159 | if isinstance(s, bytes): | |
149 | s = s.decode('utf8') |
|
160 | s = s.decode('utf8') | |
150 | return fp.write(s) |
|
161 | return fp.write(s) |
@@ -1,37 +1,49 b'' | |||||
1 | """Test the APIs at the top-level of nbformat""" |
|
1 | """Test the APIs at the top-level of nbformat""" | |
2 |
|
2 | |||
3 | # Copyright (c) IPython Development Team. |
|
3 | # Copyright (c) IPython Development Team. | |
4 | # Distributed under the terms of the Modified BSD License. |
|
4 | # Distributed under the terms of the Modified BSD License. | |
5 |
|
5 | |||
6 | import json |
|
6 | import json | |
|
7 | import os | |||
7 |
|
8 | |||
8 | from .base import TestsBase |
|
9 | from .base import TestsBase | |
9 |
|
10 | |||
|
11 | from IPython.utils.tempdir import TemporaryDirectory | |||
10 | from ..reader import get_version |
|
12 | from ..reader import get_version | |
11 | from IPython.nbformat import read, current_nbformat, writes |
|
13 | from IPython.nbformat import read, current_nbformat, writes, write | |
12 |
|
14 | |||
13 |
|
15 | |||
14 | class TestAPI(TestsBase): |
|
16 | class TestAPI(TestsBase): | |
15 |
|
17 | |||
16 | def test_read(self): |
|
18 | def test_read(self): | |
17 | """Can older notebooks be opened and automatically converted to the current |
|
19 | """Can older notebooks be opened and automatically converted to the current | |
18 | nbformat?""" |
|
20 | nbformat?""" | |
19 |
|
21 | |||
20 | # Open a version 2 notebook. |
|
22 | # Open a version 2 notebook. | |
21 | with self.fopen(u'test2.ipynb', 'r') as f: |
|
23 | with self.fopen(u'test2.ipynb', 'r') as f: | |
22 | nb = read(f, as_version=current_nbformat) |
|
24 | nb = read(f, as_version=current_nbformat) | |
23 |
|
25 | |||
24 | # Check that the notebook was upgraded to the latest version automatically. |
|
26 | # Check that the notebook was upgraded to the latest version automatically. | |
25 | (major, minor) = get_version(nb) |
|
27 | (major, minor) = get_version(nb) | |
26 | self.assertEqual(major, current_nbformat) |
|
28 | self.assertEqual(major, current_nbformat) | |
27 |
|
29 | |||
28 | def test_write_downgrade_2(self): |
|
30 | def test_write_downgrade_2(self): | |
29 | """dowgrade a v3 notebook to v2""" |
|
31 | """dowgrade a v3 notebook to v2""" | |
30 | # Open a version 3 notebook. |
|
32 | # Open a version 3 notebook. | |
31 | with self.fopen(u'test3.ipynb', 'r') as f: |
|
33 | with self.fopen(u'test3.ipynb', 'r') as f: | |
32 | nb = read(f, as_version=3) |
|
34 | nb = read(f, as_version=3) | |
33 |
|
35 | |||
34 | jsons = writes(nb, version=2) |
|
36 | jsons = writes(nb, version=2) | |
35 | nb2 = json.loads(jsons) |
|
37 | nb2 = json.loads(jsons) | |
36 | (major, minor) = get_version(nb2) |
|
38 | (major, minor) = get_version(nb2) | |
37 | self.assertEqual(major, 2) |
|
39 | self.assertEqual(major, 2) | |
|
40 | ||||
|
41 | def test_read_write_path(self): | |||
|
42 | """read() and write() take filesystem paths""" | |||
|
43 | path = os.path.join(self._get_files_path(), u'test4.ipynb') | |||
|
44 | nb = read(path, as_version=4) | |||
|
45 | ||||
|
46 | with TemporaryDirectory() as td: | |||
|
47 | dest = os.path.join(td, 'echidna.ipynb') | |||
|
48 | write(nb, dest) | |||
|
49 | assert os.path.isfile(dest) |
General Comments 0
You need to be logged in to leave comments.
Login now