Show More
@@ -0,0 +1,164 b'' | |||
|
1 | { | |
|
2 | "metadata": { | |
|
3 | "cell_tags": [ | |
|
4 | [ | |
|
5 | "<None>", | |
|
6 | null | |
|
7 | ] | |
|
8 | ], | |
|
9 | "name": "" | |
|
10 | }, | |
|
11 | "nbformat": 3, | |
|
12 | "nbformat_minor": 5, | |
|
13 | "extra": 5, | |
|
14 | "worksheets": [ | |
|
15 | { | |
|
16 | "cells": [ | |
|
17 | { | |
|
18 | "cell_type": "heading", | |
|
19 | "level": 1, | |
|
20 | "metadata": {}, | |
|
21 | "source": [ | |
|
22 | "nbconvert latex test" | |
|
23 | ] | |
|
24 | }, | |
|
25 | { | |
|
26 | "cell_type": "markdown", | |
|
27 | "extra_key": ["list"], | |
|
28 | "metadata": {}, | |
|
29 | "source": [ | |
|
30 | "**Lorem ipsum** dolor sit amet, consectetur adipiscing elit. Nunc luctus bibendum felis dictum sodales. Ut suscipit, orci ut interdum imperdiet, purus ligula mollis *justo*, non malesuada nisl augue eget lorem. Donec bibendum, erat sit amet porttitor aliquam, urna lorem ornare libero, in vehicula diam diam ut ante. Nam non urna rhoncus, accumsan elit sit amet, mollis tellus. Vestibulum nec tellus metus. Vestibulum tempor, ligula et vehicula rhoncus, sapien turpis faucibus lorem, id dapibus turpis mauris ac orci. Sed volutpat vestibulum venenatis." | |
|
31 | ] | |
|
32 | }, | |
|
33 | { | |
|
34 | "cell_type": "heading", | |
|
35 | "level": 2, | |
|
36 | "metadata": {}, | |
|
37 | "another_attr": {}, | |
|
38 | "source": [ | |
|
39 | "Printed Using Python" | |
|
40 | ] | |
|
41 | }, | |
|
42 | { | |
|
43 | "cell_type": "code", | |
|
44 | "collapsed": false, | |
|
45 | "key": "value", | |
|
46 | "input": [ | |
|
47 | "print(\"hello\")" | |
|
48 | ], | |
|
49 | "language": "python", | |
|
50 | "metadata": {}, | |
|
51 | "outputs": [ | |
|
52 | { | |
|
53 | "output_type": "stream", | |
|
54 | "meta": 5, | |
|
55 | "stream": "stdout", | |
|
56 | "text": [ | |
|
57 | "hello\n" | |
|
58 | ] | |
|
59 | } | |
|
60 | ], | |
|
61 | "prompt_number": 1 | |
|
62 | }, | |
|
63 | { | |
|
64 | "cell_type": "heading", | |
|
65 | "level": 2, | |
|
66 | "metadata": {}, | |
|
67 | "source": [ | |
|
68 | "Pyout" | |
|
69 | ] | |
|
70 | }, | |
|
71 | { | |
|
72 | "cell_type": "code", | |
|
73 | "collapsed": false, | |
|
74 | "input": [ | |
|
75 | "from IPython.display import HTML\n", | |
|
76 | "HTML(\"\"\"\n", | |
|
77 | "<script>\n", | |
|
78 | "console.log(\"hello\");\n", | |
|
79 | "</script>\n", | |
|
80 | "<b>HTML</b>\n", | |
|
81 | "\"\"\")" | |
|
82 | ], | |
|
83 | "language": "python", | |
|
84 | "metadata": {}, | |
|
85 | "outputs": [ | |
|
86 | { | |
|
87 | "html": [ | |
|
88 | "\n", | |
|
89 | "<script>\n", | |
|
90 | "console.log(\"hello\");\n", | |
|
91 | "</script>\n", | |
|
92 | "<b>HTML</b>\n" | |
|
93 | ], | |
|
94 | "metadata": {}, | |
|
95 | "output_type": "pyout", | |
|
96 | "key": "value", | |
|
97 | "prompt_number": 3, | |
|
98 | "text": [ | |
|
99 | "<IPython.core.display.HTML at 0x1112757d0>" | |
|
100 | ] | |
|
101 | } | |
|
102 | ], | |
|
103 | "prompt_number": 3 | |
|
104 | }, | |
|
105 | { | |
|
106 | "cell_type": "code", | |
|
107 | "collapsed": false, | |
|
108 | "input": [ | |
|
109 | "%%javascript\n", | |
|
110 | "console.log(\"hi\");" | |
|
111 | ], | |
|
112 | "language": "python", | |
|
113 | "metadata": {}, | |
|
114 | "outputs": [ | |
|
115 | { | |
|
116 | "javascript": [ | |
|
117 | "console.log(\"hi\");" | |
|
118 | ], | |
|
119 | "metadata": {}, | |
|
120 | "output_type": "display_data", | |
|
121 | "text": [ | |
|
122 | "<IPython.core.display.Javascript at 0x1112b4b50>" | |
|
123 | ] | |
|
124 | } | |
|
125 | ], | |
|
126 | "prompt_number": 7 | |
|
127 | }, | |
|
128 | { | |
|
129 | "cell_type": "heading", | |
|
130 | "level": 3, | |
|
131 | "metadata": {}, | |
|
132 | "source": [ | |
|
133 | "Image" | |
|
134 | ] | |
|
135 | }, | |
|
136 | { | |
|
137 | "cell_type": "code", | |
|
138 | "collapsed": false, | |
|
139 | "input": [ | |
|
140 | "from IPython.display import Image\n", | |
|
141 | "Image(\"http://ipython.org/_static/IPy_header.png\")" | |
|
142 | ], | |
|
143 | "language": "python", | |
|
144 | "metadata": {}, | |
|
145 | "outputs": [ | |
|
146 | { | |
|
147 | "metadata": {}, | |
|
148 | "output_type": "pyout", | |
|
149 | "more": "data", | |
|
150 | "png": "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\n", | |
|
151 | "prompt_number": 6, | |
|
152 | "text": [ | |
|
153 | "<IPython.core.display.Image at 0x111275490>" | |
|
154 | ] | |
|
155 | } | |
|
156 | ], | |
|
157 | "prompt_number": 6 | |
|
158 | } | |
|
159 | ], | |
|
160 | "keys": ["value", "s"], | |
|
161 | "metadata": {} | |
|
162 | } | |
|
163 | ] | |
|
164 | } No newline at end of file |
@@ -1,45 +1,54 b'' | |||
|
1 | 1 | """Test nbformat.validator""" |
|
2 | 2 | |
|
3 | 3 | # Copyright (c) IPython Development Team. |
|
4 | 4 | # Distributed under the terms of the Modified BSD License. |
|
5 | 5 | |
|
6 | 6 | import os |
|
7 | 7 | |
|
8 | 8 | from .base import TestsBase |
|
9 | 9 | from jsonschema import ValidationError |
|
10 | 10 | from ..current import read |
|
11 | 11 | from ..validator import isvalid, validate |
|
12 | 12 | |
|
13 | 13 | |
|
14 | 14 | #----------------------------------------------------------------------------- |
|
15 | 15 | # Classes and functions |
|
16 | 16 | #----------------------------------------------------------------------------- |
|
17 | 17 | |
|
18 | 18 | class TestValidator(TestsBase): |
|
19 | 19 | |
|
20 | 20 | def test_nb2(self): |
|
21 | 21 | """Test that a v2 notebook converted to v3 passes validation""" |
|
22 | 22 | with self.fopen(u'test2.ipynb', u'r') as f: |
|
23 | 23 | nb = read(f, u'json') |
|
24 | 24 | validate(nb) |
|
25 | 25 | self.assertEqual(isvalid(nb), True) |
|
26 | 26 | |
|
27 | 27 | def test_nb3(self): |
|
28 | 28 | """Test that a v3 notebook passes validation""" |
|
29 | 29 | with self.fopen(u'test3.ipynb', u'r') as f: |
|
30 | 30 | nb = read(f, u'json') |
|
31 | 31 | validate(nb) |
|
32 | 32 | self.assertEqual(isvalid(nb), True) |
|
33 | 33 | |
|
34 | 34 | def test_invalid(self): |
|
35 | 35 | """Test than an invalid notebook does not pass validation""" |
|
36 | 36 | # this notebook has a few different errors: |
|
37 | 37 | # - the name is an integer, rather than a string |
|
38 | 38 | # - one cell is missing its source |
|
39 | 39 | # - one cell has an invalid level |
|
40 | 40 | with self.fopen(u'invalid.ipynb', u'r') as f: |
|
41 | 41 | nb = read(f, u'json') |
|
42 | 42 | with self.assertRaises(ValidationError): |
|
43 | 43 | validate(nb) |
|
44 | 44 | self.assertEqual(isvalid(nb), False) |
|
45 | 45 | |
|
46 | def test_future(self): | |
|
47 | """Test than a notebook from the future with extra keys passes validation""" | |
|
48 | with self.fopen(u'test3plus.ipynb', u'r') as f: | |
|
49 | nb = read(f) | |
|
50 | with self.assertRaises(ValidationError): | |
|
51 | validate(nb, version=3) | |
|
52 | ||
|
53 | self.assertEqual(isvalid(nb, version=3), False) | |
|
54 | self.assertEqual(isvalid(nb), True) |
@@ -1,117 +1,146 b'' | |||
|
1 | 1 | # Copyright (c) IPython Development Team. |
|
2 | 2 | # Distributed under the terms of the Modified BSD License. |
|
3 | 3 | |
|
4 | 4 | from __future__ import print_function |
|
5 | 5 | import json |
|
6 | 6 | import os |
|
7 | import warnings | |
|
7 | 8 | |
|
8 | 9 | try: |
|
9 | 10 | from jsonschema import ValidationError |
|
10 | 11 | from jsonschema import Draft4Validator as Validator |
|
11 | 12 | except ImportError as e: |
|
12 | 13 | verbose_msg = """ |
|
13 | 14 | |
|
14 | 15 | IPython notebook format depends on the jsonschema package: |
|
15 | 16 | |
|
16 | 17 | https://pypi.python.org/pypi/jsonschema |
|
17 | 18 | |
|
18 | 19 | Please install it first. |
|
19 | 20 | """ |
|
20 | 21 | raise ImportError(str(e) + verbose_msg) |
|
21 | 22 | |
|
22 | 23 | from IPython.utils.importstring import import_item |
|
23 | 24 | |
|
24 | 25 | |
|
25 | 26 | validators = {} |
|
26 | 27 | |
|
27 | def get_validator(version=None): | |
|
28 | def _relax_additional_properties(obj): | |
|
29 | """relax any `additionalProperties`""" | |
|
30 | if isinstance(obj, dict): | |
|
31 | for key, value in obj.items(): | |
|
32 | if key == 'additionalProperties': | |
|
33 | print(obj) | |
|
34 | value = True | |
|
35 | else: | |
|
36 | value = _relax_additional_properties(value) | |
|
37 | obj[key] = value | |
|
38 | elif isinstance(obj, list): | |
|
39 | for i, value in enumerate(obj): | |
|
40 | obj[i] = _relax_additional_properties(value) | |
|
41 | return obj | |
|
42 | ||
|
43 | def get_validator(version=None, version_minor=None): | |
|
28 | 44 | """Load the JSON schema into a Validator""" |
|
29 | 45 | if version is None: |
|
30 | 46 | from .current import nbformat as version |
|
31 | 47 | |
|
32 | if version not in validators: | |
|
33 | v = import_item("IPython.nbformat.v%s" % version) | |
|
48 | v = import_item("IPython.nbformat.v%s" % version) | |
|
49 | current_minor = v.nbformat_minor | |
|
50 | if version_minor is None: | |
|
51 | version_minor = current_minor | |
|
52 | ||
|
53 | version_tuple = (version, version_minor) | |
|
54 | ||
|
55 | if version_tuple not in validators: | |
|
34 | 56 | try: |
|
35 | 57 | v.nbformat_schema |
|
36 | 58 | except AttributeError: |
|
37 | 59 | # no validator |
|
38 | 60 | return None |
|
39 | 61 | schema_path = os.path.join(os.path.dirname(v.__file__), v.nbformat_schema) |
|
40 | 62 | with open(schema_path) as f: |
|
41 | 63 | schema_json = json.load(f) |
|
42 | validators[version] = Validator(schema_json) | |
|
43 | return validators[version] | |
|
44 | 64 | |
|
45 | def isvalid(nbjson, ref=None, version=None): | |
|
65 | if current_minor < version_minor: | |
|
66 | # notebook from the future, relax all `additionalProperties: False` requirements | |
|
67 | schema_json = _relax_additional_properties(schema_json) | |
|
68 | ||
|
69 | validators[version_tuple] = Validator(schema_json) | |
|
70 | return validators[version_tuple] | |
|
71 | ||
|
72 | def isvalid(nbjson, ref=None, version=None, version_minor=None): | |
|
46 | 73 | """Checks whether the given notebook JSON conforms to the current |
|
47 | 74 | notebook format schema. Returns True if the JSON is valid, and |
|
48 | 75 | False otherwise. |
|
49 | 76 | |
|
50 | 77 | To see the individual errors that were encountered, please use the |
|
51 | 78 | `validate` function instead. |
|
52 | 79 | """ |
|
53 | 80 | try: |
|
54 | validate(nbjson, ref, version) | |
|
81 | validate(nbjson, ref, version, version_minor) | |
|
55 | 82 | except ValidationError: |
|
56 | 83 | return False |
|
57 | 84 | else: |
|
58 | 85 | return True |
|
59 | 86 | |
|
60 | 87 | |
|
61 | def better_validation_error(error, version): | |
|
88 | def better_validation_error(error, version, version_minor): | |
|
62 | 89 | """Get better ValidationError on oneOf failures |
|
63 | 90 | |
|
64 | 91 | oneOf errors aren't informative. |
|
65 | 92 | if it's a cell type or output_type error, |
|
66 | 93 | try validating directly based on the type for a better error message |
|
67 | 94 | """ |
|
68 | 95 | key = error.schema_path[-1] |
|
69 | 96 | if key.endswith('Of'): |
|
70 | 97 | |
|
71 | 98 | ref = None |
|
72 | 99 | if isinstance(error.instance, dict): |
|
73 | 100 | if 'cell_type' in error.instance: |
|
74 | 101 | ref = error.instance['cell_type'] + "_cell" |
|
75 | 102 | elif 'output_type' in error.instance: |
|
76 | 103 | ref = error.instance['output_type'] |
|
77 | 104 | |
|
78 | 105 | if ref: |
|
79 | 106 | try: |
|
80 | 107 | validate(error.instance, |
|
81 | 108 | ref, |
|
82 | version=version | |
|
109 | version=version, | |
|
110 | version_minor=version_minor, | |
|
83 | 111 | ) |
|
84 | 112 | except ValidationError as e: |
|
85 | return better_validation_error(e, version) | |
|
113 | return better_validation_error(e, version, version_minor) | |
|
86 | 114 | except: |
|
87 | 115 | # if it fails for some reason, |
|
88 | 116 | # let the original error through |
|
89 | 117 | pass |
|
90 | 118 | |
|
91 | 119 | return error |
|
92 | 120 | |
|
93 | 121 | |
|
94 | def validate(nbjson, ref=None, version=None): | |
|
122 | def validate(nbjson, ref=None, version=None, version_minor=None): | |
|
95 | 123 | """Checks whether the given notebook JSON conforms to the current |
|
96 | 124 | notebook format schema. |
|
97 | 125 | |
|
98 | 126 | Raises ValidationError if not valid. |
|
99 | 127 | """ |
|
100 | 128 | if version is None: |
|
101 |
from . |
|
|
102 | version = nbjson.get('nbformat', nbformat) | |
|
129 | from .reader import get_version | |
|
130 | (version, version_minor) = get_version(nbjson) | |
|
103 | 131 | |
|
104 | validator = get_validator(version) | |
|
132 | validator = get_validator(version, version_minor) | |
|
105 | 133 | |
|
106 | 134 | if validator is None: |
|
107 | 135 | # no validator |
|
136 | warnings.warn("No schema for validating v%s notebooks" % version, UserWarning) | |
|
108 | 137 | return |
|
109 | 138 | |
|
110 | 139 | try: |
|
111 | 140 | if ref: |
|
112 | 141 | return validator.validate(nbjson, {'$ref' : '#/definitions/%s' % ref}) |
|
113 | 142 | else: |
|
114 | 143 | return validator.validate(nbjson) |
|
115 | 144 | except ValidationError as e: |
|
116 | raise better_validation_error(e, version) | |
|
145 | raise better_validation_error(e, version, version_minor) | |
|
117 | 146 |
General Comments 0
You need to be logged in to leave comments.
Login now