Show More
@@ -0,0 +1,143 b'' | |||
|
1 | """The IPython notebook format | |
|
2 | ||
|
3 | Use this module to read or write notebook files as particular nbformat versions. | |
|
4 | """ | |
|
5 | ||
|
6 | # Copyright (c) IPython Development Team. | |
|
7 | # Distributed under the terms of the Modified BSD License. | |
|
8 | ||
|
9 | from IPython.utils.log import get_logger | |
|
10 | ||
|
11 | from . import v1 | |
|
12 | from . import v2 | |
|
13 | from . import v3 | |
|
14 | from . import v4 | |
|
15 | ||
|
16 | versions = { | |
|
17 | 1: v1, | |
|
18 | 2: v2, | |
|
19 | 3: v3, | |
|
20 | 4: v4, | |
|
21 | } | |
|
22 | ||
|
23 | from .validator import validate, ValidationError | |
|
24 | from .converter import convert | |
|
25 | from . import reader | |
|
26 | ||
|
27 | from .v4 import ( | |
|
28 | nbformat as current_nbformat, | |
|
29 | nbformat_minor as current_nbformat_minor, | |
|
30 | ) | |
|
31 | ||
|
32 | class NBFormatError(ValueError): | |
|
33 | pass | |
|
34 | ||
|
35 | # no-conversion singleton | |
|
36 | NO_CONVERT = object() | |
|
37 | ||
|
38 | def reads(s, as_version, **kwargs): | |
|
39 | """Read a notebook from a string and return the NotebookNode object as the given version. | |
|
40 | ||
|
41 | The string can contain a notebook of any version. | |
|
42 | The notebook will be returned `as_version`, converting, if necessary. | |
|
43 | ||
|
44 | Notebook format errors will be logged. | |
|
45 | ||
|
46 | Parameters | |
|
47 | ---------- | |
|
48 | s : unicode | |
|
49 | The raw unicode string to read the notebook from. | |
|
50 | as_version : int | |
|
51 | The version of the notebook format to return. | |
|
52 | The notebook will be converted, if necessary. | |
|
53 | Pass nbformat.NO_CONVERT to prevent conversion. | |
|
54 | ||
|
55 | Returns | |
|
56 | ------- | |
|
57 | nb : NotebookNode | |
|
58 | The notebook that was read. | |
|
59 | """ | |
|
60 | nb = reader.reads(s, **kwargs) | |
|
61 | if as_version is not NO_CONVERT: | |
|
62 | nb = convert(nb, as_version) | |
|
63 | try: | |
|
64 | validate(nb) | |
|
65 | except ValidationError as e: | |
|
66 | get_logger().error("Notebook JSON is invalid: %s", e) | |
|
67 | return nb | |
|
68 | ||
|
69 | ||
|
70 | def writes(nb, version, **kwargs): | |
|
71 | """Write a notebook to a string in a given format in the given nbformat version. | |
|
72 | ||
|
73 | Any notebook format errors will be logged. | |
|
74 | ||
|
75 | Parameters | |
|
76 | ---------- | |
|
77 | nb : NotebookNode | |
|
78 | The notebook to write. | |
|
79 | version : int | |
|
80 | The nbformat version to write. | |
|
81 | If nb is not this version, it will be converted. | |
|
82 | Pass nbformat.NO_CONVERT to prevent conversion. | |
|
83 | ||
|
84 | Returns | |
|
85 | ------- | |
|
86 | s : unicode | |
|
87 | The notebook as a JSON string. | |
|
88 | """ | |
|
89 | if version is not NO_CONVERT: | |
|
90 | nb = convert(nb, version) | |
|
91 | else: | |
|
92 | version, _ = reader.get_version(nb) | |
|
93 | try: | |
|
94 | validate(nb) | |
|
95 | except ValidationError as e: | |
|
96 | get_logger().error("Notebook JSON is invalid: %s", e) | |
|
97 | return versions[version].writes_json(nb, **kwargs) | |
|
98 | ||
|
99 | ||
|
100 | def read(fp, as_version, **kwargs): | |
|
101 | """Read a notebook from a file as a NotebookNode of the given version. | |
|
102 | ||
|
103 | The string can contain a notebook of any version. | |
|
104 | The notebook will be returned `as_version`, converting, if necessary. | |
|
105 | ||
|
106 | Notebook format errors will be logged. | |
|
107 | ||
|
108 | Parameters | |
|
109 | ---------- | |
|
110 | fp : file | |
|
111 | Any file-like object with a read method. | |
|
112 | as_version: int | |
|
113 | The version of the notebook format to return. | |
|
114 | The notebook will be converted, if necessary. | |
|
115 | Pass nbformat.NO_CONVERT to prevent conversion. | |
|
116 | ||
|
117 | Returns | |
|
118 | ------- | |
|
119 | nb : NotebookNode | |
|
120 | The notebook that was read. | |
|
121 | """ | |
|
122 | return reads(fp.read(), as_version, **kwargs) | |
|
123 | ||
|
124 | ||
|
125 | def write(fp, nb, version, **kwargs): | |
|
126 | """Write a notebook to a file in a given nbformat version. | |
|
127 | ||
|
128 | The file-like object must accept unicode input. | |
|
129 | ||
|
130 | Parameters | |
|
131 | ---------- | |
|
132 | fp : file | |
|
133 | Any file-like object with a write method that accepts unicode. | |
|
134 | nb : NotebookNode | |
|
135 | The notebook to write. | |
|
136 | version : int | |
|
137 | The nbformat version to write. | |
|
138 | If nb is not this version, it will be converted. | |
|
139 | """ | |
|
140 | s = writes(nb, version, **kwargs) | |
|
141 | if isinstance(s, bytes): | |
|
142 | s = s.decode('utf8') | |
|
143 | return fp.write(s) |
@@ -3,7 +3,8 b'' | |||
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 |
from . |
|
|
6 | from . import versions | |
|
7 | from .reader import get_version | |
|
7 | 8 | |
|
8 | 9 | |
|
9 | 10 | def convert(nb, to_version): |
@@ -24,7 +25,7 b' def convert(nb, to_version):' | |||
|
24 | 25 | # Get input notebook version. |
|
25 | 26 | (version, version_minor) = get_version(nb) |
|
26 | 27 | |
|
27 |
# Check if destination is |
|
|
28 | # Check if destination is target version, if so return contents | |
|
28 | 29 | if version == to_version: |
|
29 | 30 | return nb |
|
30 | 31 |
@@ -17,8 +17,8 b' from IPython.nbformat.v3 import (' | |||
|
17 | 17 | from IPython.nbformat import v3 as _v_latest |
|
18 | 18 | |
|
19 | 19 | from .reader import reads as reader_reads |
|
20 |
from . |
|
|
21 | from .convert import convert | |
|
20 | from . import versions | |
|
21 | from .converter import convert | |
|
22 | 22 | from .validator import validate, ValidationError |
|
23 | 23 | |
|
24 | 24 | from IPython.utils.log import get_logger |
@@ -5,19 +5,6 b'' | |||
|
5 | 5 | |
|
6 | 6 | import json |
|
7 | 7 | |
|
8 | from . import v1 | |
|
9 | from . import v2 | |
|
10 | from . import v3 | |
|
11 | from . import v4 | |
|
12 | ||
|
13 | versions = { | |
|
14 | 1: v1, | |
|
15 | 2: v2, | |
|
16 | 3: v3, | |
|
17 | 4: v4, | |
|
18 | } | |
|
19 | ||
|
20 | ||
|
21 | 8 | class NotJSONError(ValueError): |
|
22 | 9 | pass |
|
23 | 10 | |
@@ -66,7 +53,7 b' def reads(s, **kwargs):' | |||
|
66 | 53 | nb : NotebookNode |
|
67 | 54 | The notebook that was read. |
|
68 | 55 | """ |
|
69 |
from . |
|
|
56 | from . import versions, NBFormatError | |
|
70 | 57 | |
|
71 | 58 | nb_dict = parse_json(s, **kwargs) |
|
72 | 59 | (major, minor) = get_version(nb_dict) |
@@ -10,12 +10,13 b' from hmac import HMAC' | |||
|
10 | 10 | import io |
|
11 | 11 | import os |
|
12 | 12 | |
|
13 | from IPython.utils.io import atomic_writing | |
|
13 | 14 | from IPython.utils.py3compat import string_types, unicode_type, cast_bytes |
|
14 | 15 | from IPython.utils.traitlets import Instance, Bytes, Enum, Any, Unicode, Bool |
|
15 | 16 | from IPython.config import LoggingConfigurable, MultipleInstanceError |
|
16 | 17 | from IPython.core.application import BaseIPythonApplication, base_flags |
|
17 | 18 | |
|
18 |
from . |
|
|
19 | from . import read, write, NO_CONVERT | |
|
19 | 20 | |
|
20 | 21 | try: |
|
21 | 22 | # Python 3 |
@@ -278,14 +279,14 b' class TrustNotebookApp(BaseIPythonApplication):' | |||
|
278 | 279 | self.log.error("Notebook missing: %s" % notebook_path) |
|
279 | 280 | self.exit(1) |
|
280 | 281 | with io.open(notebook_path, encoding='utf8') as f: |
|
281 |
nb = read(f, |
|
|
282 | nb = read(f, NO_CONVERT) | |
|
282 | 283 | if self.notary.check_signature(nb): |
|
283 | 284 | print("Notebook already signed: %s" % notebook_path) |
|
284 | 285 | else: |
|
285 | 286 | print("Signing notebook: %s" % notebook_path) |
|
286 | 287 | self.notary.sign(nb) |
|
287 |
with |
|
|
288 |
write(nb, |
|
|
288 | with atomic_writing(notebook_path) as f: | |
|
289 | write(f, nb, NO_CONVERT) | |
|
289 | 290 | |
|
290 | 291 | def generate_new_key(self): |
|
291 | 292 | """Generate a new notebook signature key""" |
@@ -1,29 +1,25 b'' | |||
|
1 | """ | |
|
2 | Contains tests class for current.py | |
|
3 | """ | |
|
1 | """Test the APIs at the top-level of nbformat""" | |
|
4 | 2 | |
|
5 | 3 | # Copyright (c) IPython Development Team. |
|
6 | 4 | # Distributed under the terms of the Modified BSD License. |
|
7 | 5 | |
|
8 | import io | |
|
9 | 6 | import json |
|
10 | import tempfile | |
|
11 | 7 | |
|
12 | 8 | from .base import TestsBase |
|
13 | 9 | |
|
14 | 10 | from ..reader import get_version |
|
15 |
from . |
|
|
11 | from IPython.nbformat import read, current_nbformat, writes | |
|
16 | 12 | |
|
17 | 13 | |
|
18 |
class Test |
|
|
14 | class TestAPI(TestsBase): | |
|
19 | 15 | |
|
20 | 16 | def test_read(self): |
|
21 | 17 | """Can older notebooks be opened and automatically converted to the current |
|
22 | 18 | nbformat?""" |
|
23 | 19 | |
|
24 | 20 | # Open a version 2 notebook. |
|
25 |
with self.fopen(u'test2.ipynb', |
|
|
26 | nb = read(f) | |
|
21 | with self.fopen(u'test2.ipynb', 'r') as f: | |
|
22 | nb = read(f, as_version=current_nbformat) | |
|
27 | 23 | |
|
28 | 24 | # Check that the notebook was upgraded to the latest version automatically. |
|
29 | 25 | (major, minor) = get_version(nb) |
@@ -33,7 +29,7 b' class TestCurrent(TestsBase):' | |||
|
33 | 29 | """dowgrade a v3 notebook to v2""" |
|
34 | 30 | # Open a version 3 notebook. |
|
35 | 31 | with self.fopen(u'test3.ipynb', 'r') as f: |
|
36 |
nb = read(f, |
|
|
32 | nb = read(f, as_version=3) | |
|
37 | 33 | |
|
38 | 34 | jsons = writes(nb, version=2) |
|
39 | 35 | nb2 = json.loads(jsons) |
@@ -5,9 +5,9 b'' | |||
|
5 | 5 | |
|
6 | 6 | from .base import TestsBase |
|
7 | 7 | |
|
8 | from ..convert import convert | |
|
8 | from ..converter import convert | |
|
9 | 9 | from ..reader import read, get_version |
|
10 |
from .. |
|
|
10 | from .. import current_nbformat | |
|
11 | 11 | |
|
12 | 12 | |
|
13 | 13 | class TestConvert(TestsBase): |
@@ -3,10 +3,9 b'' | |||
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | from .. import sign | |
|
7 | 6 | from .base import TestsBase |
|
8 | 7 | |
|
9 |
from . |
|
|
8 | from IPython.nbformat import read, sign | |
|
10 | 9 | from IPython.core.getipython import get_ipython |
|
11 | 10 | |
|
12 | 11 | |
@@ -18,7 +17,7 b' class TestNotary(TestsBase):' | |||
|
18 | 17 | profile_dir=get_ipython().profile_dir |
|
19 | 18 | ) |
|
20 | 19 | with self.fopen(u'test3.ipynb', u'r') as f: |
|
21 |
self.nb = read(f, |
|
|
20 | self.nb = read(f, as_version=4) | |
|
22 | 21 | |
|
23 | 22 | def test_algorithms(self): |
|
24 | 23 | last_sig = '' |
@@ -7,7 +7,7 b' import os' | |||
|
7 | 7 | |
|
8 | 8 | from .base import TestsBase |
|
9 | 9 | from jsonschema import ValidationError |
|
10 |
from . |
|
|
10 | from IPython.nbformat import read | |
|
11 | 11 | from ..validator import isvalid, validate |
|
12 | 12 | |
|
13 | 13 | |
@@ -16,21 +16,21 b' class TestValidator(TestsBase):' | |||
|
16 | 16 | def test_nb2(self): |
|
17 | 17 | """Test that a v2 notebook converted to current passes validation""" |
|
18 | 18 | with self.fopen(u'test2.ipynb', u'r') as f: |
|
19 |
nb = read(f, |
|
|
19 | nb = read(f, as_version=4) | |
|
20 | 20 | validate(nb) |
|
21 | 21 | self.assertEqual(isvalid(nb), True) |
|
22 | 22 | |
|
23 | 23 | def test_nb3(self): |
|
24 | 24 | """Test that a v3 notebook passes validation""" |
|
25 | 25 | with self.fopen(u'test3.ipynb', u'r') as f: |
|
26 |
nb = read(f, |
|
|
26 | nb = read(f, as_version=4) | |
|
27 | 27 | validate(nb) |
|
28 | 28 | self.assertEqual(isvalid(nb), True) |
|
29 | 29 | |
|
30 | 30 | def test_nb4(self): |
|
31 | 31 | """Test that a v4 notebook passes validation""" |
|
32 | 32 | with self.fopen(u'test4.ipynb', u'r') as f: |
|
33 |
nb = read(f, |
|
|
33 | nb = read(f, as_version=4) | |
|
34 | 34 | validate(nb) |
|
35 | 35 | self.assertEqual(isvalid(nb), True) |
|
36 | 36 | |
@@ -41,7 +41,7 b' class TestValidator(TestsBase):' | |||
|
41 | 41 | # - invalid cell type |
|
42 | 42 | # - invalid output_type |
|
43 | 43 | with self.fopen(u'invalid.ipynb', u'r') as f: |
|
44 |
nb = read(f, |
|
|
44 | nb = read(f, as_version=4) | |
|
45 | 45 | with self.assertRaises(ValidationError): |
|
46 | 46 | validate(nb) |
|
47 | 47 | self.assertEqual(isvalid(nb), False) |
@@ -49,7 +49,7 b' class TestValidator(TestsBase):' | |||
|
49 | 49 | def test_future(self): |
|
50 | 50 | """Test than a notebook from the future with extra keys passes validation""" |
|
51 | 51 | with self.fopen(u'test4plus.ipynb', u'r') as f: |
|
52 | nb = read(f) | |
|
52 | nb = read(f, as_version=4) | |
|
53 | 53 | with self.assertRaises(ValidationError): |
|
54 | 54 | validate(nb, version=4) |
|
55 | 55 |
@@ -16,7 +16,7 b' from IPython.utils.log import get_logger' | |||
|
16 | 16 | |
|
17 | 17 | def _warn_if_invalid(nb, version): |
|
18 | 18 | """Log validation errors, if there are any.""" |
|
19 |
from IPython.nbformat |
|
|
19 | from IPython.nbformat import validate, ValidationError | |
|
20 | 20 | try: |
|
21 | 21 | validate(nb, version=version) |
|
22 | 22 | except ValidationError as e: |
@@ -19,7 +19,7 b" nbformat_schema = 'nbformat.v4.schema.json'" | |||
|
19 | 19 | |
|
20 | 20 | def validate(node, ref=None): |
|
21 | 21 | """validate a v4 node""" |
|
22 |
from .. |
|
|
22 | from .. import validate | |
|
23 | 23 | return validate(node, ref=ref, version=nbformat) |
|
24 | 24 | |
|
25 | 25 |
@@ -2,7 +2,7 b' import copy' | |||
|
2 | 2 | |
|
3 | 3 | import nose.tools as nt |
|
4 | 4 | |
|
5 |
from IPython.nbformat |
|
|
5 | from IPython.nbformat import validate | |
|
6 | 6 | from .. import convert |
|
7 | 7 | |
|
8 | 8 | from . import nbexamples |
@@ -43,7 +43,8 b' def _relax_additional_properties(obj):' | |||
|
43 | 43 | def get_validator(version=None, version_minor=None): |
|
44 | 44 | """Load the JSON schema into a Validator""" |
|
45 | 45 | if version is None: |
|
46 |
from . |
|
|
46 | from .. import current_nbformat | |
|
47 | version = current_nbformat | |
|
47 | 48 | |
|
48 | 49 | v = import_item("IPython.nbformat.v%s" % version) |
|
49 | 50 | current_minor = v.nbformat_minor |
General Comments 0
You need to be logged in to leave comments.
Login now