##// END OF EJS Templates
remove nbconvert
Min RK -
Show More
@@ -146,7 +146,7 b" have['zmq'] = test_for('zmq.pyzmq_version_info', min_zmq, callback=lambda x: x()"
146
146
147 test_group_names = ['core',
147 test_group_names = ['core',
148 'extensions', 'lib', 'terminal', 'testing', 'utils',
148 'extensions', 'lib', 'terminal', 'testing', 'utils',
149 'html', 'nbconvert'
149 'html',
150 ]
150 ]
151
151
152 class TestSection(object):
152 class TestSection(object):
@@ -239,22 +239,9 b" sec.exclude('static')"
239 sec.exclude('tasks')
239 sec.exclude('tasks')
240 if not have['jinja2']:
240 if not have['jinja2']:
241 sec.exclude('notebookapp')
241 sec.exclude('notebookapp')
242 if not have['pygments'] or not have['jinja2']:
243 sec.exclude('nbconvert')
244 if not have['terminado']:
242 if not have['terminado']:
245 sec.exclude('terminal')
243 sec.exclude('terminal')
246
244
247 # nbconvert:
248 sec = test_sections['nbconvert']
249 sec.requires('pygments', 'jinja2', 'jsonschema', 'mistune')
250 # Exclude nbconvert directories containing config files used to test.
251 # Executing the config files with iptest would cause an exception.
252 sec.exclude('tests.files')
253 sec.exclude('exporters.tests.files')
254 if not have['tornado']:
255 sec.exclude('nbconvert.post_processors.serve')
256 sec.exclude('nbconvert.post_processors.tests.test_serve')
257
258
245
259 #-----------------------------------------------------------------------------
246 #-----------------------------------------------------------------------------
260 # Functions and classes
247 # Functions and classes
@@ -7,3 +7,4 b''
7 -e git+https://github.com/jupyter/jupyter_nbformat.git#egg=jupyter_nbformat
7 -e git+https://github.com/jupyter/jupyter_nbformat.git#egg=jupyter_nbformat
8 -e git+https://github.com/jupyter/jupyter_client.git#egg=jupyter_client
8 -e git+https://github.com/jupyter/jupyter_client.git#egg=jupyter_client
9 -e git+https://github.com/ipython/ipython_kernel.git#egg=ipython_kernel
9 -e git+https://github.com/ipython/ipython_kernel.git#egg=ipython_kernel
10 -e git+https://github.com/jupyter/jupyter_nbconvert.git#egg=jupyter_nbconvert
@@ -176,20 +176,6 b' def find_package_data():'
176 # os.chdir(os.path.join('tests',))
176 # os.chdir(os.path.join('tests',))
177 # js_tests = glob('*.js') + glob('*/*.js')
177 # js_tests = glob('*.js') + glob('*/*.js')
178
178
179 # nbconvert package_data:
180 # os.chdir(os.path.join(cwd, 'IPython', 'nbconvert'))
181 # nbconvert_templates = [os.path.join(dirpath, '*.*')
182 # for dirpath, _, _ in os.walk('templates')]
183 # package_data = {
184 # 'IPython.nbconvert.filters' : ['marked.js'],
185 # 'IPython.nbconvert' : nbconvert_templates +
186 # [
187 # 'tests/files/*.*',
188 # 'exporters/tests/files/*.*',
189 # 'preprocessors/tests/files/*.*',
190 # ],
191 # }
192
193 # os.chdir(cwd)
179 # os.chdir(cwd)
194
180
195 package_data = {
181 package_data = {
@@ -1,7 +0,0 b''
1 """Utilities for converting notebooks to and from different formats."""
2
3 from .exporters import *
4 from . import filters
5 from . import preprocessors
6 from . import postprocessors
7 from . import writers
@@ -1,2 +0,0 b''
1 from .nbconvertapp import launch_new_instance
2 launch_new_instance()
@@ -1,11 +0,0 b''
1 from .export import *
2 from .html import HTMLExporter
3 from .slides import SlidesExporter
4 from .templateexporter import TemplateExporter
5 from .latex import LatexExporter
6 from .markdown import MarkdownExporter
7 from .notebook import NotebookExporter
8 from .pdf import PDFExporter
9 from .python import PythonExporter
10 from .rst import RSTExporter
11 from .exporter import Exporter, FilenameExtension
@@ -1,177 +0,0 b''
1 """Module containing single call export functions."""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from functools import wraps
7
8 from IPython.nbformat import NotebookNode
9 from IPython.utils.decorators import undoc
10 from IPython.utils.py3compat import string_types
11
12 from .exporter import Exporter
13 from .templateexporter import TemplateExporter
14 from .html import HTMLExporter
15 from .slides import SlidesExporter
16 from .latex import LatexExporter
17 from .pdf import PDFExporter
18 from .markdown import MarkdownExporter
19 from .python import PythonExporter
20 from .rst import RSTExporter
21 from .notebook import NotebookExporter
22 from .script import ScriptExporter
23
24 #-----------------------------------------------------------------------------
25 # Classes
26 #-----------------------------------------------------------------------------
27
28 @undoc
29 def DocDecorator(f):
30
31 #Set docstring of function
32 f.__doc__ = f.__doc__ + """
33 nb : :class:`~IPython.nbformat.NotebookNode`
34 The notebook to export.
35 config : config (optional, keyword arg)
36 User configuration instance.
37 resources : dict (optional, keyword arg)
38 Resources used in the conversion process.
39
40 Returns
41 -------
42 tuple- output, resources, exporter_instance
43 output : str
44 Jinja 2 output. This is the resulting converted notebook.
45 resources : dictionary
46 Dictionary of resources used prior to and during the conversion
47 process.
48 exporter_instance : Exporter
49 Instance of the Exporter class used to export the document. Useful
50 to caller because it provides a 'file_extension' property which
51 specifies what extension the output should be saved as.
52
53 Notes
54 -----
55 WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT
56 """
57
58 @wraps(f)
59 def decorator(*args, **kwargs):
60 return f(*args, **kwargs)
61
62 return decorator
63
64
65 #-----------------------------------------------------------------------------
66 # Functions
67 #-----------------------------------------------------------------------------
68
69 __all__ = [
70 'export',
71 'export_html',
72 'export_custom',
73 'export_slides',
74 'export_latex',
75 'export_pdf',
76 'export_markdown',
77 'export_python',
78 'export_script',
79 'export_rst',
80 'export_by_name',
81 'get_export_names',
82 'ExporterNameError'
83 ]
84
85
86 class ExporterNameError(NameError):
87 pass
88
89 @DocDecorator
90 def export(exporter, nb, **kw):
91 """
92 Export a notebook object using specific exporter class.
93
94 Parameters
95 ----------
96 exporter : class:`~jupyter_nbconvert.exporters.exporter.Exporter` class or instance
97 Class type or instance of the exporter that should be used. If the
98 method initializes it's own instance of the class, it is ASSUMED that
99 the class type provided exposes a constructor (``__init__``) with the same
100 signature as the base Exporter class.
101 """
102
103 #Check arguments
104 if exporter is None:
105 raise TypeError("Exporter is None")
106 elif not isinstance(exporter, Exporter) and not issubclass(exporter, Exporter):
107 raise TypeError("exporter does not inherit from Exporter (base)")
108 if nb is None:
109 raise TypeError("nb is None")
110
111 #Create the exporter
112 resources = kw.pop('resources', None)
113 if isinstance(exporter, Exporter):
114 exporter_instance = exporter
115 else:
116 exporter_instance = exporter(**kw)
117
118 #Try to convert the notebook using the appropriate conversion function.
119 if isinstance(nb, NotebookNode):
120 output, resources = exporter_instance.from_notebook_node(nb, resources)
121 elif isinstance(nb, string_types):
122 output, resources = exporter_instance.from_filename(nb, resources)
123 else:
124 output, resources = exporter_instance.from_file(nb, resources)
125 return output, resources
126
127 exporter_map = dict(
128 custom=TemplateExporter,
129 html=HTMLExporter,
130 slides=SlidesExporter,
131 latex=LatexExporter,
132 pdf=PDFExporter,
133 markdown=MarkdownExporter,
134 python=PythonExporter,
135 rst=RSTExporter,
136 notebook=NotebookExporter,
137 script=ScriptExporter,
138 )
139
140 def _make_exporter(name, E):
141 """make an export_foo function from a short key and Exporter class E"""
142 def _export(nb, **kw):
143 return export(E, nb, **kw)
144 _export.__doc__ = """Export a notebook object to {0} format""".format(name)
145 return _export
146
147 g = globals()
148
149 for name, E in exporter_map.items():
150 g['export_%s' % name] = DocDecorator(_make_exporter(name, E))
151
152 @DocDecorator
153 def export_by_name(format_name, nb, **kw):
154 """
155 Export a notebook object to a template type by its name. Reflection
156 (Inspect) is used to find the template's corresponding explicit export
157 method defined in this module. That method is then called directly.
158
159 Parameters
160 ----------
161 format_name : str
162 Name of the template style to export to.
163 """
164
165 function_name = "export_" + format_name.lower()
166
167 if function_name in globals():
168 return globals()[function_name](nb, **kw)
169 else:
170 raise ExporterNameError("template for `%s` not found" % function_name)
171
172
173 def get_export_names():
174 """Return a list of the currently supported export targets
175
176 WARNING: API WILL CHANGE IN FUTURE RELEASES OF NBCONVERT"""
177 return sorted(exporter_map.keys())
@@ -1,280 +0,0 b''
1 """This module defines a base Exporter class. For Jinja template-based export,
2 see templateexporter.py.
3 """
4
5
6 from __future__ import print_function, absolute_import
7
8 import io
9 import os
10 import copy
11 import collections
12 import datetime
13
14 from IPython.config.configurable import LoggingConfigurable
15 from IPython.config import Config
16 from IPython import nbformat
17 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, TraitError
18 from IPython.utils.importstring import import_item
19 from IPython.utils import text, py3compat
20
21
22 class ResourcesDict(collections.defaultdict):
23 def __missing__(self, key):
24 return ''
25
26
27 class FilenameExtension(Unicode):
28 """A trait for filename extensions."""
29
30 default_value = u''
31 info_text = 'a filename extension, beginning with a dot'
32
33 def validate(self, obj, value):
34 # cast to proper unicode
35 value = super(FilenameExtension, self).validate(obj, value)
36
37 # check that it starts with a dot
38 if value and not value.startswith('.'):
39 msg = "FileExtension trait '{}' does not begin with a dot: {!r}"
40 raise TraitError(msg.format(self.name, value))
41
42 return value
43
44
45 class Exporter(LoggingConfigurable):
46 """
47 Class containing methods that sequentially run a list of preprocessors on a
48 NotebookNode object and then return the modified NotebookNode object and
49 accompanying resources dict.
50 """
51
52 file_extension = FilenameExtension(
53 '.txt', config=True,
54 help="Extension of the file that should be written to disk"
55 )
56
57 # MIME type of the result file, for HTTP response headers.
58 # This is *not* a traitlet, because we want to be able to access it from
59 # the class, not just on instances.
60 output_mimetype = ''
61
62 #Configurability, allows the user to easily add filters and preprocessors.
63 preprocessors = List(config=True,
64 help="""List of preprocessors, by name or namespace, to enable.""")
65
66 _preprocessors = List()
67
68 default_preprocessors = List(['jupyter_nbconvert.preprocessors.coalesce_streams',
69 'jupyter_nbconvert.preprocessors.SVG2PDFPreprocessor',
70 'jupyter_nbconvert.preprocessors.ExtractOutputPreprocessor',
71 'jupyter_nbconvert.preprocessors.CSSHTMLHeaderPreprocessor',
72 'jupyter_nbconvert.preprocessors.RevealHelpPreprocessor',
73 'jupyter_nbconvert.preprocessors.LatexPreprocessor',
74 'jupyter_nbconvert.preprocessors.ClearOutputPreprocessor',
75 'jupyter_nbconvert.preprocessors.ExecutePreprocessor',
76 'jupyter_nbconvert.preprocessors.HighlightMagicsPreprocessor'],
77 config=True,
78 help="""List of preprocessors available by default, by name, namespace,
79 instance, or type.""")
80
81
82 def __init__(self, config=None, **kw):
83 """
84 Public constructor
85
86 Parameters
87 ----------
88 config : config
89 User configuration instance.
90 """
91 with_default_config = self.default_config
92 if config:
93 with_default_config.merge(config)
94
95 super(Exporter, self).__init__(config=with_default_config, **kw)
96
97 self._init_preprocessors()
98
99
100 @property
101 def default_config(self):
102 return Config()
103
104 def from_notebook_node(self, nb, resources=None, **kw):
105 """
106 Convert a notebook from a notebook node instance.
107
108 Parameters
109 ----------
110 nb : :class:`~IPython.nbformat.NotebookNode`
111 Notebook node (dict-like with attr-access)
112 resources : dict
113 Additional resources that can be accessed read/write by
114 preprocessors and filters.
115 **kw
116 Ignored (?)
117 """
118 nb_copy = copy.deepcopy(nb)
119 resources = self._init_resources(resources)
120
121 if 'language' in nb['metadata']:
122 resources['language'] = nb['metadata']['language'].lower()
123
124 # Preprocess
125 nb_copy, resources = self._preprocess(nb_copy, resources)
126
127 return nb_copy, resources
128
129
130 def from_filename(self, filename, resources=None, **kw):
131 """
132 Convert a notebook from a notebook file.
133
134 Parameters
135 ----------
136 filename : str
137 Full filename of the notebook file to open and convert.
138 """
139
140 # Pull the metadata from the filesystem.
141 if resources is None:
142 resources = ResourcesDict()
143 if not 'metadata' in resources or resources['metadata'] == '':
144 resources['metadata'] = ResourcesDict()
145 path, basename = os.path.split(filename)
146 notebook_name = basename[:basename.rfind('.')]
147 resources['metadata']['name'] = notebook_name
148 resources['metadata']['path'] = path
149
150 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
151 resources['metadata']['modified_date'] = modified_date.strftime(text.date_format)
152
153 with io.open(filename, encoding='utf-8') as f:
154 return self.from_notebook_node(nbformat.read(f, as_version=4), resources=resources, **kw)
155
156
157 def from_file(self, file_stream, resources=None, **kw):
158 """
159 Convert a notebook from a notebook file.
160
161 Parameters
162 ----------
163 file_stream : file-like object
164 Notebook file-like object to convert.
165 """
166 return self.from_notebook_node(nbformat.read(file_stream, as_version=4), resources=resources, **kw)
167
168
169 def register_preprocessor(self, preprocessor, enabled=False):
170 """
171 Register a preprocessor.
172 Preprocessors are classes that act upon the notebook before it is
173 passed into the Jinja templating engine. preprocessors are also
174 capable of passing additional information to the Jinja
175 templating engine.
176
177 Parameters
178 ----------
179 preprocessor : preprocessor
180 """
181 if preprocessor is None:
182 raise TypeError('preprocessor')
183 isclass = isinstance(preprocessor, type)
184 constructed = not isclass
185
186 # Handle preprocessor's registration based on it's type
187 if constructed and isinstance(preprocessor, py3compat.string_types):
188 # Preprocessor is a string, import the namespace and recursively call
189 # this register_preprocessor method
190 preprocessor_cls = import_item(preprocessor)
191 return self.register_preprocessor(preprocessor_cls, enabled)
192
193 if constructed and hasattr(preprocessor, '__call__'):
194 # Preprocessor is a function, no need to construct it.
195 # Register and return the preprocessor.
196 if enabled:
197 preprocessor.enabled = True
198 self._preprocessors.append(preprocessor)
199 return preprocessor
200
201 elif isclass and isinstance(preprocessor, MetaHasTraits):
202 # Preprocessor is configurable. Make sure to pass in new default for
203 # the enabled flag if one was specified.
204 self.register_preprocessor(preprocessor(parent=self), enabled)
205
206 elif isclass:
207 # Preprocessor is not configurable, construct it
208 self.register_preprocessor(preprocessor(), enabled)
209
210 else:
211 # Preprocessor is an instance of something without a __call__
212 # attribute.
213 raise TypeError('preprocessor')
214
215
216 def _init_preprocessors(self):
217 """
218 Register all of the preprocessors needed for this exporter, disabled
219 unless specified explicitly.
220 """
221 self._preprocessors = []
222
223 # Load default preprocessors (not necessarly enabled by default).
224 for preprocessor in self.default_preprocessors:
225 self.register_preprocessor(preprocessor)
226
227 # Load user-specified preprocessors. Enable by default.
228 for preprocessor in self.preprocessors:
229 self.register_preprocessor(preprocessor, enabled=True)
230
231
232 def _init_resources(self, resources):
233
234 #Make sure the resources dict is of ResourcesDict type.
235 if resources is None:
236 resources = ResourcesDict()
237 if not isinstance(resources, ResourcesDict):
238 new_resources = ResourcesDict()
239 new_resources.update(resources)
240 resources = new_resources
241
242 #Make sure the metadata extension exists in resources
243 if 'metadata' in resources:
244 if not isinstance(resources['metadata'], ResourcesDict):
245 new_metadata = ResourcesDict()
246 new_metadata.update(resources['metadata'])
247 resources['metadata'] = new_metadata
248 else:
249 resources['metadata'] = ResourcesDict()
250 if not resources['metadata']['name']:
251 resources['metadata']['name'] = 'Notebook'
252
253 #Set the output extension
254 resources['output_extension'] = self.file_extension
255 return resources
256
257
258 def _preprocess(self, nb, resources):
259 """
260 Preprocess the notebook before passing it into the Jinja engine.
261 To preprocess the notebook is to apply all of the
262
263 Parameters
264 ----------
265 nb : notebook node
266 notebook that is being exported.
267 resources : a dict of additional resources that
268 can be accessed read/write by preprocessors
269 """
270
271 # Do a copy.deepcopy first,
272 # we are never safe enough with what the preprocessors could do.
273 nbc = copy.deepcopy(nb)
274 resc = copy.deepcopy(resources)
275
276 #Run each preprocessor on the notebook. Carry the output along
277 #to each preprocessor
278 for preprocessor in self._preprocessors:
279 nbc, resc = preprocessor(nbc, resc)
280 return nbc, resc
@@ -1,57 +0,0 b''
1 """HTML Exporter class"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import os
7
8 from jupyter_nbconvert.filters.highlight import Highlight2HTML
9 from IPython.config import Config
10
11 from .templateexporter import TemplateExporter
12
13 #-----------------------------------------------------------------------------
14 # Classes
15 #-----------------------------------------------------------------------------
16
17 class HTMLExporter(TemplateExporter):
18 """
19 Exports a basic HTML document. This exporter assists with the export of
20 HTML. Inherit from it if you are writing your own HTML template and need
21 custom preprocessors/filters. If you don't need custom preprocessors/
22 filters, just change the 'template_file' config option.
23 """
24
25 def _file_extension_default(self):
26 return '.html'
27
28 def _default_template_path_default(self):
29 return os.path.join("..", "templates", "html")
30
31 def _template_file_default(self):
32 return 'full'
33
34 output_mimetype = 'text/html'
35
36 @property
37 def default_config(self):
38 c = Config({
39 'NbConvertBase': {
40 'display_data_priority' : ['application/javascript', 'text/html', 'text/markdown', 'application/pdf', 'image/svg+xml', 'text/latex', 'image/png', 'image/jpeg', 'text/plain']
41 },
42 'CSSHTMLHeaderPreprocessor':{
43 'enabled':True
44 },
45 'HighlightMagicsPreprocessor': {
46 'enabled':True
47 }
48 })
49 c.merge(super(HTMLExporter,self).default_config)
50 return c
51
52 def from_notebook_node(self, nb, resources=None, **kw):
53 langinfo = nb.metadata.get('language_info', {})
54 lexer = langinfo.get('pygments_lexer', langinfo.get('name', None))
55 self.register_filter('highlight_code',
56 Highlight2HTML(pygments_lexer=lexer, parent=self))
57 return super(HTMLExporter, self).from_notebook_node(nb, resources, **kw)
@@ -1,96 +0,0 b''
1 """LaTeX Exporter class"""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 # Stdlib imports
16 import os
17
18 # IPython imports
19 from IPython.utils.traitlets import Unicode
20 from IPython.config import Config
21
22 from jupyter_nbconvert.filters.highlight import Highlight2Latex
23 from .templateexporter import TemplateExporter
24
25 #-----------------------------------------------------------------------------
26 # Classes and functions
27 #-----------------------------------------------------------------------------
28
29 class LatexExporter(TemplateExporter):
30 """
31 Exports to a Latex template. Inherit from this class if your template is
32 LaTeX based and you need custom tranformers/filters. Inherit from it if
33 you are writing your own HTML template and need custom tranformers/filters.
34 If you don't need custom tranformers/filters, just change the
35 'template_file' config option. Place your template in the special "/latex"
36 subfolder of the "../templates" folder.
37 """
38
39 def _file_extension_default(self):
40 return '.tex'
41
42 def _template_file_default(self):
43 return 'article'
44
45 #Latex constants
46 def _default_template_path_default(self):
47 return os.path.join("..", "templates", "latex")
48
49 def _template_skeleton_path_default(self):
50 return os.path.join("..", "templates", "latex", "skeleton")
51
52 #Special Jinja2 syntax that will not conflict when exporting latex.
53 jinja_comment_block_start = Unicode("((=", config=True)
54 jinja_comment_block_end = Unicode("=))", config=True)
55 jinja_variable_block_start = Unicode("(((", config=True)
56 jinja_variable_block_end = Unicode(")))", config=True)
57 jinja_logic_block_start = Unicode("((*", config=True)
58 jinja_logic_block_end = Unicode("*))", config=True)
59
60 #Extension that the template files use.
61 template_extension = Unicode(".tplx", config=True)
62
63 output_mimetype = 'text/latex'
64
65
66 @property
67 def default_config(self):
68 c = Config({
69 'NbConvertBase': {
70 'display_data_priority' : ['text/latex', 'application/pdf', 'image/png', 'image/jpeg', 'image/svg+xml', 'text/plain']
71 },
72 'ExtractOutputPreprocessor': {
73 'enabled':True
74 },
75 'SVG2PDFPreprocessor': {
76 'enabled':True
77 },
78 'LatexPreprocessor': {
79 'enabled':True
80 },
81 'SphinxPreprocessor': {
82 'enabled':True
83 },
84 'HighlightMagicsPreprocessor': {
85 'enabled':True
86 }
87 })
88 c.merge(super(LatexExporter,self).default_config)
89 return c
90
91 def from_notebook_node(self, nb, resources=None, **kw):
92 langinfo = nb.metadata.get('language_info', {})
93 lexer = langinfo.get('pygments_lexer', langinfo.get('name', None))
94 self.register_filter('highlight_code',
95 Highlight2Latex(pygments_lexer=lexer, parent=self))
96 return super(LatexExporter, self).from_notebook_node(nb, resources, **kw)
@@ -1,43 +0,0 b''
1 """Markdown Exporter class"""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 from IPython.config import Config
16
17 from .templateexporter import TemplateExporter
18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
22
23 class MarkdownExporter(TemplateExporter):
24 """
25 Exports to a markdown document (.md)
26 """
27
28 def _file_extension_default(self):
29 return '.md'
30
31 def _template_file_default(self):
32 return 'markdown'
33
34 output_mimetype = 'text/markdown'
35
36 def _raw_mimetypes_default(self):
37 return ['text/markdown', 'text/html', '']
38
39 @property
40 def default_config(self):
41 c = Config({'ExtractOutputPreprocessor':{'enabled':True}})
42 c.merge(super(MarkdownExporter,self).default_config)
43 return c
@@ -1,32 +0,0 b''
1 """NotebookExporter class"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .exporter import Exporter
7 from IPython import nbformat
8 from IPython.utils.traitlets import Enum
9
10 class NotebookExporter(Exporter):
11 """Exports to an IPython notebook."""
12
13 nbformat_version = Enum(list(nbformat.versions),
14 default_value=nbformat.current_nbformat,
15 config=True,
16 help="""The nbformat version to write.
17 Use this to downgrade notebooks.
18 """
19 )
20 def _file_extension_default(self):
21 return '.ipynb'
22
23 output_mimetype = 'application/json'
24
25 def from_notebook_node(self, nb, resources=None, **kw):
26 nb_copy, resources = super(NotebookExporter, self).from_notebook_node(nb, resources, **kw)
27 if self.nbformat_version != nb_copy.nbformat:
28 resources['output_suffix'] = '.v%i' % self.nbformat_version
29 else:
30 resources['output_suffix'] = '.nbconvert'
31 output = nbformat.writes(nb_copy, version=self.nbformat_version)
32 return output, resources
@@ -1,149 +0,0 b''
1 """Export to PDF via latex"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import subprocess
7 import os
8 import sys
9
10 from IPython.utils.py3compat import which
11 from IPython.utils.traitlets import Integer, List, Bool, Instance
12 from IPython.utils.tempdir import TemporaryWorkingDirectory
13 from .latex import LatexExporter
14
15
16 class PDFExporter(LatexExporter):
17 """Writer designed to write to PDF files"""
18
19 latex_count = Integer(3, config=True,
20 help="How many times latex will be called."
21 )
22
23 latex_command = List([u"pdflatex", u"{filename}"], config=True,
24 help="Shell command used to compile latex."
25 )
26
27 bib_command = List([u"bibtex", u"{filename}"], config=True,
28 help="Shell command used to run bibtex."
29 )
30
31 verbose = Bool(False, config=True,
32 help="Whether to display the output of latex commands."
33 )
34
35 temp_file_exts = List(['.aux', '.bbl', '.blg', '.idx', '.log', '.out'], config=True,
36 help="File extensions of temp files to remove after running."
37 )
38
39 writer = Instance("jupyter_nbconvert.writers.FilesWriter", args=())
40
41 def run_command(self, command_list, filename, count, log_function):
42 """Run command_list count times.
43
44 Parameters
45 ----------
46 command_list : list
47 A list of args to provide to Popen. Each element of this
48 list will be interpolated with the filename to convert.
49 filename : unicode
50 The name of the file to convert.
51 count : int
52 How many times to run the command.
53
54 Returns
55 -------
56 success : bool
57 A boolean indicating if the command was successful (True)
58 or failed (False).
59 """
60 command = [c.format(filename=filename) for c in command_list]
61
62 # On windows with python 2.x there is a bug in subprocess.Popen and
63 # unicode commands are not supported
64 if sys.platform == 'win32' and sys.version_info < (3,0):
65 #We must use cp1252 encoding for calling subprocess.Popen
66 #Note that sys.stdin.encoding and encoding.DEFAULT_ENCODING
67 # could be different (cp437 in case of dos console)
68 command = [c.encode('cp1252') for c in command]
69
70 # This will throw a clearer error if the command is not found
71 cmd = which(command_list[0])
72 if cmd is None:
73 raise OSError("%s not found on PATH" % command_list[0])
74
75 times = 'time' if count == 1 else 'times'
76 self.log.info("Running %s %i %s: %s", command_list[0], count, times, command)
77 with open(os.devnull, 'rb') as null:
78 stdout = subprocess.PIPE if not self.verbose else None
79 for index in range(count):
80 p = subprocess.Popen(command, stdout=stdout, stdin=null)
81 out, err = p.communicate()
82 if p.returncode:
83 if self.verbose:
84 # verbose means I didn't capture stdout with PIPE,
85 # so it's already been displayed and `out` is None.
86 out = u''
87 else:
88 out = out.decode('utf-8', 'replace')
89 log_function(command, out)
90 return False # failure
91 return True # success
92
93 def run_latex(self, filename):
94 """Run pdflatex self.latex_count times."""
95
96 def log_error(command, out):
97 self.log.critical(u"%s failed: %s\n%s", command[0], command, out)
98
99 return self.run_command(self.latex_command, filename,
100 self.latex_count, log_error)
101
102 def run_bib(self, filename):
103 """Run bibtex self.latex_count times."""
104 filename = os.path.splitext(filename)[0]
105
106 def log_error(command, out):
107 self.log.warn('%s had problems, most likely because there were no citations',
108 command[0])
109 self.log.debug(u"%s output: %s\n%s", command[0], command, out)
110
111 return self.run_command(self.bib_command, filename, 1, log_error)
112
113 def clean_temp_files(self, filename):
114 """Remove temporary files created by pdflatex/bibtex."""
115 self.log.info("Removing temporary LaTeX files")
116 filename = os.path.splitext(filename)[0]
117 for ext in self.temp_file_exts:
118 try:
119 os.remove(filename+ext)
120 except OSError:
121 pass
122
123 def from_notebook_node(self, nb, resources=None, **kw):
124 latex, resources = super(PDFExporter, self).from_notebook_node(
125 nb, resources=resources, **kw
126 )
127 with TemporaryWorkingDirectory() as td:
128 notebook_name = "notebook"
129 tex_file = self.writer.write(latex, resources, notebook_name=notebook_name)
130 self.log.info("Building PDF")
131 rc = self.run_latex(tex_file)
132 if not rc:
133 rc = self.run_bib(tex_file)
134 if not rc:
135 rc = self.run_latex(tex_file)
136
137 pdf_file = notebook_name + '.pdf'
138 if not os.path.isfile(pdf_file):
139 raise RuntimeError("PDF creating failed")
140 self.log.info('PDF successfully created')
141 with open(pdf_file, 'rb') as f:
142 pdf_data = f.read()
143
144 # convert output extension to pdf
145 # the writer above required it to be tex
146 resources['output_extension'] = '.pdf'
147
148 return pdf_data, resources
149
@@ -1,31 +0,0 b''
1 """Python script Exporter class"""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 from .templateexporter import TemplateExporter
16
17 #-----------------------------------------------------------------------------
18 # Classes
19 #-----------------------------------------------------------------------------
20
21 class PythonExporter(TemplateExporter):
22 """
23 Exports a Python code file.
24 """
25 def _file_extension_default(self):
26 return '.py'
27
28 def _template_file_default(self):
29 return 'python'
30
31 output_mimetype = 'text/x-python'
@@ -1,40 +0,0 b''
1 """restructuredText Exporter class"""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 from IPython.config import Config
16
17 from .templateexporter import TemplateExporter
18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
22
23 class RSTExporter(TemplateExporter):
24 """
25 Exports restructured text documents.
26 """
27
28 def _file_extension_default(self):
29 return '.rst'
30
31 def _template_file_default(self):
32 return 'rst'
33
34 output_mimetype = 'text/restructuredtext'
35
36 @property
37 def default_config(self):
38 c = Config({'ExtractOutputPreprocessor':{'enabled':True}})
39 c.merge(super(RSTExporter,self).default_config)
40 return c
@@ -1,33 +0,0 b''
1 """Generic script exporter class for any kernel language"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .templateexporter import TemplateExporter
7
8 from IPython.utils.traitlets import Dict
9
10 class ScriptExporter(TemplateExporter):
11
12 _exporters = Dict()
13
14 def _template_file_default(self):
15 return 'script'
16
17 def from_notebook_node(self, nb, resources=None, **kw):
18 langinfo = nb.metadata.get('language_info', {})
19
20 # delegate to custom exporter, if specified
21 exporter_name = langinfo.get('nbconvert_exporter')
22 if exporter_name and exporter_name != 'script':
23 self.log.debug("Loading script exporter: %s", exporter_name)
24 from .export import exporter_map
25 if exporter_name not in self._exporters:
26 Exporter = exporter_map[exporter_name]
27 self._exporters[exporter_name] = Exporter(parent=self)
28 exporter = self._exporters[exporter_name]
29 return exporter.from_notebook_node(nb, resources, **kw)
30
31 self.file_extension = langinfo.get('file_extension', '.txt')
32 self.output_mimetype = langinfo.get('mimetype', 'text/plain')
33 return super(ScriptExporter, self).from_notebook_node(nb, resources, **kw)
@@ -1,43 +0,0 b''
1 """HTML slide show Exporter class"""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 from jupyter_nbconvert import preprocessors
16 from IPython.config import Config
17
18 from .html import HTMLExporter
19
20 #-----------------------------------------------------------------------------
21 # Classes
22 #-----------------------------------------------------------------------------
23
24 class SlidesExporter(HTMLExporter):
25 """Exports HTML slides with reveal.js"""
26
27 def _file_extension_default(self):
28 return '.slides.html'
29
30 def _template_file_default(self):
31 return 'slides_reveal'
32
33 output_mimetype = 'text/html'
34
35 @property
36 def default_config(self):
37 c = Config({
38 'RevealHelpPreprocessor': {
39 'enabled': True,
40 },
41 })
42 c.merge(super(SlidesExporter,self).default_config)
43 return c
@@ -1,321 +0,0 b''
1 """This module defines TemplateExporter, a highly configurable converter
2 that uses Jinja2 to export notebook files into different formats.
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from __future__ import print_function, absolute_import
18
19 # Stdlib imports
20 import os
21
22 # other libs/dependencies are imported at runtime
23 # to move ImportErrors to runtime when the requirement is actually needed
24
25 # IPython imports
26 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, Dict, Any
27 from IPython.utils.importstring import import_item
28 from IPython.utils import py3compat, text
29
30 from jupyter_nbconvert import filters
31 from .exporter import Exporter
32
33 #-----------------------------------------------------------------------------
34 # Globals and constants
35 #-----------------------------------------------------------------------------
36
37 #Jinja2 extensions to load.
38 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
39
40 default_filters = {
41 'indent': text.indent,
42 'markdown2html': filters.markdown2html,
43 'ansi2html': filters.ansi2html,
44 'filter_data_type': filters.DataTypeFilter,
45 'get_lines': filters.get_lines,
46 'highlight2html': filters.Highlight2HTML,
47 'highlight2latex': filters.Highlight2Latex,
48 'ipython2python': filters.ipython2python,
49 'posix_path': filters.posix_path,
50 'markdown2latex': filters.markdown2latex,
51 'markdown2rst': filters.markdown2rst,
52 'comment_lines': filters.comment_lines,
53 'strip_ansi': filters.strip_ansi,
54 'strip_dollars': filters.strip_dollars,
55 'strip_files_prefix': filters.strip_files_prefix,
56 'html2text' : filters.html2text,
57 'add_anchor': filters.add_anchor,
58 'ansi2latex': filters.ansi2latex,
59 'wrap_text': filters.wrap_text,
60 'escape_latex': filters.escape_latex,
61 'citation2latex': filters.citation2latex,
62 'path2url': filters.path2url,
63 'add_prompts': filters.add_prompts,
64 'ascii_only': filters.ascii_only,
65 'prevent_list_blocks': filters.prevent_list_blocks,
66 }
67
68 #-----------------------------------------------------------------------------
69 # Class
70 #-----------------------------------------------------------------------------
71
72 class TemplateExporter(Exporter):
73 """
74 Exports notebooks into other file formats. Uses Jinja 2 templating engine
75 to output new formats. Inherit from this class if you are creating a new
76 template type along with new filters/preprocessors. If the filters/
77 preprocessors provided by default suffice, there is no need to inherit from
78 this class. Instead, override the template_file and file_extension
79 traits via a config file.
80
81 {filters}
82 """
83
84 # finish the docstring
85 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
86
87
88 template_file = Unicode(u'default',
89 config=True,
90 help="Name of the template file to use")
91 def _template_file_changed(self, name, old, new):
92 if new == 'default':
93 self.template_file = self.default_template
94 else:
95 self.template_file = new
96 self.template = None
97 self._load_template()
98
99 default_template = Unicode(u'')
100 template = Any()
101 environment = Any()
102
103 template_path = List(['.'], config=True)
104 def _template_path_changed(self, name, old, new):
105 self._load_template()
106
107 default_template_path = Unicode(
108 os.path.join("..", "templates"),
109 help="Path where the template files are located.")
110
111 template_skeleton_path = Unicode(
112 os.path.join("..", "templates", "skeleton"),
113 help="Path where the template skeleton files are located.")
114
115 #Jinja block definitions
116 jinja_comment_block_start = Unicode("", config=True)
117 jinja_comment_block_end = Unicode("", config=True)
118 jinja_variable_block_start = Unicode("", config=True)
119 jinja_variable_block_end = Unicode("", config=True)
120 jinja_logic_block_start = Unicode("", config=True)
121 jinja_logic_block_end = Unicode("", config=True)
122
123 #Extension that the template files use.
124 template_extension = Unicode(".tpl", config=True)
125
126 filters = Dict(config=True,
127 help="""Dictionary of filters, by name and namespace, to add to the Jinja
128 environment.""")
129
130 raw_mimetypes = List(config=True,
131 help="""formats of raw cells to be included in this Exporter's output."""
132 )
133 def _raw_mimetypes_default(self):
134 return [self.output_mimetype, '']
135
136
137 def __init__(self, config=None, extra_loaders=None, **kw):
138 """
139 Public constructor
140
141 Parameters
142 ----------
143 config : config
144 User configuration instance.
145 extra_loaders : list[of Jinja Loaders]
146 ordered list of Jinja loader to find templates. Will be tried in order
147 before the default FileSystem ones.
148 template : str (optional, kw arg)
149 Template to use when exporting.
150 """
151 super(TemplateExporter, self).__init__(config=config, **kw)
152
153 #Init
154 self._init_template()
155 self._init_environment(extra_loaders=extra_loaders)
156 self._init_filters()
157
158
159 def _load_template(self):
160 """Load the Jinja template object from the template file
161
162 This is a no-op if the template attribute is already defined,
163 or the Jinja environment is not setup yet.
164
165 This is triggered by various trait changes that would change the template.
166 """
167 from jinja2 import TemplateNotFound
168
169 if self.template is not None:
170 return
171 # called too early, do nothing
172 if self.environment is None:
173 return
174 # Try different template names during conversion. First try to load the
175 # template by name with extension added, then try loading the template
176 # as if the name is explicitly specified, then try the name as a
177 # 'flavor', and lastly just try to load the template by module name.
178 try_names = []
179 if self.template_file:
180 try_names.extend([
181 self.template_file + self.template_extension,
182 self.template_file,
183 ])
184 for try_name in try_names:
185 self.log.debug("Attempting to load template %s", try_name)
186 try:
187 self.template = self.environment.get_template(try_name)
188 except (TemplateNotFound, IOError):
189 pass
190 except Exception as e:
191 self.log.warn("Unexpected exception loading template: %s", try_name, exc_info=True)
192 else:
193 self.log.debug("Loaded template %s", try_name)
194 break
195
196 def from_notebook_node(self, nb, resources=None, **kw):
197 """
198 Convert a notebook from a notebook node instance.
199
200 Parameters
201 ----------
202 nb : :class:`~IPython.nbformat.NotebookNode`
203 Notebook node
204 resources : dict
205 Additional resources that can be accessed read/write by
206 preprocessors and filters.
207 """
208 nb_copy, resources = super(TemplateExporter, self).from_notebook_node(nb, resources, **kw)
209 resources.setdefault('raw_mimetypes', self.raw_mimetypes)
210
211 self._load_template()
212
213 if self.template is not None:
214 output = self.template.render(nb=nb_copy, resources=resources)
215 else:
216 raise IOError('template file "%s" could not be found' % self.template_file)
217 return output, resources
218
219
220 def register_filter(self, name, jinja_filter):
221 """
222 Register a filter.
223 A filter is a function that accepts and acts on one string.
224 The filters are accesible within the Jinja templating engine.
225
226 Parameters
227 ----------
228 name : str
229 name to give the filter in the Jinja engine
230 filter : filter
231 """
232 if jinja_filter is None:
233 raise TypeError('filter')
234 isclass = isinstance(jinja_filter, type)
235 constructed = not isclass
236
237 #Handle filter's registration based on it's type
238 if constructed and isinstance(jinja_filter, py3compat.string_types):
239 #filter is a string, import the namespace and recursively call
240 #this register_filter method
241 filter_cls = import_item(jinja_filter)
242 return self.register_filter(name, filter_cls)
243
244 if constructed and hasattr(jinja_filter, '__call__'):
245 #filter is a function, no need to construct it.
246 self.environment.filters[name] = jinja_filter
247 return jinja_filter
248
249 elif isclass and isinstance(jinja_filter, MetaHasTraits):
250 #filter is configurable. Make sure to pass in new default for
251 #the enabled flag if one was specified.
252 filter_instance = jinja_filter(parent=self)
253 self.register_filter(name, filter_instance )
254
255 elif isclass:
256 #filter is not configurable, construct it
257 filter_instance = jinja_filter()
258 self.register_filter(name, filter_instance)
259
260 else:
261 #filter is an instance of something without a __call__
262 #attribute.
263 raise TypeError('filter')
264
265
266 def _init_template(self):
267 """
268 Make sure a template name is specified. If one isn't specified, try to
269 build one from the information we know.
270 """
271 self._template_file_changed('template_file', self.template_file, self.template_file)
272
273
274 def _init_environment(self, extra_loaders=None):
275 """
276 Create the Jinja templating environment.
277 """
278 from jinja2 import Environment, ChoiceLoader, FileSystemLoader
279 here = os.path.dirname(os.path.realpath(__file__))
280 loaders = []
281 if extra_loaders:
282 loaders.extend(extra_loaders)
283
284 paths = self.template_path
285 paths.extend([os.path.join(here, self.default_template_path),
286 os.path.join(here, self.template_skeleton_path)])
287 loaders.append(FileSystemLoader(paths))
288
289 self.environment = Environment(
290 loader= ChoiceLoader(loaders),
291 extensions=JINJA_EXTENSIONS
292 )
293
294 #Set special Jinja2 syntax that will not conflict with latex.
295 if self.jinja_logic_block_start:
296 self.environment.block_start_string = self.jinja_logic_block_start
297 if self.jinja_logic_block_end:
298 self.environment.block_end_string = self.jinja_logic_block_end
299 if self.jinja_variable_block_start:
300 self.environment.variable_start_string = self.jinja_variable_block_start
301 if self.jinja_variable_block_end:
302 self.environment.variable_end_string = self.jinja_variable_block_end
303 if self.jinja_comment_block_start:
304 self.environment.comment_start_string = self.jinja_comment_block_start
305 if self.jinja_comment_block_end:
306 self.environment.comment_end_string = self.jinja_comment_block_end
307
308
309 def _init_filters(self):
310 """
311 Register all of the filters required for the exporter.
312 """
313
314 #Add default filters to the Jinja2 environment
315 for key, value in default_filters.items():
316 self.register_filter(key, value)
317
318 #Load user filters. Overwrite existing filters if need be.
319 if self.filters:
320 for key, user_filter in self.filters.items():
321 self.register_filter(key, user_filter)
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,38 +0,0 b''
1 """Base TestCase class for testing Exporters"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import os
7
8 from ...tests.base import TestsBase
9
10 all_raw_mimetypes = {
11 'text/x-python',
12 'text/markdown',
13 'text/html',
14 'text/restructuredtext',
15 'text/latex',
16 }
17
18 class ExportersTestsBase(TestsBase):
19 """Contains base test functions for exporters"""
20
21 exporter_class = None
22 should_include_raw = None
23
24 def _get_notebook(self, nb_name='notebook2.ipynb'):
25 return os.path.join(self._get_files_path(), nb_name)
26
27 def test_raw_cell_inclusion(self):
28 """test raw cell inclusion based on raw_mimetype metadata"""
29 if self.should_include_raw is None:
30 return
31 exporter = self.exporter_class()
32 (output, resources) = exporter.from_filename(self._get_notebook('rawtest.ipynb'))
33 for inc in self.should_include_raw:
34 self.assertIn('raw %s' % inc, output, "should include %s" % inc)
35 self.assertIn('no raw_mimetype metadata', output)
36 for exc in all_raw_mimetypes.difference(self.should_include_raw):
37 self.assertNotIn('raw %s' % exc, output, "should exclude %s" % exc)
38 self.assertNotIn('never be included', output)
@@ -1,48 +0,0 b''
1 """
2 Contains CheesePreprocessor
3 """
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
6 #
7 # Distributed under the terms of the Modified BSD License.
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 from ...preprocessors.base import Preprocessor
17
18 #-----------------------------------------------------------------------------
19 # Classes
20 #-----------------------------------------------------------------------------
21
22 class CheesePreprocessor(Preprocessor):
23 """
24 Adds a cheese tag to the resources object
25 """
26
27
28 def __init__(self, **kw):
29 """
30 Public constructor
31 """
32 super(CheesePreprocessor, self).__init__(**kw)
33
34
35 def preprocess(self, nb, resources):
36 """
37 Sphinx preprocessing to apply on each notebook.
38
39 Parameters
40 ----------
41 nb : NotebookNode
42 Notebook being converted
43 resources : dictionary
44 Additional resources used in the conversion process. Allows
45 preprocessors to pass variables into the Jinja engine.
46 """
47 resources['cheese'] = 'real'
48 return nb, resources
@@ -1,178 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# NumPy and Matplotlib examples"
8 ]
9 },
10 {
11 "cell_type": "markdown",
12 "metadata": {},
13 "source": [
14 "First import NumPy and Matplotlib:"
15 ]
16 },
17 {
18 "cell_type": "code",
19 "execution_count": 1,
20 "metadata": {
21 "collapsed": false
22 },
23 "outputs": [
24 {
25 "name": "stdout",
26 "output_type": "stream",
27 "text": [
28 "\n",
29 "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.kernel.zmq.pylab.backend_inline].\n",
30 "For more information, type 'help(pylab)'.\n"
31 ]
32 }
33 ],
34 "source": [
35 "%pylab inline"
36 ]
37 },
38 {
39 "cell_type": "code",
40 "execution_count": 2,
41 "metadata": {
42 "collapsed": false
43 },
44 "outputs": [],
45 "source": [
46 "import numpy as np"
47 ]
48 },
49 {
50 "cell_type": "markdown",
51 "metadata": {},
52 "source": [
53 "Now we show some very basic examples of how they can be used."
54 ]
55 },
56 {
57 "cell_type": "code",
58 "execution_count": 6,
59 "metadata": {
60 "collapsed": false
61 },
62 "outputs": [],
63 "source": [
64 "a = np.random.uniform(size=(100,100))"
65 ]
66 },
67 {
68 "cell_type": "code",
69 "execution_count": 7,
70 "metadata": {
71 "collapsed": false
72 },
73 "outputs": [
74 {
75 "data": {
76 "text/plain": [
77 "(100, 100)"
78 ]
79 },
80 "execution_count": 7,
81 "metadata": {},
82 "output_type": "execute_result"
83 }
84 ],
85 "source": [
86 "a.shape"
87 ]
88 },
89 {
90 "cell_type": "code",
91 "execution_count": 8,
92 "metadata": {
93 "collapsed": false
94 },
95 "outputs": [],
96 "source": [
97 "evs = np.linalg.eigvals(a)"
98 ]
99 },
100 {
101 "cell_type": "code",
102 "execution_count": 10,
103 "metadata": {
104 "collapsed": false
105 },
106 "outputs": [
107 {
108 "data": {
109 "text/plain": [
110 "(100,)"
111 ]
112 },
113 "execution_count": 10,
114 "metadata": {},
115 "output_type": "execute_result"
116 }
117 ],
118 "source": [
119 "evs.shape"
120 ]
121 },
122 {
123 "cell_type": "markdown",
124 "metadata": {},
125 "source": [
126 "Here is a cell that has both text and PNG output:"
127 ]
128 },
129 {
130 "cell_type": "code",
131 "execution_count": 14,
132 "metadata": {
133 "collapsed": false
134 },
135 "outputs": [
136 {
137 "data": {
138 "text/plain": [
139 "(array([95, 4, 0, 0, 0, 0, 0, 0, 0, 1]),\n",
140 " array([ -2.93566063, 2.35937011, 7.65440086, 12.9494316 ,\n",
141 " 18.24446235, 23.53949309, 28.83452384, 34.12955458,\n",
142 " 39.42458533, 44.71961607, 50.01464682]),\n",
143 " <a list of 10 Patch objects>)"
144 ]
145 },
146 "execution_count": 14,
147 "metadata": {},
148 "output_type": "execute_result"
149 },
150 {
151 "data": {
152 "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXgAAAD9CAYAAAC2l2x5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEhdJREFUeJzt3X1olfX/x/HXtVbT8CZDmsK6KmrubEu3U2xnZOpxLBnG\nOqsIE7RoE3QRZkT/yEAjcIh/LIs6i/BEGSU1CkxT0+pkFp1zMmsxZ5uUTIXoxm95lmdlef3+8Nep\ndbtz7exs16fnAw7sXNs5n/c14nmurl3naDmO4wgAYJy8sR4AADA6CDwAGIrAA4ChCDwAGIrAA4Ch\nCDwAGOofA9/U1KTCwkLNnj07vS2ZTCoUCsm2bTU2NmpgYCD9vccee0zFxcUqKyvTgQMHRm9qAMC/\n+sfA33PPPdq9e/eQbeFwWLZtq6+vT0VFRero6JAkffXVV3ryySf15ptvKhwOa/Xq1aM3NQDgX/1j\n4OfNm6dp06YN2RaPx9Xc3KyCggI1NTUpFotJkmKxmOrr62XbthYsWCDHcZRMJkdvcgDAP8r4HHwi\nkZDP55Mk+Xw+xeNxSecDX1pamv65kpKS9PcAALmXn+kDMvlkA8uyhrUNAPDvMv1kmYyP4KuqqtTT\n0yNJ6unpUVVVlSQpEAjo8OHD6Z87cuRI+nt/NaRXb+vWrRvzGZh/7Odgfu/dvDy747j7yLCMAx8I\nBBSJRJRKpRSJRFRTUyNJqq6u1p49e9Tf369oNKq8vDxNnjzZ1VAAgJH7x8AvXbpUN9xwg3p7e3X5\n5ZfrmWeeUUtLi/r7+1VSUqKTJ09q1apVkqTCwkK1tLSotrZW9957rzZv3pyTHQAA/DXLcXvs73ZB\ny3L9vxvjQTQaVTAYHOsxXGP+scX8Y8fLs0vu2kngAcAD3LSTjyoAAEMReAAwFIEHAEMReAAwFIEH\nAEP9ZwM/Zcqlsixr1G9Tplw61rsK4D/qP3uZ5PnPxMnFHONjfwF4G5dJAgDSCDwAGIrAA4ChCDwA\nGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrA\nA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChXAf+6aef1g03\n3KDrr79ea9askSQlk0mFQiHZtq3GxkYNDAxkbVAAQGZcBf7UqVPasGGD9u7dq0Qiod7eXu3Zs0fh\ncFi2bauvr09FRUXq6OjI9rwAgGFyFfiJEyfKcRx9//33SqVSOnPmjC655BLF43E1NzeroKBATU1N\nisVi2Z4XADBMrgMfDod15ZVXasaMGZo7d64CgYASiYR8Pp8kyefzKR6PZ3VYAMDw5bt50Ndff62W\nlhYdPnxY06ZN0x133KEdO3bIcZxhPX79+vXpr4PBoILBoJsxAMBY0WhU0Wh0RM9hOcOt8u/s3LlT\nW7du1bZt2yRJ4XBYx44d09GjR9Xa2iq/36+DBw+qra1NnZ2dQxe0rGG/EIwmy7Ik5WKO8bG/ALzN\nTTtdnaKZN2+ePvzwQ506dUo//vijdu3apUWLFikQCCgSiSiVSikSiaimpsbN0wMAssBV4KdMmaLW\n1lbdeuutuvHGG1VRUaGFCxeqpaVF/f39Kikp0cmTJ7Vq1apszwsAGCZXp2hGtCCnaAAgYzk7RQMA\nGP8IPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEI\nPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAY\nisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYisADgKEIPAAYynXgf/jhB919992a\nNWuWysrKFIvFlEwmFQqFZNu2GhsbNTAwkM1ZAQAZcB34devWybZtdXV1qaurSz6fT+FwWLZtq6+v\nT0VFRero6MjmrACADLgO/L59+7R27VpNmDBB+fn5mjp1quLxuJqbm1VQUKCmpibFYrFszgoAyICr\nwJ84cUKDg4NqaWlRIBDQxo0blUqllEgk5PP5JEk+n0/xeDyrwwIAhi/fzYMGBwfV29urTZs2qa6u\nTitXrtRLL70kx3GG9fj169envw4GgwoGg27GAABjRaNRRaPRET2H5Qy3yn9QWlqqnp4eSdKuXbv0\n3HPP6aefflJra6v8fr8OHjyotrY2dXZ2Dl3Qsob9QjCaLMuSlIs5xsf+AvA2N+10fQ6+uLhYsVhM\n586d086dO1VXV6dAIKBIJKJUKqVIJKKamhq3Tw8AGCHXR/C9vb266667NDg4qLq6Oj388MM6d+6c\nli1bpkOHDum6667T888/r0mTJg1dkCN4AMiYm3a6DrxbBB4AMpfTUzQAgPGNwAOAoQg8ABiKwAOA\noQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8\nABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiK\nwAOAoQg8ABiKwAOAoQg8ABiKwAOAoQg8ABiKwAOAoVwH/pdffpHf71dDQ4MkKZlMKhQKybZtNTY2\namBgIGtDAgAy5zrwmzdvVllZmSzLkiSFw2HZtq2+vj4VFRWpo6Mja0MCADLnKvAnTpzQ66+/rhUr\nVshxHElSPB5Xc3OzCgoK1NTUpFgsltVBAQCZcRX4Bx54QJs2bVJe3m8PTyQS8vl8kiSfz6d4PJ6d\nCQEAruRn+oAdO3bosssuk9/vVzQaTW//9Uh+ONavX5/+OhgMKhgMZjoGABgtGo0OaawblpNJmSWt\nXbtWW7duVX5+vgYHB3X69GnddtttOnPmjFpbW+X3+3Xw4EG1tbWps7PzzwtaVkYvBqPl/N8OcjHH\n+NhfAN7mpp0Zn6LZsGGDjh8/ri+++ELbtm1TbW2ttm7dqkAgoEgkolQqpUgkopqamkyfGgCQRSO+\nDv7Xq2haWlrU39+vkpISnTx5UqtWrRrxcAAA9zI+RTPiBTlFAwAZy8kpGgCANxB4ADAUgQcAQxF4\nADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAU\ngQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcA\nQxF4ADAUgQcAQxF4ADAUgQcAQxF4ADAUgQcAQ7kK/PHjx7Vw4UKVl5crGAzqhRdekCQlk0mFQiHZ\ntq3GxkYNDAxkdVgAwPC5CvyFF16o9vZ2dXd3q7OzU62trUomkwqHw7JtW319fSoqKlJHR0e25wUA\nDJOrwM+YMUOVlZWSpOnTp6u8vFyJRELxeFzNzc0qKChQU1OTYrFYVocFAAzfiM/BHz16VN3d3aqu\nrlYikZDP55Mk+Xw+xePxEQ8IAHAnfyQPTiaTWrJkidrb2zVp0iQ5jjOsx61fvz79dTAYVDAYHMkY\nAGCcaDSqaDQ6ouewnOFW+Q/Onj2rm2++WYsXL9aaNWskSbfffrtaW1vl9/t18OBBtbW1qbOzc+iC\nljXsF4LRZFmWpFzMMT72F4C3uWmnq1M0juOoublZ1157bTrukhQIBBSJRJRKpRSJRFRTU+Pm6QEA\nWeDqCP7AgQOaP3++5syZ8/9HwlJbW5vmzp2rZcuW6dChQ7ruuuv0/PPPa9KkSUMX5AgeADLmpp2u\nT9G4ReABIHM5O0UDABj/CDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrA\nA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4Ch\nCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4ChCDwAGIrAA4Ch8sd6APPly7KsUV1h8uRpOn361Kiu\nAcB7LMdxnJwuaFnK8ZJ/O4eUizlysc74+J0CGD1u2skpGgAwFIEHAEMReAAwVNYDv3//fpWWlqq4\nuFiPP/54tp9+HIiO9QAjEo1Gx3qEEWH+seXl+b08u1tZD/z999+vp556Svv27dMTTzyhb775JttL\njLHoWA8wIl7/j5z5x5aX5/fy7G5lNfDff/+9JGn+/Pm64oortGjRIsVisWwuAcBAU6ZcKsuyRvXW\n1rZxrHcz57Ia+EQiIZ/Pl75fVlamDz74IJtLADBQMvk/nb+cePRuP/00mLsdGieyeh38vn37tGXL\nFr344ouSpI6ODp08eVKPPPLIbwuO8pt+AMBUmeY6q+9kraqq0kMPPZS+393drfr6+iE/wxtyACA3\nsnqKZurUqZLOX0lz7Ngx7d27V4FAIJtLAACGKeufRfPoo49q5cqVOnv2rFavXq3p06dnewkAwDBk\n/TLJBQsWqKenR0ePHtXq1aslSS+//LLKy8t1wQUX6KOPPhry84899piKi4tVVlamAwcOZHucrPHa\n9f1NTU0qLCzU7Nmz09uSyaRCoZBs21ZjY6MGBgbGcMJ/dvz4cS1cuFDl5eUKBoN64YUXJHlnHwYH\nBxUIBFRZWamamhq1t7dL8s78kvTLL7/I7/eroaFBkrdmv/LKKzVnzhz5/X5VV1dL8tb8P/zwg+6+\n+27NmjVLZWVlisVirubPyTtZZ8+erVdffVXz588fsv2rr77Sk08+qTfffFPhcDj9gjAeee36/nvu\nuUe7d+8esi0cDsu2bfX19amoqEgdHR1jNN2/u/DCC9Xe3q7u7m51dnaqtbVVyWTSM/swYcIEvf32\n2/r444/1zjvvaMuWLerr6/PM/JK0efNmlZWVpS+M8NLslmUpGo3q0KFDisfjkrw1/7p162Tbtrq6\nutTV1SWfz+dq/pwE3ufzadasWX/aHovFVF9fL9u2tWDBAjmOo2QymYuRMuLF6/vnzZunadOmDdkW\nj8fV3NysgoICNTU1jet9mDFjhiorKyVJ06dPV3l5uRKJhKf24eKLL5YkDQwM6Oeff1ZBQYFn5j9x\n4oRef/11rVixIn1hhFdm/9UfL+jw0vz79u3T2rVrNWHCBOXn52vq1Kmu5h/Tz6KJx+MqLS1N3y8p\nKUm/2o4nplzf//v98Pl84/J3/VeOHj2q7u5uVVdXe2ofzp07p4qKChUWFuq+++6Tbduemf+BBx7Q\npk2blJf3WyK8Mrt0/gi+trZWjY2N2r59uyTvzH/ixAkNDg6qpaVFgUBAGzduVCqVcjV/1v7IetNN\nN+nLL7/80/YNGzakz+H90V9dMsl18qPHi5eoJpNJLVmyRO3t7Zo0aZKn9iEvL0+ffPKJjh07psWL\nF2vu3LmemH/Hjh267LLL5Pf7h7y93wuz/+q9997TzJkz1dPTo4aGBlVXV3tm/sHBQfX29mrTpk2q\nq6vTypUr9dJLL7maP2tH8Hv37tWnn376p9vfxV2SAoGADh8+nL5/5MgRVVVVZWukrKmqqtKRI0fS\n97u7u1VTUzOGE7lTVVWlnp4eSVJPT8+4/F3/3tmzZ3X77bdr+fLlCoVCkry3D9L5P/gtXrxYsVjM\nE/O///772r59u6666iotXbpUb731lpYvX+6J2X81c+ZMSVJpaaluueUWvfbaa56Z/5prrlFJSYka\nGho0ceJELV26VLt373Y1f85P0fz+Vai6ulp79uxRf3+/otGo8vLyNHny5FyP9K9Mub4/EAgoEoko\nlUopEomM6xcpx3HU3Nysa6+9VmvWrElv98o+fPPNN/ruu+8kSd9++63eeOMNhUIhT8y/YcMGHT9+\nXF988YW2bdum2tpabd261ROzS9KZM2fSf8v7+uuvtWfPHtXX13tmfkkqLi5WLBbTuXPntHPnTtXV\n1bmb38mBV155xSkqKnImTJjgFBYWOvX19envPfroo87VV1/tlJaWOvv378/FOK5Eo1HH5/M5V199\ntbN58+axHudf3Xnnnc7MmTOdiy66yCkqKnIikYhz+vRp55ZbbnEuv/xyJxQKOclkcqzH/Fvvvvuu\nY1mWU1FR4VRWVjqVlZXOrl27PLMPXV1djt/vd+bMmeMsWrTIefbZZx3HcTwz/6+i0ajT0NDgOI53\nZv/888+diooKp6KiwqmtrXW2bNniOI535nccx/nss8+cQCDgVFRUOA8++KAzMDDgav6c/5usAIDc\n4F90AgBDEXgAMBSBBwBDEXgAMBSBBwBDEXgAMNT/AQKseNIf7mhWAAAAAElFTkSuQmCC\n",
153 "text/plain": [
154 "<matplotlib.figure.Figure at 0x108c8f1d0>"
155 ]
156 },
157 "metadata": {},
158 "output_type": "display_data"
159 }
160 ],
161 "source": [
162 "hist(evs.real)"
163 ]
164 },
165 {
166 "cell_type": "code",
167 "execution_count": null,
168 "metadata": {
169 "collapsed": false
170 },
171 "outputs": [],
172 "source": []
173 }
174 ],
175 "metadata": {},
176 "nbformat": 4,
177 "nbformat_minor": 0
178 }
@@ -1,240 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [
10 {
11 "data": {
12 "text/plain": [
13 "[<matplotlib.lines.Line2D at 0x10f695240>]"
14 ]
15 },
16 "execution_count": 1,
17 "metadata": {},
18 "output_type": "execute_result"
19 },
20 {
21 "data": {
22 "image/png": [
23 "iVBORw0KGgoAAAANSUhEUgAAAu0AAAH/CAYAAADjSONqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
24 "AAAWJQAAFiUBSVIk8AAAIABJREFUeJzt3X/M7ndd3/HXezmJG7QpEdqyrbD21OYgLMbNmRK6aM+w\n",
25 "DKMhwDS4RNnmkM0xLIqMyTY5JSEwNy2jiJOxOu1MiEQLW8xoQTBDKttcIJlz/YE9BaFWZdACtoVp\n",
26 "3/vjum56zn3u69w/rl/f73U9HsmVb3t9r/tzf+/e33Puz/3s5/p+q7sDAAAM159Z9wEAAADnZ9IO\n",
27 "AAADZ9IOAAADZ9IOAAADZ9IOAAADZ9IOAAADZ9IOAAADZ9IOAAADZ9IOAAADZ9IOAAADZ9IOAAAD\n",
28 "Z9IOAAADZ9IOAAADZ9IOAAADN9ekvaq+q6puqqoPV9UXquqxqrrliGNdVlU3V9X9VfVoVZ2uqhur\n",
29 "6knzHCMAAIzdsTk//p8n+YYkX0zy6STPSNKHHaSqrkxyR5KLk7wnyZ1Jrk5yfZLnV9U13f25OY8V\n",
30 "AABGad7lMa9KclV3X5TkB+cY5+2ZTNhf2d0v7u7Xdfdzk9yY5ESSN855nAAAMFrVfegwvvdAVdcm\n",
31 "+WCS/9jdLz3Ex12Z5J4kp7v7yl37LkjyQCb1/tLufnghBwsAACMyhDeinpxub9+9o7u/lOQjSZ6Y\n",
32 "5NmrPCgAABiKIUzaT0y3d8/Yf890e9UKjgUAAAZnCJP2i6bbh2bs33neVWQAANhK8149ZlCqajEL\n",
33 "9AEAYB/dXav6XEMo7Tsl/aIZ+3eef3AFxwIAAIMzhNJ+53R7Ysb+nbXss9a876GTybXjX53knd2H\n",
34 "v3Y8m6WqepW/DTN8zgn24rxgL84LdlvH6o4hlPYPTbfXVdVZfyCq6sIk1yT54yQfPcSYtya5MMk7\n",
35 "ktxWlacv4kABAGAdVjZpr6pjVfWMqjp+5vPdfW8ml3u8Iskrdn3YDUmekOSW7n7kEJ/ubyX520n+\n",
36 "b5Lrkvx2VX6gKn5LBgBgdOa6uVJVvTDJC6f/+tQkz0tyb5LfmD73R939mulrL5/u+2R3X7FrnONJ\n",
37 "7khySZL3ZrJk5uok1ya5K8lzuvvzBzieTh5/U0BVLk3yM0leNH3J+5O8rDufOvQXy6j5X5vs5pxg\n",
38 "L84L9uK8YLfdc86VfM45J+2vT/L65Jw14ztfwH3dfXz62sszmbR/9bldY12W5A1Jnp/kyUnuz2SZ\n",
39 "yw3dPetykLvHOOc/4LSuvyTJ26bjWuu+hfyFy27OCfbivGAvzgt2G92kfWjO9x9Qdd9u/sJlN+cE\n",
40 "e3FesBfnBbutY9I+hDeirkR3/iDWugMAMEJbM2lPku50d96V5FlxhZltc8O6D4DBcU6wF+cFe3Fe\n",
41 "sHZbszzm3Nda6w4AwOFZ0z6no/wHtNYdAIDDsKZ9Dax1BwBg6La+tJ/98ao7AADnp7SvmeoOAMAQ\n",
42 "Ke0zx1LdAQA4l9I+IKo7AABDobQfaFzVHQCACaV9oFR3AADWSWk/9OdQ3QEAtpnSPgKqOwAAq6a0\n",
43 "z/X5VHcAgG2jtI+M6g4AwCoo7Qv73Ko7AMA2UNpHTHUHAGBZlPalHIfqDgCwqZT2DaG6AwCwSEr7\n",
44 "kqnuAACbRWnfQKo7AADzUtpXSHUHABg/pX3Dqe4AAByF0r4mqjsAwDgp7VtEdQcA4KCU9gFQ3QEA\n",
45 "xkNp31KqOwAA56O0D4zqDgAwbEo7qjsAAOdQ2gdMdQcAGB6lnbOo7gAAJEr7aKjuAADDoLQzk+oO\n",
46 "ALC9lPYRUt0BANZHaedAVHcAgO2itI+c6g4AsFpKO4emugMAbD6lfYOo7gAAy6e0MxfVHQBgMynt\n",
47 "G0p1BwBYDqWdhVHdAQA2h9K+BVR3AIDFUdpZCtUdAGDclPYto7oDAMxHaWfpVHcAgPFR2reY6g4A\n",
48 "cHhKOyulugMAjIPSThLVHQDgoJR21kZ1BwAYLqWdc6juAACzKe0MguoOADAsSjvnpboDAJxNaWdw\n",
49 "VHcAgPVT2jkw1R0AQGln4FR3AID1UNo5EtUdANhWSjujoboDAKyO0s7cVHcAYJso7YyS6g4AsFxK\n",
50 "OwulugMAm05pZ/RUdwCAxVPaWRrVHQDYREo7G0V1BwBYDKWdlVDdAYBNobSzsVR3AICjU9pZOdUd\n",
51 "ABgzpZ2toLoDAByO0s5aqe4AwNgo7Wwd1R0AYH9KO4OhugMAY6C0s9VUdwCAvSntDJLqDgAMldIO\n",
52 "U6o7AMDjlHYGT3UHAIZEaYc9qO4AwLZbyKS9qi6rqpur6v6qerSqTlfVjVX1pEOO8x1VdXtVfbqq\n",
53 "Hq6q362qX6qqZy/iOBmv7nR33pXkWUluTXJhknckua0qT1/rwQEALNncy2Oq6sokdyS5OMl7ktyZ\n",
54 "5OokJ5PcleSa7v7cAcb5l0lek+Sz03E+m+SqJC9IcizJS7v7F/cZw/KYLTCt6y9J8rYkT07yxSSv\n",
55 "TvLO7mzOei8AYJDWMedcxKT9tkyWK7yyu3/6jOd/MskPJ/nZ7v7BfcZ4apLPJPmDJN/Q3Z89Y9+1\n",
56 "ST6Y5HR3X7nPOCbtW8RadwBgHUY3aZ9W9nuyx4S6qi5I8kCSTnJpdz98nnGuTvKbSd7b3S/aY/8X\n",
57 "knR3X7TP8Zi0bxnVHQBYtTG+EfXkdHv77h3d/aUkH0nyxCT7rUm/O8lXklxdVU8+c0dVfUuSC5J8\n",
58 "YM5jZQNZ6w4AbIN5J+0nptu7Z+y/Z7q96nyDdPfnk7w2yaVJfqeq3lFVb6qqX0pyWya/FPyDOY+V\n",
59 "DeYKMwDAJpt30r6zXOWhGft3nt/3KjLd/W8ymXQdS/KyTCbx35Xk95L8/Jnr3GEvqjsAsKkGc532\n",
60 "qvonSd6d5OeSHE/yhCTflOTeJL84vbrMQcfq8zxOLeP4GQ7VHQCYV1WdmjWfXMfxzDtp3ynps94g\n",
61 "uvP8g+cbZHqFmDdn8kbUH+3u+7r70e7+WCZXBvlMkldX1RUHOajurvM8Th1kDMZNdQcA5tHdp2bN\n",
62 "J9dxPPNO2u+cbk/M2L+zln3Wmvcd3zndfmj3ju5+JMn/yORYv/GwB8h2U90BgE0w76R9Z5J9XVWd\n",
63 "NQGqqguTXJPkj5N8dJ9xvma6vWTG/oun268c5SDZbqo7ADB2c03au/veTK7sckWSV+zafUMm69Jv\n",
64 "mdbyVNWxqnpGVR3f9dr/Ot2+vKr+wpk7qurbM5n8P5LJnVfhSFR3AGCsFnFH1OOZTKYvSfLeTJbM\n",
65 "XJ3k2iR3JXnO9JKOqarLM3lj6Se7+4ozxqhMLu34bZncHOfWTO6O+vWZLJ3pJK/q7pv2ORY3V+JA\n",
66 "3E0VADiq0d0R9auDVF2W5A1Jnp/JXSnvz2TifUN3P3TG6y7PZNJ+X3cf3zXGsUxq/fckeWYmlf7/\n",
67 "JvnvSd7a3fveXMmkncNwN1UA4ChGO2kfCpN2jkJ1BwAOYx1zzsFcpx3WxVp3AGDolHY4g+oOAOxH\n",
68 "aYc1U90BgCFS2mEG1R0A2IvSDgOiugMAQ6G0wwGo7gDADqUdBkp1BwDWSWmHQ1LdAWC7Ke0wAqo7\n",
69 "ALBqSjvMQXUHgO2jtMPIqO4AwCoo7bAgqjsAbAelHUZMdQcAlkVphyVQ3QFgcyntsCFUdwBgkZR2\n",
70 "WDLVHQA2i9IOG0h1BwDmpbTDCqnuADB+SjtsONUdADgKpR3WRHUHgHFS2mGLqO4AwEEp7TAAqjsA\n",
71 "jIfSDltKdQcAzkdph4FR3QFg2JR2QHUHAM6htMOAqe4AMDxKO3AW1R0ASJR2GA3VHQCGQWkHZlLd\n",
72 "AWB7Ke0wQqo7AKyP0g4ciOoOANtFaYeRU90BYLWUduDQVHcA2HxKO2wQ1R0Alk9pB+aiugPAZlLa\n",
73 "YUOp7gCwHEo7sDCqOwBsDqUdtoDqDgCLo7QDS6G6A8C4Ke2wZVR3AJiP0g4sneoOAOOjtMMWU90B\n",
74 "4PCUdmClVHcAGAelHUiiugPAQSntwNqo7gAwXEo7cA7VHQBmU9qBQVDdAWBYlHbgvFR3ADib0g4M\n",
75 "juoOAOuntAMHproDgNIODJzqDgDrobQDR6K6A7CtlHZgNFR3AFgdpR2Ym+oOwDZR2oFRUt0BYLmU\n",
76 "dmChVHcANp3SDoye6g4Ai6e0A0ujugOwiZR2YKOo7gCwGEo7sBKqOwCbQmkHNpbqDgBHp7QDK6e6\n",
77 "AzBmSjuwFVR3ADgcpR1YK9UdgLFR2oGto7oDwP6UdmAwVHcAxkBpB7aa6g4Ae1PagUFS3QEYKqUd\n",
78 "YEp1B4DHKe3A4KnuAAyJ0g6wB9UdgG2ntAOjoroDsG5KO8A+VHcAtpHSDoyW6g7AOoyytFfVZVV1\n",
79 "c1XdX1WPVtXpqrqxqp50hLGeW1W3VtUD07E+U1Xvq6pvn/c4gc2jugOwLeYq7VV1ZZI7klyc5D1J\n",
80 "7kxydZKTSe5Kck13f+6AY/1Ekh9N8ntJ/kuSzya5JMlfTfKB7v6nBxhDaYctpboDsCrrmHPOO2m/\n",
81 "LZOy9cru/ukznv/JJD+c5Ge7+wcPMM4PJPnZJP8hycu7+0927T+2+7kZ45i0wxab1vWXJHlbkicn\n",
82 "+WKSVyd5Z3c2Zy0gAGs1qkn7tLLfk+R0d1+5a98FSR5I0kku7e6HzzPO12RS1/84yVUHmZyfZyyT\n",
83 "dkB1B2Cpxram/eR0e/vuHd39pSQfSfLEJM/eZ5zrkjwlya8k6ar6jqp6bVVdX1X7fSzAOax1B2DT\n",
84 "zDNpPzHd3j1j/z3T7VX7jPPN0+2Xk3w8yX9O8qYkNya5o6p+vaqeMsdxAluoO92ddyV5VpJbk1yY\n",
85 "5B1JbqvK09d6cABwSPNM2i+abh+asX/n+f2uInPJdPuaJH+a5K8nuSDJN2RS8b8lybuPfpjANlPd\n",
86 "AdgEQ7i50s4x/L8kL+juO7r74e7+7UzWo346ybdaKgMcleoOwNjNM2nfKekXzdi/8/yD+4yzs/9j\n",
87 "3X3Wm8S6+5Ekt03/9ZtzQFXV53mcOug4wGZR3QE4qKo6NWs+uY7jmWfSfud0e2LG/p217LPWvO8e\n",
88 "Z9bkfuf5P3fA40p313kepw46DrB5VHcADqK7T82aT67jeOaZtH9our2uqs46+Kq6MMk1mVzG8aP7\n",
89 "jPNrmVwa8pm7x5n6y9Pt6TmOFeAsqjsAY3LkSXt335vJG0WvSPKKXbtvSPKEJLdMl7ikqo5V1TOq\n",
90 "6viucT6VyRVj/lKS68/cV1XPS/I3k3w+yfuOeqwAe1HdARiLee+IejzJHZlcAea9mSx1uTrJtUnu\n",
91 "SvKc7v789LWXJ7k3ySe7+4pd4/zF6ThPy6S8fzyTXwZemMkVZb6nu289wPG4uRJwJO6mCsBBjeqO\n",
92 "qF8doOqyJG9I8vxMftDdn0mxuqG7HzrjdZdnMmm/r7uP7zHOU5L8eJIXJPnzmbzR9cNJ3tTdv3XA\n",
93 "YzFpB+bibqoA7GeUk/YhMWkHFkF1B+B8TNrnZNIOLJLqDsBe1jHnHMLNlQAGyRVmABgKpR3gAFR3\n",
94 "AHYo7QADpboDsE5KO8Ahqe4A201pBxgB1R2AVVPaAeagugNsH6UdYGRUdwBWQWkHWBDVHWA7KO0A\n",
95 "I6a6A7AsSjvAEqjuAJtLaQfYEKo7AIuktAMsmeoOsFmUdoANpLoDMC+lHWCFVHeA8VPaATac6g7A\n",
96 "USjtAGuiugOMk9IOsEVUdwAOSmkHGADVHWA8lHaALaW6A3A+SjvAwKjuAMOmtAOgugNwDqUdYMBU\n",
97 "d4DhUdoBOIvqDkCitAOMhuoOMAxKOwAzqe4A20tpBxgh1R1gfZR2AA5EdQfYLko7wMip7gCrpbQD\n",
98 "cGiqO8DmU9oBNojqDrB8SjsAc1HdATaT0g6woVR3gOVQ2gFYGNUdYHMo7QBbQHUHWBylHYClUN0B\n",
99 "xk1pB9gyqjvAfJR2AJZOdQcYH6UdYIup7gCHp7QDsFKqO8A4KO0AJFHdAQ5KaQdgbVR3gOFS2gE4\n",
100 "h+oOMJvSDsAgqO4Aw6K0A3BeqjvA2ZR2AAZHdQdYP6UdgANT3QGUdgAGTnUHWA+lHYAjUd2BbaW0\n",
101 "AzAaqjvA6ijtAMxNdQe2idIOwCip7gDLpbQDsFCqO7DplHYARk91B1g8pR2ApVHdgU2ktAOwUVR3\n",
102 "gMVQ2gFYCdUd2BRKOwAbS3UHODqlHYCVU92BMVPaAdgKqjvA4SjtAKyV6g6MjdIOwNZR3QH2p7QD\n",
103 "MBiqOzAGSjsAW011B9ib0g7AIKnuwFAp7QAwpboDPE5pB2DwVHdgSJR2ANiD6g5sO6UdgFFR3YF1\n",
104 "U9oBYB+qO7CNlHYARkt1B9ZBaQeAQ1DdgW2htAOwEVR3YFWUdgA4ItUd2GRzT9qr6rKqurmq7q+q\n",
105 "R6vqdFXdWFVPmmPM762qx6aPvz/vMQKwHbrT3XlXkmcluTXJhUnekeS2qjx9rQcHMIe5Ju1VdWWS\n",
106 "/5nk7yb5aJKfSnJvkuuT/GZVfe0Rxnxakrcl+dL0qc1ZvwPASqjuwKaZt7S/PcnFSV7Z3S/u7td1\n",
107 "93OT3JjkRJI3HmawqqokP5fkj5L82zmPDYAtproDm+TIk/ZpZb8uyenu/uldu1+f5OEk31tVTzjE\n",
108 "sD+U5GSSvzf9eACYi+oObIJ5SvvJ6fb23Tu6+0tJPpLkiUmefZDBqurrk7w5yVu6+zfmOC4AOIvq\n",
109 "DozdPJP2E9Pt3TP23zPdXrXfQFV1LMktSe5L8ro5jgkAZlLdgbGaZ9J+0XT70Iz9O88f5CoyP57k\n",
110 "G5P83e7+8hzHBADnpboDY7T267RX1dVJfizJv+ru/7bu4wFgO6juwJjMM2nfKekXzdi/8/yDswaY\n",
111 "Lov5hSR3ZfLm1T1fdtgDq6o+z+PUYccDYDOp7sAsVXVq1nxyHcczz6T9zun2xIz9O2vZZ615T5IL\n",
112 "pq97ZpJHz7ih0mOZLJlJkn83fe7Ggx5Yd9d5HqcOOg4A20F1B3br7lOz5pPrOJ7qPtovC1V1PMkn\n",
113 "kpxO8nV9xkBVdWGS38/kxkiXdPcjM8b4s0luyt43UPqmJH8lyYczKfHv7+5373NMnUwm7Yf+ggAg\n",
114 "SVUuTfIzSV40fer9SV7WnU+t76iAIVnHnPPIk/Ykqar3JXlekh/q7red8fxPJXlVkn/b3f9o+tyx\n",
115 "JF+X5Cvdfe8Bxj6VSW1/WXfffMDjMWkHYG7Tuv6STO7Q/eQkX0zy6iTv7Hanbth265hzzvtG1H+U\n",
116 "5A+TvLWqbq2qN1XVBzOZsN+V5J+d8drLkvxOkl+b83MCwFJZ6w4MzVyT9mkx/2tJ/kOSq5P8SJIr\n",
117 "krwlybO7+/N7fdhBhz/EawFg4ax1B4ZiruUxQ2N5DADLYq07sGOMy2MAYCuo7sA6Ke0AcEiqO2w3\n",
118 "pR0ARkB1B1ZNaQeAOajusH2UdgAYGdUdWAWlHQAWRHWH7aC0A8CIqe7AsijtALAEqjtsLqUdADaE\n",
119 "6g4sktIOAEumusNmUdoBYAOp7sC8lHYAWCHVHcZPaQeADae6A0ehtAPAmqjuME5KOwBsEdUdOCil\n",
120 "HQAGQHWH8VDaAWBLqe7A+SjtADAwqjsMm9IOAKjuwDmUdgAYMNUdhkdpBwDOoroDidIOAKOhusMw\n",
121 "KO0AwEyqO2wvpR0ARkh1h/VR2gGAA1HdYbso7QAwcqo7rJbSDgAcmuoOm09pB4ANorrD8intAMBc\n",
122 "VHfYTEo7AGwo1R2WQ2kHABZGdYfNobQDwBZQ3WFxlHYAYClUdxg3pR0AtozqDvNR2gGApVPdYXyU\n",
123 "dgDYYqo7HJ7SDgCslOoO46C0AwBJVHc4KKUdAFgb1R2GS2kHAM6husNsSjsAMAiqOwyL0g4AnJfq\n",
124 "DmdT2gGAwVHdYf2UdgDgwFR3UNoBgIFT3WE9lHYA4EhUd7aV0g4AjIbqDqujtAMAc1Pd2SZKOwAw\n",
125 "Sqo7LJfSDgAslOrOplPaAYDRU91h8ZR2AGBpVHc2kdIOAGwU1R0WQ2kHAFZCdWdTKO0AwMZS3eHo\n",
126 "lHYAYOVUd8ZMaQcAtoLqDoejtAMAa6W6MzZKOwCwdVR32J/SDgAMhurOGCjtAMBWU91hb0o7ADBI\n",
127 "qjtDpbQDAEyp7vA4pR0AGDzVnSFR2gEA9qC6s+2UdgBgVFR31k1pBwDYh+rONlLaAYDRUt1ZB6Ud\n",
128 "AOAQVHe2hdIOAGwE1Z1VUdoBAI5IdWeTKe0AwMZR3VkmpR0AYAFUdzaN0g4AbDTVnUVT2gEAFkx1\n",
129 "ZxMsZNJeVZdV1c1VdX9VPVpVp6vqxqp60gE//mur6mVVdWtVfaKqHq6qB6vqw1X1/VXlDxQAcGTd\n",
130 "6e68K8mzktya5MIk70hyW1WevtaDgwOYe3lMVV2Z5I4kFyd5T5I7k1yd5GSSu5Jc092f22eMf5jk\n",
131 "7UnuT/KhJJ9K8tQkL05yUZJf7u7vPsCxWB4DAJzXtK6/JMnbkjw5yReTvDrJO7uzOeuGWZp1zDkX\n",
132 "MWm/LZP/zfTK7v7pM57/ySQ/nORnu/sH9xnjZJIndPev7nr+0iT/PcnTknxXd//KPuOYtAMAB2Kt\n",
133 "O0c1ukn7tLLfk+R0d1+5a98FSR5I0kku7e6Hj/g5fizJG5Pc1N3X7/Nak3YA4MBUd45ijG9EPTnd\n",
134 "3r57R3d/KclHkjwxybPn+Bx/smsLALAQ1rozFvNO2k9Mt3fP2H/PdHvVUQavqmNJXjr91/cdZQwA\n",
135 "gP24wgxDN++k/aLp9qEZ+3eeP9BVZPbw5kx+8/3V7n7/EccAANiX6s6QDfY67VX1Q0l+JMn/SfJ9\n",
136 "h/zYPs/j1DKOFwDYDKo7SVJVp2bNJ9dxPPNO2ndK+kUz9u88/+BhBq2qf5zkLUn+d5KT3X2oj+/u\n",
137 "Os/j1GHGAgC2j+pOd5+aNZ9cx/HMO2m/c7o9MWP/zlr2WWvez1FVr0ry1iT/K5MJ+x8e/fAAAI5O\n",
138 "dWco5r3k4/Ekn0hyOsnX9RmDVdWFSX4/k0s+XtLdjxxgvNcmeVOSjyW5br+bMu3x8S75CAAsheu6\n",
139 "s2N0l3zs7nszudzjFUlesWv3DUmekOSWnQl7VR2rqmdMJ/tnqap/kcmE/beSPPewE3YAgGVS3Vmn\n",
140 "RdwR9XiSO5JckuS9mSyZuTrJtUnuSvKc7v789LWXJ7k3ySe7+4ozxvg7SX4uyZ8muSnJF/b4VKe7\n",
141 "++f3ORalHQBYOtV9u43ujqhfHaTqsiRvSPL8TO4mdn8mb9q4obsfOuN1l2cyab+vu4+f8fzrk7w+\n",
142 "k6U0s774X+/uv7HPcZi0AwAr4W6q22u0k/ahMGkHAFZNdd8+o1vTDgCw7ax1ZxWUdgCABVHdt4PS\n",
143 "DgAwYqo7y6K0AwAsgeq+uZR2AIANobqzSEo7AMCSqe6bRWkHANhAqjvzUtoBAFZIdR8/pR0AYMOp\n",
144 "7hyF0g4AsCaq+zgp7QAAW0R156CUdgCAAVDdx0NpBwDYUqo756O0AwAMjOo+bEo7AACqO+dQ2gEA\n",
145 "Bkx1Hx6lHQCAs6juJEo7AMBoqO7DoLQDADCT6r69lHYAgBFS3ddHaQcA4EBU9+2itAMAjJzqvlpK\n",
146 "OwAAh6a6bz6lHQBgg6juy6e0AwAwF9V9MyntAAAbSnVfDqUdAICFUd03h9IOALAFVPfFUdoBAFgK\n",
147 "1X3clHYAgC2jus9HaQcAYOlU9/FR2gEAtpjqfnhKOwAAK6W6j4PSDgBAEtX9oJR2AADWRnUfLqUd\n",
148 "AIBzqO6zKe0AAAyC6j4sSjsAAOelup9NaQcAYHBU9/VT2gEAODDVXWkHAGDgVPf1UNoBADiSba3u\n",
149 "SjsAAKOhuq+O0g4AwNy2qbor7QAAjJLqvlxKOwAAC7Xp1V1pBwBg9FT3xVPaAQBYmk2s7ko7AAAb\n",
150 "RXVfDKUdAICV2JTqrrQDALCxVPejU9oBAFi5MVd3pR0AgK2guh+O0g4AwFqNrbor7QAAbB3VfX9K\n",
151 "OwAAgzGG6q60AwCw1VT3vSntAAAM0lCru9IOAABTqvvjlHYAAAZvSNVdaQcAgD1se3VX2gEAGJV1\n",
152 "V3elHQAA9rGN1V1pBwBgtNZR3ZV2AAA4hG2p7ko7AAAbYVXVXWkHAIAj2uTqrrQDALBxllndlXYA\n",
153 "AFiATavuSjsAABtt0dVdaQcAgAXbhOqutAMAsDUWUd2VdgAAWKKxVnelHQCArXTU6j7K0l5Vl1XV\n",
154 "zVV1f1U9WlWnq+rGqnrSOsaBvVTVqXUfA8PinGAvzgv24rzYXGOq7nOV9qq6MskdSS5O8p4kdya5\n",
155 "OsnJJHcluaa7P7fCcZR29lRV7bzgTM4J9uK8YC/Oi+1wmOo+xtL+9kwm2q/s7hd39+u6+7lJbkxy\n",
156 "IskbVzwOAAAc2tCr+5FL+7SO35PkdHdfuWvfBUkeSNJJLu3uh5c9zvT1Sjt7UknYzTnBXpwX7MV5\n",
157 "sX32q+5jK+0np9vbd+/o7i8l+UiSJyZ59orGAQCAuQ2xus8zaT8x3d49Y/890+1VKxoHAAAWojvd\n",
158 "nXcleVaSW5NcmOQdSW5bx/HMM2m/aLp9aMb+nef3u/rLosYBAICFmlHdV+7YOj7psu2sM4IzOS/Y\n",
159 "zTnBXpwX7MV5wbrNU9p3CvhFM/bvPP/gisYBAICNNE9pv3O6PTFj/84a9Flr1Rc9jqvGAACwkea5\n",
160 "5OPxJJ9IcjrJ1/UZA1XVhUl+P5NLNV7S3Y8sexwAANhUR14e0933ZnKZxiuSvGLX7huSPCHJLTsT\n",
161 "7ao6VlXPmE7SjzwOAABsmyOX9uSrlfyOJJckeW8mS12uTnJtkruSPKe7Pz997eVJ7k3yye6+4qjj\n",
162 "AADAtplr0p4kVXVZkjckeX6SJye5P5NrWd7Q3Q+d8brLM5m039fdx486DgAAbJu5J+0AAMByzXPJ\n",
163 "RwAAYAVM2gEAYOAGPWmvqsuq6uaqur+qHq2q01V1Y1U9aR3jMAzzfj+r6mur6mVVdWtVfaKqHq6q\n",
164 "B6vqw1X1/VXlev8jtIw/51X1vVX12PTx9xd5vKzGIs+Lqnru9O+NB6Zjfaaq3ldV376MY2d5Fji/\n",
165 "+I6qur2qPj39WfK7VfVLVfXsZR07i1dV31VVN03nAV+Y/p1/yxHHWtqcc7Br2qvqykyuKHNxkvfk\n",
166 "8SvKnMzkijLXdPfnVjUOw7CI72dV/cMkb8/kzc4fSvKpJE9N8uJM7sD7y9393cv6Gli8Zfw5r6qn\n",
167 "JflfmcSNC5K8rLtvXuRxs1yLPC+q6ieS/GiS30vyX5J8NpMrnv3VJB/o7n+68C+ApVjg/OJfJnlN\n",
168 "JufCe6ZH+b3pAAAGc0lEQVTbq5K8IJObV760u39xGV8Di1VVH0/yDUm+mOQzSZ6R5D9290sPOc5y\n",
169 "55zdPchHktuSPJbkFbue/8np8z+zynE8hvFYxPdz+ofnO/Z4/tIkn5yO8+J1f60eqz0vdn1cJflA\n",
170 "knuS/MR0jO9f99fpsZ7zIskPTF9/c5Jje+w/5zmP4T4W9HPkqUn+NJP485Rd+66djvO76/5aPQ58\n",
171 "Tlyb5MrpP3/r9Pv3C0cYZ6lzzkGW9ulvKvckOd3dV+7ad0GSBzK5S+ql3f3wssdhGFbx/ayqH0vy\n",
172 "xiQ3dff1cx4yK7CM86Kqrk/yU5n85f1tSX48SvuoLPDnyNdkUtf/OMlV3f0nyztqlm2B58XVSX4z\n",
173 "yXu7+0V77P9Cku7uixZ5/CxfVV2b5IM5ZGlfxRxlqGvaT063t+/e0d1fSvKRJE9Mst+asUWNwzCs\n",
174 "4vv5J7u2DN9Cz4uq+vokb07ylu7+jUUdJCu3qPPiuiRPSfIrSXq6hvm1VXW9dcujtKjz4u4kX0ly\n",
175 "dVU9+cwdVfUtmSyp+8DcR8uYLH2OMtRJ+4np9u4Z+++Zbq9a0TgMw1K/n1V1LMnOb9XvO8oYrMXC\n",
176 "zovpOXBLkvuSvG7uI2OdFnVefPN0++UkH0/yn5O8KcmNSe6oql+vqqfMc6Cs1ELOi57cpf21mSyr\n",
177 "/J2qekdVvamqfimTJRK3J/kHCzhexmPpc85jR/3AJdv530mz7oS68/x+78Rd1DgMw7K/n29O8qwk\n",
178 "v9rd7z/iGKzeIs+LH0/yjZm8WejL8x4Ya7Wo8+KS6fY1Sf53kr+eyeT9eJJ/neR5Sd6dxysbw7aw\n",
179 "vy+6+99U1SeT/PskLztj1yeS/Hx3f/bIR8kYLX3OOdTSDitVVT+U5EeS/J8k37fmw2ENpmtUfyzJ\n",
180 "v+ru/7bu42Ewdn5O/r8kL+juO7r74e7+7SQvSvLpJN9qqcz2qap/kskvbD+XyS9xT0jyTUnuTfKL\n",
181 "06vLwMIMddK+89vIrDdw7Dz/4IrGYRiW8v2sqn+c5C2ZVLST3e18GJe5z4vpsphfyOSSXK+f9bIj\n",
182 "HR3rsqi/L3b2f6y7P3Xmju5+JJOlEMnjy2gYtoWcF9M3K745kzei/mh339fdj3b3xzL5Ze4zSV5d\n",
183 "VVcs4JgZh6XPOYc6ab9zuj0xY//OeqBZ64YWPQ7DsPDvZ1W9KslbM7ke98nu/sOjHx5rsojz4oLp\n",
184 "656Z5NEzbqj0WCZLZpLk302fu3HuI2YVFv1zZNYP2p3n/9wBj4v1WtR58Z3T7Yd275j+Mvc/Mplj\n",
185 "feNhD5DRWvqcc6hr2nf+EFxXVdVnXJeyqi5Mck0ml9/66IrGYRgW+v2sqtdm8oayjyW5rt1ka6wW\n",
186 "cV48msm61L2ugftNSf5Kkg9nUuLvWMRBs3SL+vvi1zI5L565e5ypvzzdnl7AMbN8izovvma6vWTG\n",
187 "/oun268c9UAZnaXPOQdZ2rv73kzeeX1Fklfs2n1DJuvGbpn+NpuqOlZVz6iq4/OMw7At6ryY7vsX\n",
188 "mUzYfyvJc03Yx2sR58X0f2v/QHe/fPcjk6uFJJM3lr28u9+9/K+KeS3w58inMjkH/lKSs+7dUFXP\n",
189 "S/I3k3w+rjg1Cgv8OfJfp9uXV9VfOHNHVX17JhO0R+KX/I2zzjnnIG+ulCTT/xh3ZPJb7Hvz+K1g\n",
190 "r82kdj1nesmlVNXlmbzx45PdfcVRx2H4FnFeVNXfyeSNQ3+a5KYkX9jjU53u7p9f1tfBYi3q74sZ\n",
191 "Y5+KmyuN0gJ/jvzF6ThPy6S8fzyTH8wvzOTvke/p7luX/gWxEAv6OVKZvJ/h25J8McmtSf4gyddn\n",
192 "snSmk7yqu29axdfEfKrqhZn8eU4md7t9Xibf9517dfxRd79m+trLs64552Fun7rqR5LLMrlt9P2Z\n",
193 "XCP3dCZ3Kbxo1+suz+T2sPfOM47HOB7znheZvNHwsUx+2D424/HBdX+dHqs9L84z7uun58r3r/tr\n",
194 "9FjfeZHJDZbemsk1/L+c5A+T/HKSv7bur9FjPedFJkuMr8/kzqgPZXKFoQeS/Kck37bur9HjUOfD\n",
195 "mfOCMx+P7f7+r3POOdjSDgAATAxyTTsAAPA4k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YAABg4\n",
196 "k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YAABg4k3YA\n",
197 "ABg4k3YAABi4/w/Y3UZ5IHmVbAAAAABJRU5ErkJggg==\n"
198 ],
199 "text/plain": [
200 "<matplotlib.figure.Figure at 0x10d0da080>"
201 ]
202 },
203 "metadata": {
204 "image/png": {
205 "height": 255,
206 "width": 374
207 }
208 },
209 "output_type": "display_data"
210 }
211 ],
212 "source": [
213 "%matplotlib inline\n",
214 "%config InlineBackend.figure_formats = set(['retina'])\n",
215 "import matplotlib.pyplot as plt\n",
216 "plt.plot([0,1],[1,0])"
217 ]
218 }
219 ],
220 "metadata": {
221 "kernelspec": {
222 "display_name": "IPython mydev (Python 3)",
223 "name": "python3_mydev"
224 },
225 "language_info": {
226 "codemirror_mode": {
227 "name": "ipython",
228 "version": 3
229 },
230 "file_extension": ".py",
231 "mimetype": "text/x-python",
232 "name": "python",
233 "nbconvert_exporter": "python",
234 "pygments_lexer": "ipython3",
235 "version": "3.4.2"
236 }
237 },
238 "nbformat": 4,
239 "nbformat_minor": 0
240 } No newline at end of file
@@ -1,81 +0,0 b''
1 {
2 "metadata": {
3 "name": "notebook2"
4 },
5 "nbformat": 3,
6 "nbformat_minor": 0,
7 "worksheets": [
8 {
9 "cells": [
10 {
11 "cell_type": "code",
12 "collapsed": false,
13 "input": [
14 "import numpy as np"
15 ],
16 "language": "python",
17 "metadata": {},
18 "outputs": [],
19 "prompt_number": 2
20 },
21 {
22 "cell_type": "code",
23 "collapsed": false,
24 "input": [
25 "evs = np.zeros(100)",
26 "evs.shape"
27 ],
28 "language": "python",
29 "metadata": {},
30 "outputs": [
31 {
32 "metadata": {},
33 "output_type": "pyout",
34 "prompt_number": 10,
35 "text": [
36 "(100,)"
37 ]
38 }
39 ],
40 "prompt_number": 10
41 },
42 {
43 "cell_type": "code",
44 "collapsed": false,
45 "input": [],
46 "language": "python",
47 "metadata": {},
48 "outputs": []
49 },
50 {
51 "cell_type": "code",
52 "collapsed": false,
53 "input": [],
54 "language": "python",
55 "metadata": {},
56 "outputs": [],
57 "prompt_number": null
58 },
59 {
60 "cell_type": "code",
61 "collapsed": false,
62 "input": [],
63 "language": "python",
64 "metadata": {},
65 "outputs": [],
66 "prompt_number": "*"
67 },
68 {
69 "cell_type": "code",
70 "collapsed": false,
71 "input": [],
72 "language": "python",
73 "metadata": {},
74 "outputs": [],
75 "prompt_number": 0
76 }
77 ],
78 "metadata": {}
79 }
80 ]
81 } No newline at end of file
@@ -1,77 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "raw",
5 "metadata": {
6 "raw_mimetype": "text/html"
7 },
8 "source": [
9 "<b>raw html</b>"
10 ]
11 },
12 {
13 "cell_type": "raw",
14 "metadata": {
15 "raw_mimetype": "text/markdown"
16 },
17 "source": [
18 "* raw markdown\n",
19 "* bullet\n",
20 "* list"
21 ]
22 },
23 {
24 "cell_type": "raw",
25 "metadata": {
26 "raw_mimetype": "text/restructuredtext"
27 },
28 "source": [
29 "``raw rst``\n",
30 "\n",
31 ".. sourcecode:: python\n",
32 "\n",
33 " def foo(): pass\n"
34 ]
35 },
36 {
37 "cell_type": "raw",
38 "metadata": {
39 "raw_mimetype": "text/x-python"
40 },
41 "source": [
42 "def bar():\n",
43 " \"\"\"raw python\"\"\"\n",
44 " pass"
45 ]
46 },
47 {
48 "cell_type": "raw",
49 "metadata": {
50 "raw_mimetype": "text/latex"
51 },
52 "source": [
53 "\\LaTeX\n",
54 "% raw latex"
55 ]
56 },
57 {
58 "cell_type": "raw",
59 "metadata": {},
60 "source": [
61 "# no raw_mimetype metadata, should be included by default"
62 ]
63 },
64 {
65 "cell_type": "raw",
66 "metadata": {
67 "raw_mimetype": "doesnotexist"
68 },
69 "source": [
70 "garbage format defined, should never be included"
71 ]
72 }
73 ],
74 "metadata": {},
75 "nbformat": 4,
76 "nbformat_minor": 0
77 } No newline at end of file
@@ -1,90 +0,0 b''
1 """
2 Module with tests for export.py
3 """
4
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 import os
9
10 from IPython import nbformat
11
12 from .base import ExportersTestsBase
13 from ..export import *
14 from ..python import PythonExporter
15
16
17 class TestExport(ExportersTestsBase):
18 """Contains test functions for export.py"""
19
20
21 def test_export_wrong_name(self):
22 """
23 Is the right error thrown when a bad template name is used?
24 """
25 try:
26 export_by_name('not_a_name', self._get_notebook())
27 except ExporterNameError as e:
28 pass
29
30
31 def test_export_filename(self):
32 """
33 Can a notebook be exported by filename?
34 """
35 (output, resources) = export_by_name('python', self._get_notebook())
36 assert len(output) > 0
37
38
39 def test_export_nbnode(self):
40 """
41 Can a notebook be exported by a notebook node handle?
42 """
43 with open(self._get_notebook(), 'r') as f:
44 notebook = nbformat.read(f, 4)
45 (output, resources) = export_by_name('python', notebook)
46 assert len(output) > 0
47
48
49 def test_export_filestream(self):
50 """
51 Can a notebook be exported by a filesteam?
52 """
53 with open(self._get_notebook(), 'r') as f:
54 (output, resources) = export_by_name('python', f)
55 assert len(output) > 0
56
57
58 def test_export_using_exporter(self):
59 """
60 Can a notebook be exported using an instanciated exporter?
61 """
62 (output, resources) = export(PythonExporter(), self._get_notebook())
63 assert len(output) > 0
64
65
66 def test_export_using_exporter_class(self):
67 """
68 Can a notebook be exported using an exporter class type?
69 """
70 (output, resources) = export(PythonExporter, self._get_notebook())
71 assert len(output) > 0
72
73
74 def test_export_resources(self):
75 """
76 Can a notebook be exported along with a custom resources dict?
77 """
78 (output, resources) = export(PythonExporter, self._get_notebook(), resources={})
79 assert len(output) > 0
80
81
82 def test_no_exporter(self):
83 """
84 Is the right error thrown if no exporter is provided?
85 """
86 try:
87 (output, resources) = export(None, self._get_notebook())
88 except TypeError:
89 pass
90
@@ -1,59 +0,0 b''
1 """
2 Module with tests for exporter.py
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from IPython.config import Config
18
19 from .base import ExportersTestsBase
20 from ...preprocessors.base import Preprocessor
21 from ..exporter import Exporter
22
23
24 #-----------------------------------------------------------------------------
25 # Class
26 #-----------------------------------------------------------------------------
27
28 class PizzaPreprocessor(Preprocessor):
29 """Simple preprocessor that adds a 'pizza' entry to the NotebookNode. Used
30 to test Exporter.
31 """
32
33 def preprocess(self, nb, resources):
34 nb['pizza'] = 'cheese'
35 return nb, resources
36
37
38 class TestExporter(ExportersTestsBase):
39 """Contains test functions for exporter.py"""
40
41
42 def test_constructor(self):
43 """Can an Exporter be constructed?"""
44 Exporter()
45
46
47 def test_export(self):
48 """Can an Exporter export something?"""
49 exporter = Exporter()
50 (notebook, resources) = exporter.from_filename(self._get_notebook())
51 assert isinstance(notebook, dict)
52
53
54 def test_preprocessor(self):
55 """Do preprocessors work?"""
56 config = Config({'Exporter': {'preprocessors': [PizzaPreprocessor()]}})
57 exporter = Exporter(config=config)
58 (notebook, resources) = exporter.from_filename(self._get_notebook())
59 self.assertEqual(notebook['pizza'], 'cheese')
@@ -1,85 +0,0 b''
1 """Tests for HTMLExporter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import ExportersTestsBase
7 from ..html import HTMLExporter
8 from IPython.nbformat import v4
9 import re
10
11
12 class TestHTMLExporter(ExportersTestsBase):
13 """Tests for HTMLExporter"""
14
15 exporter_class = HTMLExporter
16 should_include_raw = ['html']
17
18 def test_constructor(self):
19 """
20 Can a HTMLExporter be constructed?
21 """
22 HTMLExporter()
23
24
25 def test_export(self):
26 """
27 Can a HTMLExporter export something?
28 """
29 (output, resources) = HTMLExporter().from_filename(self._get_notebook())
30 assert len(output) > 0
31
32
33 def test_export_basic(self):
34 """
35 Can a HTMLExporter export using the 'basic' template?
36 """
37 (output, resources) = HTMLExporter(template_file='basic').from_filename(self._get_notebook())
38 assert len(output) > 0
39
40
41 def test_export_full(self):
42 """
43 Can a HTMLExporter export using the 'full' template?
44 """
45 (output, resources) = HTMLExporter(template_file='full').from_filename(self._get_notebook())
46 assert len(output) > 0
47
48 def test_prompt_number(self):
49 """
50 Does HTMLExporter properly format input and output prompts?
51 """
52 (output, resources) = HTMLExporter(template_file='full').from_filename(
53 self._get_notebook(nb_name="prompt_numbers.ipynb"))
54 in_regex = r"In&nbsp;\[(.*)\]:"
55 out_regex = r"Out\[(.*)\]:"
56
57 ins = ["2", "10", "&nbsp;", "&nbsp;", "*", "0"]
58 outs = ["10"]
59
60 assert re.findall(in_regex, output) == ins
61 assert re.findall(out_regex, output) == outs
62
63 def test_png_metadata(self):
64 """
65 Does HTMLExporter with the 'basic' template treat pngs with width/height metadata correctly?
66 """
67 (output, resources) = HTMLExporter(template_file='basic').from_filename(
68 self._get_notebook(nb_name="pngmetadata.ipynb"))
69 assert len(output) > 0
70
71 def test_javascript_output(self):
72 nb = v4.new_notebook(
73 cells=[
74 v4.new_code_cell(
75 outputs=[v4.new_output(
76 output_type='display_data',
77 data={
78 'application/javascript': "javascript_output();"
79 }
80 )]
81 )
82 ]
83 )
84 (output, resources) = HTMLExporter(template_file='basic').from_notebook_node(nb)
85 self.assertIn('javascript_output', output)
@@ -1,117 +0,0 b''
1 """Tests for Latex exporter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import os.path
7 import textwrap
8 import re
9
10 from .base import ExportersTestsBase
11 from ..latex import LatexExporter
12 from IPython.nbformat import write
13 from IPython.nbformat import v4
14 from IPython.testing.decorators import onlyif_cmds_exist
15 from IPython.utils.tempdir import TemporaryDirectory
16
17
18 class TestLatexExporter(ExportersTestsBase):
19 """Contains test functions for latex.py"""
20
21 exporter_class = LatexExporter
22 should_include_raw = ['latex']
23
24 def test_constructor(self):
25 """
26 Can a LatexExporter be constructed?
27 """
28 LatexExporter()
29
30
31 @onlyif_cmds_exist('pandoc')
32 def test_export(self):
33 """
34 Can a LatexExporter export something?
35 """
36 (output, resources) = LatexExporter().from_filename(self._get_notebook())
37 assert len(output) > 0
38
39
40 @onlyif_cmds_exist('pandoc')
41 def test_export_book(self):
42 """
43 Can a LatexExporter export using 'report' template?
44 """
45 (output, resources) = LatexExporter(template_file='report').from_filename(self._get_notebook())
46 assert len(output) > 0
47
48
49 @onlyif_cmds_exist('pandoc')
50 def test_export_basic(self):
51 """
52 Can a LatexExporter export using 'article' template?
53 """
54 (output, resources) = LatexExporter(template_file='article').from_filename(self._get_notebook())
55 assert len(output) > 0
56
57
58 @onlyif_cmds_exist('pandoc')
59 def test_export_article(self):
60 """
61 Can a LatexExporter export using 'article' template?
62 """
63 (output, resources) = LatexExporter(template_file='article').from_filename(self._get_notebook())
64 assert len(output) > 0
65
66 @onlyif_cmds_exist('pandoc')
67 def test_very_long_cells(self):
68 """
69 Torture test that long cells do not cause issues
70 """
71 lorem_ipsum_text = textwrap.dedent("""\
72 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
73 dignissim, ipsum non facilisis tempus, dui felis tincidunt metus,
74 nec pulvinar neque odio eget risus. Nulla nisi lectus, cursus
75 suscipit interdum at, ultrices sit amet orci. Mauris facilisis
76 imperdiet elit, vitae scelerisque ipsum dignissim non. Integer
77 consequat malesuada neque sit amet pulvinar. Curabitur pretium
78 ut turpis eget aliquet. Maecenas sagittis lacus sed lectus
79 volutpat, eu adipiscing purus pulvinar. Maecenas consequat
80 luctus urna, eget cursus quam mollis a. Aliquam vitae ornare
81 erat, non hendrerit urna. Sed eu diam nec massa egestas pharetra
82 at nec tellus. Fusce feugiat lacus quis urna sollicitudin volutpat.
83 Quisque at sapien non nibh feugiat tempus ac ultricies purus.
84 """)
85 lorem_ipsum_text = lorem_ipsum_text.replace("\n"," ") + "\n\n"
86 large_lorem_ipsum_text = "".join([lorem_ipsum_text]*3000)
87
88 notebook_name = "lorem_ipsum_long.ipynb"
89 nb = v4.new_notebook(
90 cells=[
91 v4.new_markdown_cell(source=large_lorem_ipsum_text)
92 ]
93 )
94
95 with TemporaryDirectory() as td:
96 nbfile = os.path.join(td, notebook_name)
97 with open(nbfile, 'w') as f:
98 write(nb, f, 4)
99
100 (output, resources) = LatexExporter(template_file='article').from_filename(nbfile)
101 assert len(output) > 0
102
103 @onlyif_cmds_exist('pandoc')
104 def test_prompt_number_color(self):
105 """
106 Does LatexExporter properly format input and output prompts in color?
107 """
108 (output, resources) = LatexExporter().from_filename(
109 self._get_notebook(nb_name="prompt_numbers.ipynb"))
110 in_regex = r"In \[\{\\color\{incolor\}(.*)\}\]:"
111 out_regex = r"Out\[\{\\color\{outcolor\}(.*)\}\]:"
112
113 ins = ["2", "10", " ", " ", "*", "0"]
114 outs = ["10"]
115
116 assert re.findall(in_regex, output) == ins
117 assert re.findall(out_regex, output) == outs
@@ -1,40 +0,0 b''
1 """Tests for MarkdownExporter"""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 from .base import ExportersTestsBase
16 from ..markdown import MarkdownExporter
17
18 #-----------------------------------------------------------------------------
19 # Class
20 #-----------------------------------------------------------------------------
21
22 class TestMarkdownExporter(ExportersTestsBase):
23 """Tests for MarkdownExporter"""
24
25 exporter_class = MarkdownExporter
26 should_include_raw = ['markdown', 'html']
27
28 def test_constructor(self):
29 """
30 Can a MarkdownExporter be constructed?
31 """
32 MarkdownExporter()
33
34
35 def test_export(self):
36 """
37 Can a MarkdownExporter export something?
38 """
39 (output, resources) = MarkdownExporter().from_filename(self._get_notebook())
40 assert len(output) > 0 No newline at end of file
@@ -1,39 +0,0 b''
1 """Tests for notebook.py"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import json
7
8 from .base import ExportersTestsBase
9 from ..notebook import NotebookExporter
10
11 from IPython.nbformat import validate
12 from jupyter_nbconvert.tests.base import assert_big_text_equal
13
14 class TestNotebookExporter(ExportersTestsBase):
15 """Contains test functions for notebook.py"""
16
17 exporter_class = NotebookExporter
18
19 def test_export(self):
20 """
21 Does the NotebookExporter return the file unchanged?
22 """
23 with open(self._get_notebook()) as f:
24 file_contents = f.read()
25 (output, resources) = self.exporter_class().from_filename(self._get_notebook())
26 assert len(output) > 0
27 assert_big_text_equal(output.strip(), file_contents.strip())
28
29 def test_downgrade_3(self):
30 exporter = self.exporter_class(nbformat_version=3)
31 (output, resources) = exporter.from_filename(self._get_notebook())
32 nb = json.loads(output)
33 validate(nb)
34
35 def test_downgrade_2(self):
36 exporter = self.exporter_class(nbformat_version=2)
37 (output, resources) = exporter.from_filename(self._get_notebook())
38 nb = json.loads(output)
39 self.assertEqual(nb['nbformat'], 2)
@@ -1,36 +0,0 b''
1 """Tests for PDF export"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import logging
7 import os
8
9 from IPython.testing import decorators as dec
10
11 from .base import ExportersTestsBase
12 from ..pdf import PDFExporter
13
14
15 #-----------------------------------------------------------------------------
16 # Class
17 #-----------------------------------------------------------------------------
18
19 class TestPDF(ExportersTestsBase):
20 """Test PDF export"""
21
22 exporter_class = PDFExporter
23
24 def test_constructor(self):
25 """Can a PDFExporter be constructed?"""
26 self.exporter_class()
27
28
29 @dec.onlyif_cmds_exist('pdflatex')
30 @dec.onlyif_cmds_exist('pandoc')
31 def test_export(self):
32 """Smoke test PDFExporter"""
33 (output, resources) = self.exporter_class(latex_count=1).from_filename(self._get_notebook())
34 self.assertIsInstance(output, bytes)
35 assert len(output) > 0
36
@@ -1,23 +0,0 b''
1 """Tests for PythonExporter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import ExportersTestsBase
7 from ..python import PythonExporter
8
9
10 class TestPythonExporter(ExportersTestsBase):
11 """Tests for PythonExporter"""
12
13 exporter_class = PythonExporter
14 should_include_raw = ['python']
15
16 def test_constructor(self):
17 """Can a PythonExporter be constructed?"""
18 self.exporter_class()
19
20 def test_export(self):
21 """Can a PythonExporter export something?"""
22 (output, resources) = self.exporter_class().from_filename(self._get_notebook())
23 self.assertIn("coding: utf-8", output)
@@ -1,54 +0,0 b''
1 """Tests for RSTExporter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import io
7
8 from IPython import nbformat
9 from IPython.nbformat import v4
10
11 from .base import ExportersTestsBase
12 from ..rst import RSTExporter
13 from IPython.testing.decorators import onlyif_cmds_exist
14
15
16 class TestRSTExporter(ExportersTestsBase):
17 """Tests for RSTExporter"""
18
19 exporter_class = RSTExporter
20 should_include_raw = ['rst']
21
22 def test_constructor(self):
23 """
24 Can a RSTExporter be constructed?
25 """
26 RSTExporter()
27
28
29 @onlyif_cmds_exist('pandoc')
30 def test_export(self):
31 """
32 Can a RSTExporter export something?
33 """
34 (output, resources) = RSTExporter().from_filename(self._get_notebook())
35 assert len(output) > 0
36
37 @onlyif_cmds_exist('pandoc')
38 def test_empty_code_cell(self):
39 """No empty code cells in rst"""
40 nbname = self._get_notebook()
41 with io.open(nbname, encoding='utf8') as f:
42 nb = nbformat.read(f, 4)
43
44 exporter = self.exporter_class()
45
46 (output, resources) = exporter.from_notebook_node(nb)
47 # add an empty code cell
48 nb.cells.append(
49 v4.new_code_cell(source="")
50 )
51 (output2, resources) = exporter.from_notebook_node(nb)
52 # adding an empty code cell shouldn't change output
53 self.assertEqual(output.strip(), output2.strip())
54
@@ -1,45 +0,0 b''
1 """Tests for ScriptExporter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import sys
7
8 from IPython.nbformat import v4
9 from IPython.utils.py3compat import PY3
10
11 from .base import ExportersTestsBase
12 from ..script import ScriptExporter
13
14
15 class TestScriptExporter(ExportersTestsBase):
16 """Tests for ScriptExporter"""
17
18 exporter_class = ScriptExporter
19
20 def test_constructor(self):
21 """Construct ScriptExporter"""
22 e = self.exporter_class()
23
24 def test_export(self):
25 """ScriptExporter can export something"""
26 (output, resources) = self.exporter_class().from_filename(self._get_notebook())
27 assert len(output) > 0
28
29 def test_export_python(self):
30 """delegate to custom exporter from language_info"""
31 exporter = self.exporter_class()
32
33 pynb = v4.new_notebook()
34 (output, resources) = self.exporter_class().from_notebook_node(pynb)
35 self.assertNotIn('# coding: utf-8', output)
36
37 pynb.metadata.language_info = {
38 'name': 'python',
39 'mimetype': 'text/x-python',
40 'nbconvert_exporter': 'python',
41 }
42 (output, resources) = self.exporter_class().from_notebook_node(pynb)
43 self.assertIn('# coding: utf-8', output)
44
45 No newline at end of file
@@ -1,36 +0,0 b''
1 """Tests for SlidesExporter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import ExportersTestsBase
7 from ..slides import SlidesExporter
8
9
10 class TestSlidesExporter(ExportersTestsBase):
11 """Tests for SlidesExporter"""
12
13 exporter_class = SlidesExporter
14 should_include_raw = ['html']
15
16 def test_constructor(self):
17 """
18 Can a SlidesExporter be constructed?
19 """
20 SlidesExporter()
21
22
23 def test_export(self):
24 """
25 Can a SlidesExporter export something?
26 """
27 (output, resources) = SlidesExporter().from_filename(self._get_notebook())
28 assert len(output) > 0
29
30
31 def test_export_reveal(self):
32 """
33 Can a SlidesExporter export using the 'reveal' template?
34 """
35 (output, resources) = SlidesExporter(template_file='slides_reveal').from_filename(self._get_notebook())
36 assert len(output) > 0
@@ -1,108 +0,0 b''
1 """
2 Module with tests for templateexporter.py
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from IPython.config import Config
18
19 from .base import ExportersTestsBase
20 from .cheese import CheesePreprocessor
21 from ..templateexporter import TemplateExporter
22
23
24 #-----------------------------------------------------------------------------
25 # Class
26 #-----------------------------------------------------------------------------
27
28 class TestExporter(ExportersTestsBase):
29 """Contains test functions for exporter.py"""
30
31
32 def test_constructor(self):
33 """
34 Can a TemplateExporter be constructed?
35 """
36 TemplateExporter()
37
38
39 def test_export(self):
40 """
41 Can a TemplateExporter export something?
42 """
43 exporter = self._make_exporter()
44 (output, resources) = exporter.from_filename(self._get_notebook())
45 assert len(output) > 0
46
47
48 def test_extract_outputs(self):
49 """
50 If the ExtractOutputPreprocessor is enabled, are outputs extracted?
51 """
52 config = Config({'ExtractOutputPreprocessor': {'enabled': True}})
53 exporter = self._make_exporter(config=config)
54 (output, resources) = exporter.from_filename(self._get_notebook())
55 assert resources is not None
56 assert isinstance(resources['outputs'], dict)
57 assert len(resources['outputs']) > 0
58
59
60 def test_preprocessor_class(self):
61 """
62 Can a preprocessor be added to the preprocessors list by class type?
63 """
64 config = Config({'Exporter': {'preprocessors': [CheesePreprocessor]}})
65 exporter = self._make_exporter(config=config)
66 (output, resources) = exporter.from_filename(self._get_notebook())
67 assert resources is not None
68 assert resources['cheese'] == 'real'
69
70
71 def test_preprocessor_instance(self):
72 """
73 Can a preprocessor be added to the preprocessors list by instance?
74 """
75 config = Config({'Exporter': {'preprocessors': [CheesePreprocessor()]}})
76 exporter = self._make_exporter(config=config)
77 (output, resources) = exporter.from_filename(self._get_notebook())
78 assert resources is not None
79 assert resources['cheese'] == 'real'
80
81
82 def test_preprocessor_dottedobjectname(self):
83 """
84 Can a preprocessor be added to the preprocessors list by dotted object name?
85 """
86 config = Config({'Exporter': {'preprocessors': ['jupyter_nbconvert.exporters.tests.cheese.CheesePreprocessor']}})
87 exporter = self._make_exporter(config=config)
88 (output, resources) = exporter.from_filename(self._get_notebook())
89 assert resources is not None
90 assert resources['cheese'] == 'real'
91
92
93 def test_preprocessor_via_method(self):
94 """
95 Can a preprocessor be added via the Exporter convenience method?
96 """
97 exporter = self._make_exporter()
98 exporter.register_preprocessor(CheesePreprocessor, enabled=True)
99 (output, resources) = exporter.from_filename(self._get_notebook())
100 assert resources is not None
101 assert resources['cheese'] == 'real'
102
103
104 def _make_exporter(self, config=None):
105 # Create the exporter instance, make sure to set a template name since
106 # the base TemplateExporter doesn't have a template associated with it.
107 exporter = TemplateExporter(config=config, template_file='python')
108 return exporter
@@ -1,7 +0,0 b''
1 from .ansi import *
2 from .citation import *
3 from .datatypefilter import *
4 from .highlight import *
5 from .latex import *
6 from .markdown import *
7 from .strings import *
@@ -1,166 +0,0 b''
1 """Filters for processing ANSI colors within Jinja templates.
2 """
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 import re
16 from IPython.utils import coloransi
17 from IPython.utils.text import strip_ansi
18
19 #-----------------------------------------------------------------------------
20 # Classes and functions
21 #-----------------------------------------------------------------------------
22
23 __all__ = [
24 'strip_ansi',
25 'ansi2html',
26 'single_ansi2latex',
27 'ansi2latex'
28 ]
29
30 ansi_colormap = {
31 '30': 'ansiblack',
32 '31': 'ansired',
33 '32': 'ansigreen',
34 '33': 'ansiyellow',
35 '34': 'ansiblue',
36 '35': 'ansipurple',
37 '36': 'ansicyan',
38 '37': 'ansigrey',
39 '01': 'ansibold',
40 }
41
42 html_escapes = {
43 '<': '&lt;',
44 '>': '&gt;',
45 "'": '&apos;',
46 '"': '&quot;',
47 '`': '&#96;',
48 }
49 ansi_re = re.compile('\x1b' + r'\[([\dA-Fa-f;]*?)m')
50
51 def ansi2html(text):
52 """
53 Convert ansi colors to html colors.
54
55 Parameters
56 ----------
57 text : str
58 Text containing ansi colors to convert to html
59 """
60
61 # do ampersand first
62 text = text.replace('&', '&amp;')
63
64 for c, escape in html_escapes.items():
65 text = text.replace(c, escape)
66
67 m = ansi_re.search(text)
68 opened = False
69 cmds = []
70 opener = ''
71 closer = ''
72 while m:
73 cmds = m.groups()[0].split(';')
74 closer = '</span>' if opened else ''
75
76 # True if there is there more than one element in cmds, *or*
77 # if there is only one but it is not equal to a string of zeroes.
78 opened = len(cmds) > 1 or cmds[0] != '0' * len(cmds[0])
79 classes = []
80 for cmd in cmds:
81 if cmd in ansi_colormap:
82 classes.append(ansi_colormap[cmd])
83
84 if classes:
85 opener = '<span class="%s">' % (' '.join(classes))
86 else:
87 opener = ''
88 text = re.sub(ansi_re, closer + opener, text, 1)
89
90 m = ansi_re.search(text)
91
92 if opened:
93 text += '</span>'
94 return text
95
96
97 def single_ansi2latex(code):
98 """Converts single ansi markup to latex format.
99
100 Return latex code and number of open brackets.
101
102 Accepts codes like '\x1b[1;32m' (bold, red) and the short form '\x1b[32m' (red)
103
104 Colors are matched to those defined in coloransi, which defines colors
105 using the 0, 1 (bold) and 5 (blinking) styles. Styles 1 and 5 are
106 interpreted as bold. All other styles are mapped to 0. Note that in
107 coloransi, a style of 1 does not just mean bold; for example, Brown is
108 "0;33", but Yellow is "1;33". An empty string is returned for unrecognised
109 codes and the "reset" code '\x1b[m'.
110 """
111 components = code.split(';')
112 if len(components) > 1:
113 # Style is digits after '['
114 style = int(components[0].split('[')[-1])
115 color = components[1][:-1]
116 else:
117 style = 0
118 color = components[0][-3:-1]
119
120 # If the style is not normal (0), bold (1) or blinking (5) then treat it as normal
121 if style not in [0, 1, 5]:
122 style = 0
123
124 for name, tcode in coloransi.color_templates:
125 tstyle, tcolor = tcode.split(';')
126 tstyle = int(tstyle)
127 if tstyle == style and tcolor == color:
128 break
129 else:
130 return '', 0
131
132 if style == 5:
133 name = name[5:] # BlinkRed -> Red, etc
134 name = name.lower()
135
136 if style in [1, 5]:
137 return r'\textbf{\color{'+name+'}', 1
138 else:
139 return r'{\color{'+name+'}', 1
140
141 def ansi2latex(text):
142 """Converts ansi formated text to latex version
143
144 based on https://bitbucket.org/birkenfeld/sphinx-contrib/ansi.py
145 """
146 color_pattern = re.compile('\x1b\\[([^m]*)m')
147 last_end = 0
148 openbrack = 0
149 outstring = ''
150 for match in color_pattern.finditer(text):
151 head = text[last_end:match.start()]
152 outstring += head
153 if openbrack:
154 outstring += '}'*openbrack
155 openbrack = 0
156 code = match.group()
157 if not (code == coloransi.TermColors.Normal or openbrack):
158 texform, openbrack = single_ansi2latex(code)
159 outstring += texform
160 last_end = match.end()
161
162 # Add the remainer of the string and THEN close any remaining color brackets.
163 outstring += text[last_end:]
164 if openbrack:
165 outstring += '}'*openbrack
166 return outstring.strip()
@@ -1,111 +0,0 b''
1 """Citation handling for LaTeX output."""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14 from IPython.utils.py3compat import PY3
15 if PY3:
16 from html.parser import HTMLParser
17 else:
18 from HTMLParser import HTMLParser
19
20 #-----------------------------------------------------------------------------
21 # Functions
22 #-----------------------------------------------------------------------------
23
24 __all__ = ['citation2latex']
25
26
27 def citation2latex(s):
28 """Parse citations in Markdown cells.
29
30 This looks for HTML tags having a data attribute names `data-cite`
31 and replaces it by the call to LaTeX cite command. The tranformation
32 looks like this:
33
34 `<cite data-cite="granger">(Granger, 2013)</cite>`
35
36 Becomes
37
38 `\\cite{granger}`
39
40 Any HTML tag can be used, which allows the citations to be formatted
41 in HTML in any manner.
42 """
43 parser = CitationParser()
44 parser.feed(s)
45 parser.close()
46 outtext = u''
47 startpos = 0
48 for citation in parser.citelist:
49 outtext += s[startpos:citation[1]]
50 outtext += '\\cite{%s}'%citation[0]
51 startpos = citation[2] if len(citation)==3 else -1
52 outtext += s[startpos:] if startpos != -1 else ''
53 return outtext
54
55 #-----------------------------------------------------------------------------
56 # Classes
57 #-----------------------------------------------------------------------------
58 class CitationParser(HTMLParser):
59 """Citation Parser
60
61 Replaces html tags with data-cite attribute with respective latex \\cite.
62
63 Inherites from HTMLParser, overrides:
64 - handle_starttag
65 - handle_endtag
66 """
67 # number of open tags
68 opentags = None
69 # list of found citations
70 citelist = None
71 # active citation tag
72 citetag = None
73
74 def __init__(self):
75 self.citelist = []
76 self.opentags = 0
77 HTMLParser.__init__(self)
78
79 def get_offset(self):
80 # Compute startposition in source
81 lin, offset = self.getpos()
82 pos = 0
83 for i in range(lin-1):
84 pos = self.data.find('\n',pos) + 1
85 return pos + offset
86
87 def handle_starttag(self, tag, attrs):
88 # for each tag check if attributes are present and if no citation is active
89 if self.opentags == 0 and len(attrs)>0:
90 for atr, data in attrs:
91 if atr.lower() == 'data-cite':
92 self.citetag = tag
93 self.opentags = 1
94 self.citelist.append([data, self.get_offset()])
95 return
96
97 if tag == self.citetag:
98 # found an open citation tag but not the starting one
99 self.opentags += 1
100
101 def handle_endtag(self, tag):
102 if tag == self.citetag:
103 # found citation tag check if starting one
104 if self.opentags == 1:
105 pos = self.get_offset()
106 self.citelist[-1].append(pos+len(tag)+3)
107 self.opentags -= 1
108
109 def feed(self, data):
110 self.data = data
111 HTMLParser.feed(self, data)
@@ -1,33 +0,0 b''
1 """Filter used to select the first preferred output format available.
2
3 The filter contained in the file allows the converter templates to select
4 the output format that is most valuable to the active export format. The
5 value of the different formats is set via
6 NbConvertBase.display_data_priority
7 """
8 #-----------------------------------------------------------------------------
9 # Copyright (c) 2013, the IPython Development Team.
10 #
11 # Distributed under the terms of the Modified BSD License.
12 #
13 # The full license is in the file COPYING.txt, distributed with this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Classes and functions
18 #-----------------------------------------------------------------------------
19
20 from ..utils.base import NbConvertBase
21
22 __all__ = ['DataTypeFilter']
23
24 class DataTypeFilter(NbConvertBase):
25 """ Returns the preferred display format """
26
27 def __call__(self, output):
28 """ Return the first available format in the priority """
29
30 for fmt in self.display_data_priority:
31 if fmt in output:
32 return [fmt]
33 return []
@@ -1,135 +0,0 b''
1 """
2 Module containing filter functions that allow code to be highlighted
3 from within Jinja templates.
4 """
5
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
8
9 # pygments must not be imported at the module level
10 # because errors should be raised at runtime if it's actually needed,
11 # not import time, when it may not be needed.
12
13 from jupyter_nbconvert.utils.base import NbConvertBase
14 from warnings import warn
15
16 MULTILINE_OUTPUTS = ['text', 'html', 'svg', 'latex', 'javascript', 'json']
17
18 __all__ = [
19 'Highlight2HTML',
20 'Highlight2Latex'
21 ]
22
23 class Highlight2HTML(NbConvertBase):
24 def __init__(self, pygments_lexer=None, **kwargs):
25 self.pygments_lexer = pygments_lexer or 'ipython3'
26 super(Highlight2HTML, self).__init__(**kwargs)
27
28 def _default_language_changed(self, name, old, new):
29 warn('Setting default_language in config is deprecated, '
30 'please use language_info metadata instead.')
31 self.pygments_lexer = new
32
33 def __call__(self, source, language=None, metadata=None):
34 """
35 Return a syntax-highlighted version of the input source as html output.
36
37 Parameters
38 ----------
39 source : str
40 source of the cell to highlight
41 language : str
42 language to highlight the syntax of
43 metadata : NotebookNode cell metadata
44 metadata of the cell to highlight
45 """
46 from pygments.formatters import HtmlFormatter
47
48 if not language:
49 language=self.pygments_lexer
50
51 return _pygments_highlight(source if len(source) > 0 else ' ',
52 # needed to help post processors:
53 HtmlFormatter(cssclass=" highlight hl-"+language),
54 language, metadata)
55
56
57 class Highlight2Latex(NbConvertBase):
58 def __init__(self, pygments_lexer=None, **kwargs):
59 self.pygments_lexer = pygments_lexer or 'ipython3'
60 super(Highlight2Latex, self).__init__(**kwargs)
61
62 def _default_language_changed(self, name, old, new):
63 warn('Setting default_language in config is deprecated, '
64 'please use language_info metadata instead.')
65 self.pygments_lexer = new
66
67 def __call__(self, source, language=None, metadata=None, strip_verbatim=False):
68 """
69 Return a syntax-highlighted version of the input source as latex output.
70
71 Parameters
72 ----------
73 source : str
74 source of the cell to highlight
75 language : str
76 language to highlight the syntax of
77 metadata : NotebookNode cell metadata
78 metadata of the cell to highlight
79 strip_verbatim : bool
80 remove the Verbatim environment that pygments provides by default
81 """
82 from pygments.formatters import LatexFormatter
83 if not language:
84 language=self.pygments_lexer
85
86 latex = _pygments_highlight(source, LatexFormatter(), language, metadata)
87 if strip_verbatim:
88 latex = latex.replace(r'\begin{Verbatim}[commandchars=\\\{\}]' + '\n', '')
89 return latex.replace('\n\\end{Verbatim}\n', '')
90 else:
91 return latex
92
93
94
95 def _pygments_highlight(source, output_formatter, language='ipython', metadata=None):
96 """
97 Return a syntax-highlighted version of the input source
98
99 Parameters
100 ----------
101 source : str
102 source of the cell to highlight
103 output_formatter : Pygments formatter
104 language : str
105 language to highlight the syntax of
106 metadata : NotebookNode cell metadata
107 metadata of the cell to highlight
108 """
109 from pygments import highlight
110 from pygments.lexers import get_lexer_by_name
111 from pygments.util import ClassNotFound
112 from IPython.lib.lexers import IPythonLexer, IPython3Lexer
113
114 # If the cell uses a magic extension language,
115 # use the magic language instead.
116 if language.startswith('ipython') \
117 and metadata \
118 and 'magics_language' in metadata:
119
120 language = metadata['magics_language']
121
122 if language == 'ipython2':
123 lexer = IPythonLexer()
124 elif language == 'ipython3':
125 lexer = IPython3Lexer()
126 else:
127 try:
128 lexer = get_lexer_by_name(language, stripall=True)
129 except ClassNotFound:
130 warn("No lexer found for language %r. Treating as plain text." % language)
131 from pygments.lexers.special import TextLexer
132 lexer = TextLexer()
133
134
135 return highlight(source, lexer, output_formatter)
@@ -1,63 +0,0 b''
1 """Latex filters.
2
3 Module of useful filters for processing Latex within Jinja latex templates.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 import re
17
18 #-----------------------------------------------------------------------------
19 # Globals and constants
20 #-----------------------------------------------------------------------------
21
22 LATEX_RE_SUBS = (
23 (re.compile(r'\.\.\.+'), r'{\\ldots}'),
24 )
25
26 # Latex substitutions for escaping latex.
27 # see: http://stackoverflow.com/questions/16259923/how-can-i-escape-latex-special-characters-inside-django-templates
28
29 LATEX_SUBS = {
30 '&': r'\&',
31 '%': r'\%',
32 '$': r'\$',
33 '#': r'\#',
34 '_': r'\_',
35 '{': r'\{',
36 '}': r'\}',
37 '~': r'\textasciitilde{}',
38 '^': r'\^{}',
39 '\\': r'\textbackslash{}',
40 }
41
42
43 #-----------------------------------------------------------------------------
44 # Functions
45 #-----------------------------------------------------------------------------
46
47 __all__ = ['escape_latex']
48
49 def escape_latex(text):
50 """
51 Escape characters that may conflict with latex.
52
53 Parameters
54 ----------
55 text : str
56 Text containing characters that may conflict with Latex
57 """
58 text = ''.join(LATEX_SUBS.get(c, c) for c in text)
59 for pattern, replacement in LATEX_RE_SUBS:
60 text = pattern.sub(replacement, text)
61
62 return text
63
@@ -1,142 +0,0 b''
1 """Markdown filters
2
3 This file contains a collection of utility filters for dealing with
4 markdown within Jinja templates.
5 """
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
8
9 from __future__ import print_function
10
11 import os
12 import subprocess
13 from io import TextIOWrapper, BytesIO
14
15 try:
16 from .markdown_mistune import markdown2html_mistune
17 except ImportError as e:
18 # store in variable for Python 3
19 _mistune_import_error = e
20 def markdown2html_mistune(source):
21 """mistune is unavailable, raise ImportError"""
22 raise ImportError("markdown2html requires mistune: %s" % _mistune_import_error)
23
24 from jupyter_nbconvert.utils.pandoc import pandoc
25 from jupyter_nbconvert.utils.exceptions import ConversionException
26 from jupyter_nbconvert.utils.version import check_version
27 from IPython.utils.py3compat import cast_bytes
28
29
30 marked = os.path.join(os.path.dirname(__file__), "marked.js")
31 _node = None
32
33 __all__ = [
34 'markdown2html',
35 'markdown2html_pandoc',
36 'markdown2html_marked',
37 'markdown2html_mistune',
38 'markdown2latex',
39 'markdown2rst',
40 ]
41
42 class NodeJSMissing(ConversionException):
43 """Exception raised when node.js is missing."""
44 pass
45
46
47 def markdown2latex(source, markup='markdown', extra_args=None):
48 """Convert a markdown string to LaTeX via pandoc.
49
50 This function will raise an error if pandoc is not installed.
51 Any error messages generated by pandoc are printed to stderr.
52
53 Parameters
54 ----------
55 source : string
56 Input string, assumed to be valid markdown.
57 markup : string
58 Markup used by pandoc's reader
59 default : pandoc extended markdown
60 (see http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown)
61
62 Returns
63 -------
64 out : string
65 Output as returned by pandoc.
66 """
67 return pandoc(source, markup, 'latex', extra_args=extra_args)
68
69
70 def markdown2html_pandoc(source, extra_args=None):
71 """Convert a markdown string to HTML via pandoc"""
72 extra_args = extra_args or ['--mathjax']
73 return pandoc(source, 'markdown', 'html', extra_args=extra_args)
74
75
76 def _find_nodejs():
77 global _node
78 if _node is None:
79 # prefer md2html via marked if node.js >= 0.9.12 is available
80 # node is called nodejs on debian, so try that first
81 _node = 'nodejs'
82 if not _verify_node(_node):
83 _node = 'node'
84 return _node
85
86 def markdown2html_marked(source, encoding='utf-8'):
87 """Convert a markdown string to HTML via marked"""
88 command = [_find_nodejs(), marked]
89 try:
90 p = subprocess.Popen(command,
91 stdin=subprocess.PIPE, stdout=subprocess.PIPE
92 )
93 except OSError as e:
94 raise NodeJSMissing(
95 "The command '%s' returned an error: %s.\n" % (" ".join(command), e) +
96 "Please check that Node.js is installed."
97 )
98 out, _ = p.communicate(cast_bytes(source, encoding))
99 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
100 return out.rstrip('\n')
101
102 # The mistune renderer is the default, because it's simple to depend on it
103 markdown2html = markdown2html_mistune
104
105 def markdown2rst(source, extra_args=None):
106 """Convert a markdown string to ReST via pandoc.
107
108 This function will raise an error if pandoc is not installed.
109 Any error messages generated by pandoc are printed to stderr.
110
111 Parameters
112 ----------
113 source : string
114 Input string, assumed to be valid markdown.
115
116 Returns
117 -------
118 out : string
119 Output as returned by pandoc.
120 """
121 return pandoc(source, 'markdown', 'rst', extra_args=extra_args)
122
123 def _verify_node(cmd):
124 """Verify that the node command exists and is at least the minimum supported
125 version of node.
126
127 Parameters
128 ----------
129 cmd : string
130 Node command to verify (i.e 'node')."""
131 try:
132 p = subprocess.Popen([cmd, '--version'],
133 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
134 out, _ = p.communicate()
135 out = out.decode('utf8', 'replace')
136 except OSError:
137 # Command not found
138 return False
139 if p.returncode:
140 # Command error
141 return False
142 return check_version(out.lstrip('v'), '0.9.12')
@@ -1,122 +0,0 b''
1 """Markdown filters with mistune
2
3 Used from markdown.py
4 """
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 from __future__ import print_function
9
10 import re
11
12 import mistune
13
14 from pygments import highlight
15 from pygments.lexers import get_lexer_by_name
16 from pygments.formatters import HtmlFormatter
17 from pygments.util import ClassNotFound
18
19 from jupyter_nbconvert.filters.strings import add_anchor
20 from jupyter_nbconvert.utils.exceptions import ConversionException
21 from IPython.utils.decorators import undoc
22
23
24 @undoc
25 class MathBlockGrammar(mistune.BlockGrammar):
26 block_math = re.compile(r"^\$\$(.*?)\$\$", re.DOTALL)
27 latex_environment = re.compile(r"^\\begin\{([a-z]*\*?)\}(.*?)\\end\{\1\}",
28 re.DOTALL)
29
30 @undoc
31 class MathBlockLexer(mistune.BlockLexer):
32 default_rules = ['block_math', 'latex_environment'] + mistune.BlockLexer.default_rules
33
34 def __init__(self, rules=None, **kwargs):
35 if rules is None:
36 rules = MathBlockGrammar()
37 super(MathBlockLexer, self).__init__(rules, **kwargs)
38
39 def parse_block_math(self, m):
40 """Parse a $$math$$ block"""
41 self.tokens.append({
42 'type': 'block_math',
43 'text': m.group(1)
44 })
45
46 def parse_latex_environment(self, m):
47 self.tokens.append({
48 'type': 'latex_environment',
49 'name': m.group(1),
50 'text': m.group(2)
51 })
52
53 @undoc
54 class MathInlineGrammar(mistune.InlineGrammar):
55 math = re.compile(r"^\$(.+?)\$")
56 block_math = re.compile(r"^\$\$(.+?)\$\$", re.DOTALL)
57 text = re.compile(r'^[\s\S]+?(?=[\\<!\[_*`~$]|https?://| {2,}\n|$)')
58
59 @undoc
60 class MathInlineLexer(mistune.InlineLexer):
61 default_rules = ['math', 'block_math'] + mistune.InlineLexer.default_rules
62
63 def __init__(self, renderer, rules=None, **kwargs):
64 if rules is None:
65 rules = MathInlineGrammar()
66 super(MathInlineLexer, self).__init__(renderer, rules, **kwargs)
67
68 def output_math(self, m):
69 return self.renderer.inline_math(m.group(1))
70
71 def output_block_math(self, m):
72 return self.renderer.block_math(m.group(1))
73
74 @undoc
75 class MarkdownWithMath(mistune.Markdown):
76 def __init__(self, renderer, **kwargs):
77 if 'inline' not in kwargs:
78 kwargs['inline'] = MathInlineLexer
79 if 'block' not in kwargs:
80 kwargs['block'] = MathBlockLexer
81 super(MarkdownWithMath, self).__init__(renderer, **kwargs)
82
83 def output_block_math(self):
84 return self.renderer.block_math(self.token['text'])
85
86 def output_latex_environment(self):
87 return self.renderer.latex_environment(self.token['name'], self.token['text'])
88
89 @undoc
90 class IPythonRenderer(mistune.Renderer):
91 def block_code(self, code, lang):
92 if lang:
93 try:
94 lexer = get_lexer_by_name(lang, stripall=True)
95 except ClassNotFound:
96 code = lang + '\n' + code
97 lang = None
98
99 if not lang:
100 return '\n<pre><code>%s</code></pre>\n' % \
101 mistune.escape(code)
102
103 formatter = HtmlFormatter()
104 return highlight(code, lexer, formatter)
105
106 def header(self, text, level, raw=None):
107 html = super(IPythonRenderer, self).header(text, level, raw=raw)
108 return add_anchor(html)
109
110 # Pass math through unaltered - mathjax does the rendering in the browser
111 def block_math(self, text):
112 return '$$%s$$' % text
113
114 def latex_environment(self, name, text):
115 return r'\begin{%s}%s\end{%s}' % (name, text, name)
116
117 def inline_math(self, text):
118 return '$%s$' % text
119
120 def markdown2html_mistune(source):
121 """Convert a markdown string to HTML using mistune"""
122 return MarkdownWithMath(renderer=IPythonRenderer()).render(source)
@@ -1,63 +0,0 b''
1 // Node.js script for markdown to html conversion
2 // This applies the same math extraction and marked settings
3 // that we use in the live notebook.
4
5 // IPython static_path dir relative to here:
6 var static_path = __dirname + "/../../html/static/";
7
8 // Excerpt from the example in require.js docs
9 // http://requirejs.org/docs/node.html
10 var requirejs = require('requirejs');
11 requirejs.config({
12 //Pass the top-level main.js/index.js require
13 //function to requirejs so that node modules
14 //are loaded relative to the top-level JS file.
15 nodeRequire: require,
16 baseUrl: static_path,
17 });
18
19 requirejs([
20 'fs',
21 'components/marked/lib/marked',
22 'components/highlight.js/build/highlight.pack',
23 'base/js/utils',
24 'notebook/js/mathjaxutils',
25 ], function(fs, marked, hljs, utils, mathjaxutils) {
26
27 // this is copied from notebook.main. Should it be moved somewhere we can reuse it?
28 marked.setOptions({
29 gfm : true,
30 tables: true,
31 langPrefix: "language-",
32 highlight: function(code, lang) {
33 if (!lang) {
34 // no language, no highlight
35 return code;
36 }
37 var highlighted;
38 try {
39 highlighted = hljs.highlight(lang, code, false);
40 } catch(err) {
41 highlighted = hljs.highlightAuto(code);
42 }
43 return highlighted.value;
44 }
45 });
46
47 // read the markdown from stdin
48 var md='';
49 process.stdin.on("data", function (data) {
50 md += data;
51 });
52
53 // perform the md2html transform once stdin is complete
54 process.stdin.on("end", function () {
55 var text_and_math = mathjaxutils.remove_math(md);
56 var text = text_and_math[0];
57 var math = text_and_math[1];
58 var html = marked.parser(marked.lexer(text));
59 html = mathjaxutils.replace_math(html, math);
60 process.stdout.write(html);
61 });
62
63 });
@@ -1,221 +0,0 b''
1 # coding: utf-8
2 """String filters.
3
4 Contains a collection of useful string manipulation filters for use in Jinja
5 templates.
6 """
7
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
10
11 import os
12 import re
13 import textwrap
14 try:
15 from urllib.parse import quote # Py 3
16 except ImportError:
17 from urllib2 import quote # Py 2
18 from xml.etree import ElementTree
19
20 from IPython.core.interactiveshell import InteractiveShell
21 from IPython.utils import py3compat
22
23
24 __all__ = [
25 'wrap_text',
26 'html2text',
27 'add_anchor',
28 'strip_dollars',
29 'strip_files_prefix',
30 'comment_lines',
31 'get_lines',
32 'ipython2python',
33 'posix_path',
34 'path2url',
35 'add_prompts',
36 'ascii_only',
37 'prevent_list_blocks',
38 ]
39
40
41 def wrap_text(text, width=100):
42 """
43 Intelligently wrap text.
44 Wrap text without breaking words if possible.
45
46 Parameters
47 ----------
48 text : str
49 Text to wrap.
50 width : int, optional
51 Number of characters to wrap to, default 100.
52 """
53
54 split_text = text.split('\n')
55 wrp = map(lambda x:textwrap.wrap(x,width), split_text)
56 wrpd = map('\n'.join, wrp)
57 return '\n'.join(wrpd)
58
59
60 def html2text(element):
61 """extract inner text from html
62
63 Analog of jQuery's $(element).text()
64 """
65 if isinstance(element, py3compat.string_types):
66 try:
67 element = ElementTree.fromstring(element)
68 except Exception:
69 # failed to parse, just return it unmodified
70 return element
71
72 text = element.text or ""
73 for child in element:
74 text += html2text(child)
75 text += (element.tail or "")
76 return text
77
78
79 def add_anchor(html):
80 """Add an anchor-link to an html header
81
82 For use on markdown headings
83 """
84 try:
85 h = ElementTree.fromstring(py3compat.cast_bytes_py2(html, encoding='utf-8'))
86 except Exception:
87 # failed to parse, just return it unmodified
88 return html
89 link = html2text(h).replace(' ', '-')
90 h.set('id', link)
91 a = ElementTree.Element("a", {"class" : "anchor-link", "href" : "#" + link})
92 a.text = u'¶'
93 h.append(a)
94
95 # Known issue of Python3.x, ElementTree.tostring() returns a byte string
96 # instead of a text string. See issue http://bugs.python.org/issue10942
97 # Workaround is to make sure the bytes are casted to a string.
98 return py3compat.decode(ElementTree.tostring(h), 'utf-8')
99
100
101 def add_prompts(code, first='>>> ', cont='... '):
102 """Add prompts to code snippets"""
103 new_code = []
104 code_list = code.split('\n')
105 new_code.append(first + code_list[0])
106 for line in code_list[1:]:
107 new_code.append(cont + line)
108 return '\n'.join(new_code)
109
110
111 def strip_dollars(text):
112 """
113 Remove all dollar symbols from text
114
115 Parameters
116 ----------
117 text : str
118 Text to remove dollars from
119 """
120
121 return text.strip('$')
122
123
124 files_url_pattern = re.compile(r'(src|href)\=([\'"]?)/?files/')
125 markdown_url_pattern = re.compile(r'(!?)\[(?P<caption>.*?)\]\(/?files/(?P<location>.*?)\)')
126
127 def strip_files_prefix(text):
128 """
129 Fix all fake URLs that start with `files/`, stripping out the `files/` prefix.
130 Applies to both urls (for html) and relative paths (for markdown paths).
131
132 Parameters
133 ----------
134 text : str
135 Text in which to replace 'src="files/real...' with 'src="real...'
136 """
137 cleaned_text = files_url_pattern.sub(r"\1=\2", text)
138 cleaned_text = markdown_url_pattern.sub(r'\1[\2](\3)', cleaned_text)
139 return cleaned_text
140
141
142 def comment_lines(text, prefix='# '):
143 """
144 Build a Python comment line from input text.
145
146 Parameters
147 ----------
148 text : str
149 Text to comment out.
150 prefix : str
151 Character to append to the start of each line.
152 """
153
154 #Replace line breaks with line breaks and comment symbols.
155 #Also add a comment symbol at the beginning to comment out
156 #the first line.
157 return prefix + ('\n'+prefix).join(text.split('\n'))
158
159
160 def get_lines(text, start=None,end=None):
161 """
162 Split the input text into separate lines and then return the
163 lines that the caller is interested in.
164
165 Parameters
166 ----------
167 text : str
168 Text to parse lines from.
169 start : int, optional
170 First line to grab from.
171 end : int, optional
172 Last line to grab from.
173 """
174
175 # Split the input into lines.
176 lines = text.split("\n")
177
178 # Return the right lines.
179 return "\n".join(lines[start:end]) #re-join
180
181 def ipython2python(code):
182 """Transform IPython syntax to pure Python syntax
183
184 Parameters
185 ----------
186
187 code : str
188 IPython code, to be transformed to pure Python
189 """
190 shell = InteractiveShell.instance()
191 return shell.input_transformer_manager.transform_cell(code)
192
193 def posix_path(path):
194 """Turn a path into posix-style path/to/etc
195
196 Mainly for use in latex on Windows,
197 where native Windows paths are not allowed.
198 """
199 if os.path.sep != '/':
200 return path.replace(os.path.sep, '/')
201 return path
202
203 def path2url(path):
204 """Turn a file path into a URL"""
205 parts = path.split(os.path.sep)
206 return '/'.join(quote(part) for part in parts)
207
208 def ascii_only(s):
209 """ensure a string is ascii"""
210 s = py3compat.cast_unicode(s)
211 return s.encode('ascii', 'replace').decode('ascii')
212
213 def prevent_list_blocks(s):
214 """
215 Prevent presence of enumerate or itemize blocks in latex headings cells
216 """
217 out = re.sub('(^\s*\d*)\.', '\\1\.', s)
218 out = re.sub('(^\s*)\-', '\\1\-', out)
219 out = re.sub('(^\s*)\+', '\\1\+', out)
220 out = re.sub('(^\s*)\*', '\\1\*', out)
221 return out
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,89 +0,0 b''
1 """
2 Module with tests for ansi filters
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from IPython.utils.coloransi import TermColors
18
19 from ...tests.base import TestsBase
20 from ..ansi import strip_ansi, ansi2html, ansi2latex
21
22
23 #-----------------------------------------------------------------------------
24 # Class
25 #-----------------------------------------------------------------------------
26
27 class TestAnsi(TestsBase):
28 """Contains test functions for ansi.py"""
29
30 def test_strip_ansi(self):
31 """strip_ansi test"""
32 correct_outputs = {
33 '%s%s%s' % (TermColors.Green, TermColors.White, TermColors.Red) : '',
34 'hello%s' % TermColors.Blue: 'hello',
35 'he%s%sllo' % (TermColors.Yellow, TermColors.Cyan) : 'hello',
36 '%shello' % TermColors.Blue : 'hello',
37 '{0}h{0}e{0}l{0}l{0}o{0}'.format(TermColors.Red) : 'hello',
38 'hel%slo' % TermColors.Green : 'hello',
39 'hello' : 'hello'}
40
41 for inval, outval in correct_outputs.items():
42 self._try_strip_ansi(inval, outval)
43
44
45 def _try_strip_ansi(self, inval, outval):
46 self.assertEqual(outval, strip_ansi(inval))
47
48
49 def test_ansi2html(self):
50 """ansi2html test"""
51 correct_outputs = {
52 '%s' % (TermColors.Red) : '<span class="ansired"></span>',
53 'hello%s' % TermColors.Blue: 'hello<span class="ansiblue"></span>',
54 'he%s%sllo' % (TermColors.Green, TermColors.Cyan) : 'he<span class="ansigreen"></span><span class="ansicyan">llo</span>',
55 '%shello' % TermColors.Yellow : '<span class="ansiyellow">hello</span>',
56 '{0}h{0}e{0}l{0}l{0}o{0}'.format(TermColors.White) : '<span class="ansigrey">h</span><span class="ansigrey">e</span><span class="ansigrey">l</span><span class="ansigrey">l</span><span class="ansigrey">o</span><span class="ansigrey"></span>',
57 'hel%slo' % TermColors.Green : 'hel<span class="ansigreen">lo</span>',
58 'hello' : 'hello'}
59
60 for inval, outval in correct_outputs.items():
61 self._try_ansi2html(inval, outval)
62
63
64 def _try_ansi2html(self, inval, outval):
65 self.fuzzy_compare(outval, ansi2html(inval))
66
67
68 def test_ansi2latex(self):
69 """ansi2latex test"""
70 correct_outputs = {
71 '%s' % (TermColors.Red) : r'{\color{red}}',
72 'hello%s' % TermColors.Blue: r'hello{\color{blue}}',
73 'he%s%sllo' % (TermColors.Green, TermColors.Cyan) : r'he{\color{green}}{\color{cyan}llo}',
74 '%shello' % TermColors.Yellow : r'\textbf{\color{yellow}hello}',
75 '{0}h{0}e{0}l{0}l{0}o{0}'.format(TermColors.White) : r'\textbf{\color{white}h}\textbf{\color{white}e}\textbf{\color{white}l}\textbf{\color{white}l}\textbf{\color{white}o}\textbf{\color{white}}',
76 'hel%slo' % TermColors.Green : r'hel{\color{green}lo}',
77 'hello' : 'hello',
78 u'hello\x1b[34mthere\x1b[mworld' : u'hello{\\color{blue}there}world',
79 u'hello\x1b[mthere': u'hellothere',
80 u'hello\x1b[01;34mthere' : u"hello\\textbf{\\color{lightblue}there}",
81 u'hello\x1b[001;34mthere' : u"hello\\textbf{\\color{lightblue}there}"
82 }
83
84 for inval, outval in correct_outputs.items():
85 self._try_ansi2latex(inval, outval)
86
87
88 def _try_ansi2latex(self, inval, outval):
89 self.fuzzy_compare(outval, ansi2latex(inval), case_sensitive=True)
@@ -1,150 +0,0 b''
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2013, the IPython Development Team.
3 #
4 # Distributed under the terms of the Modified BSD License.
5 #
6 # The full license is in the file COPYING.txt, distributed with this software.
7 #-----------------------------------------------------------------------------
8
9 #-----------------------------------------------------------------------------
10 # Imports
11 #-----------------------------------------------------------------------------
12 from ..citation import citation2latex
13 from nose.tools import assert_equal
14
15 #-----------------------------------------------------------------------------
16 # Tests
17 #-----------------------------------------------------------------------------
18 test_md = {"""
19 # My Heading
20
21 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac magna non augue
22 porttitor scelerisque ac id diam <cite data-cite="granger">Granger</cite>. Mauris elit
23 velit, lobortis sed interdum at, vestibulum vitae libero <strong data-cite="fperez">Perez</strong>.
24 Lorem ipsum dolor sit amet, consectetur adipiscing elit
25 <em data-cite="takluyver">Thomas</em>. Quisque iaculis ligula ut ipsum mattis viverra.
26
27 <p>Here is a plain paragraph that should be unaffected. It contains simple
28 relations like 1<2 & 4>5.</p>
29
30 * One <cite data-cite="jdfreder">Jonathan</cite>.
31 * Two <cite data-cite="carreau">Matthias</cite>.
32 * Three <cite data-cite="ivanov">Paul</cite>.
33 """: """
34 # My Heading
35
36 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac magna non augue
37 porttitor scelerisque ac id diam \cite{granger}. Mauris elit
38 velit, lobortis sed interdum at, vestibulum vitae libero \cite{fperez}.
39 Lorem ipsum dolor sit amet, consectetur adipiscing elit
40 \cite{takluyver}. Quisque iaculis ligula ut ipsum mattis viverra.
41
42 <p>Here is a plain paragraph that should be unaffected. It contains simple
43 relations like 1<2 & 4>5.</p>
44
45 * One \cite{jdfreder}.
46 * Two \cite{carreau}.
47 * Three \cite{ivanov}.
48 """,
49
50 # No citations
51 r"""The quick brown fox jumps over the lazy dog.""":
52 r"""The quick brown fox jumps over the lazy dog.""",
53
54 # Simple inline
55 r"""Foo <cite data-cite=asdf>Text</cite> bar""":
56 r"""Foo \cite{asdf} bar""",
57
58 # Multiline
59 r"""<cite data-cite=ewqr>Text
60 </cite>Foo""":
61 r"""\cite{ewqr}Foo""",
62
63 # Nested tags
64 r"""<div><div data-cite=Foo><div>Text</div></div></div> Bar""":
65 r"""<div>\cite{Foo}</div> Bar""",
66
67 # Including Maths
68 r"""Foo $3*2*1$ <div data-cite=Foo>Text</div> Bar""":
69 r"""Foo $3*2*1$ \cite{Foo} Bar""",
70
71 # Missing end tag
72 r"""<cite data-cite=asdf>Test Foo""":
73 r"""\cite{asdf}""",
74
75 r"""<cite data-cite=asdf><cite>Test Foo""":
76 r"""\cite{asdf}""",
77
78 r"""<cite data-cite=asdf><cite>Test</cite> Foo""":
79 r"""\cite{asdf}""",
80
81 # Multiple arguments
82 r"""<cite width=qwer data-cite=asdf>Test</cite> Foo""":
83 r"""\cite{asdf} Foo""",
84
85 # Wrong capitalization
86 r"""<CITE data-cite=asdf>Test</cite> Foo""":
87 r"""\cite{asdf} Foo""",
88
89 r"""<cite DATA-CITE=asdf>Test</cite> Foo""":
90 r"""\cite{asdf} Foo""",
91
92 # Wrong end tag
93 r"""<asd data-cite=wer> ksjfs </asdf> sdf ds """:
94 r"""\cite{wer}""",
95
96 r"""<asd data-cite=wer>""":
97 r"""\cite{wer}""",
98
99 # Invalid tag names
100 r"""<frog> <foo data-cite=wer></foo>""":
101 r"""<frog> \cite{wer}""",
102
103 # Non-nested tags
104 r"""<strong> <h1> <cite data-cite=asdf></cite>Test</strong> Foo </h1>""":
105 r"""<strong> <h1> \cite{asdf}Test</strong> Foo </h1>""",
106
107 # LXML errors
108 r"""Foo
109 \begin{eqnarray}
110 1 & <cite data-cite=bar>bar1</cite> \\
111 3 & 4 \\
112 \end{eqnarray}""":
113 r"""Foo
114 \begin{eqnarray}
115 1 & \cite{bar} \\
116 3 & 4 \\
117 \end{eqnarray}""",
118
119 r"""
120 1<2 is true, but 3>4 is false.
121
122 $1<2$ is true, but $3>4$ is false.
123
124 1<2 it is even worse if it is alone in a line.""":
125 r"""
126 1<2 is true, but 3>4 is false.
127
128 $1<2$ is true, but $3>4$ is false.
129
130 1<2 it is even worse if it is alone in a line.""",
131
132 r"""
133 1 < 2 is true, but 3 > 4 is false
134
135 $1 < 2$ is true, but $3 > 4$ is false
136
137 1 < 2 it is even worse if it is alone in a line.
138 """:
139 r"""
140 1 < 2 is true, but 3 > 4 is false
141
142 $1 < 2$ is true, but $3 > 4$ is false
143
144 1 < 2 it is even worse if it is alone in a line.
145 """}
146
147 def test_citation2latex():
148 """Are citations parsed properly?"""
149 for input, output in test_md.items():
150 yield (assert_equal, citation2latex(input), output)
@@ -1,27 +0,0 b''
1 """Module with tests for DataTypeFilter"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from ...tests.base import TestsBase
7 from ..datatypefilter import DataTypeFilter
8
9
10 class TestDataTypeFilter(TestsBase):
11 """Contains test functions for datatypefilter.py"""
12
13 def test_constructor(self):
14 """Can an instance of a DataTypeFilter be created?"""
15 DataTypeFilter()
16
17 def test_junk_types(self):
18 """Can the DataTypeFilter pickout a useful type from a list of junk types?"""
19 filter = DataTypeFilter()
20 assert "image/png" in filter(["hair", "water", "image/png", "rock"])
21 assert "application/pdf" in filter(["application/pdf", "hair", "water", "png", "rock"])
22 self.assertEqual(filter(["hair", "water", "rock"]), [])
23
24 def test_null(self):
25 """Will the DataTypeFilter fail if no types are passed in?"""
26 filter = DataTypeFilter()
27 self.assertEqual(filter([]), [])
@@ -1,90 +0,0 b''
1 """
2 Module with tests for Highlight
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from ...tests.base import TestsBase
18 from ..highlight import Highlight2HTML, Highlight2Latex
19 from IPython.config import Config
20 import xml
21
22 #-----------------------------------------------------------------------------
23 # Class
24 #-----------------------------------------------------------------------------
25
26 highlight2html = Highlight2HTML()
27 highlight2latex = Highlight2Latex()
28 highlight2html_ruby = Highlight2HTML(pygments_lexer='ruby')
29
30 class TestHighlight(TestsBase):
31 """Contains test functions for highlight.py"""
32
33 #Hello world test, magics test, blank string test
34 tests = [
35 """
36 #Hello World Example
37
38 import foo
39
40 def say(text):
41 foo.bar(text)
42
43 end
44
45 say('Hello World!')
46 """,
47 """
48 %%pylab
49 plot(x,y, 'r')
50 """
51 ]
52
53 tokens = [
54 ['Hello World Example', 'say', 'text', 'import', 'def'],
55 ['pylab', 'plot']]
56
57
58 def test_highlight2html(self):
59 """highlight2html test"""
60 for index, test in enumerate(self.tests):
61 self._try_highlight(highlight2html, test, self.tokens[index])
62
63
64 def test_highlight2latex(self):
65 """highlight2latex test"""
66 for index, test in enumerate(self.tests):
67 self._try_highlight(highlight2latex, test, self.tokens[index])
68
69 def test_parse_html_many_lang(self):
70
71 ht = highlight2html(self.tests[0])
72 rb = highlight2html_ruby(self.tests[0])
73
74 for lang,tkns in [
75 ( ht, ('def', )),
76 ( rb, ('def','end' ) )
77 ]:
78 print(tkns)
79 print(lang)
80 root = xml.etree.ElementTree.fromstring(lang)
81 self.assertEqual(self._extract_tokens(root,'k'), set(tkns))
82
83 def _extract_tokens(self, root, cls):
84 return set(map(lambda x:x.text,root.findall(".//*[@class='"+cls+"']")))
85
86 def _try_highlight(self, method, test, tokens):
87 """Try highlighting source, look for key tokens"""
88 results = method(test)
89 for token in tokens:
90 assert token in results
@@ -1,43 +0,0 b''
1 """
2 Module with tests for Latex
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from ...tests.base import TestsBase
18 from ..latex import escape_latex
19
20
21 #-----------------------------------------------------------------------------
22 # Class
23 #-----------------------------------------------------------------------------
24
25 class TestLatex(TestsBase):
26
27
28 def test_escape_latex(self):
29 """escape_latex test"""
30 tests = [
31 (r'How are \you doing today?', r'How are \textbackslash{}you doing today?'),
32 (r'\escapechar=`\A\catcode`\|=0 |string|foo', r'\textbackslash{}escapechar=`\textbackslash{}A\textbackslash{}catcode`\textbackslash{}|=0 |string|foo'),
33 (r'# $ % & ~ _ ^ \ { }', r'\# \$ \% \& \textasciitilde{} \_ \^{} \textbackslash{} \{ \}'),
34 ('...', r'{\ldots}'),
35 ('','')]
36
37 for test in tests:
38 self._try_escape_latex(test[0], test[1])
39
40
41 def _try_escape_latex(self, test, result):
42 """Try to remove latex from string"""
43 self.assertEqual(escape_latex(test), result)
@@ -1,186 +0,0 b''
1 # coding: utf-8
2 """Tests for conversions from markdown to other formats"""
3
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import re
8 from copy import copy
9
10 from IPython.utils.py3compat import string_types
11 from IPython.testing import decorators as dec
12
13 from ...tests.base import TestsBase
14 from ..markdown import markdown2latex, markdown2html, markdown2rst
15
16 from jinja2 import Environment
17
18 class TestMarkdown(TestsBase):
19
20 tests = [
21 '*test',
22 '**test',
23 '*test*',
24 '_test_',
25 '__test__',
26 '__*test*__',
27 '**test**',
28 '#test',
29 '##test',
30 'test\n----',
31 'test [link](https://google.com/)',
32 ]
33
34 tokens = [
35 '*test',
36 '**test',
37 'test',
38 'test',
39 'test',
40 'test',
41 'test',
42 'test',
43 'test',
44 'test',
45 ('test', 'https://google.com/'),
46 ]
47
48
49 @dec.onlyif_cmds_exist('pandoc')
50 def test_markdown2latex(self):
51 """markdown2latex test"""
52 for index, test in enumerate(self.tests):
53 self._try_markdown(markdown2latex, test, self.tokens[index])
54
55 @dec.onlyif_cmds_exist('pandoc')
56 def test_markdown2latex_markup(self):
57 """markdown2latex with markup kwarg test"""
58 # This string should be passed through unaltered with pandoc's
59 # markdown_strict reader
60 s = '1) arabic number with parenthesis'
61 self.assertEqual(markdown2latex(s, markup='markdown_strict'), s)
62 # This string should be passed through unaltered with pandoc's
63 # markdown_strict+tex_math_dollars reader
64 s = r'$\alpha$ latex math'
65 # sometimes pandoc uses $math$, sometimes it uses \(math\)
66 expected = re.compile(r'(\$|\\\()\\alpha(\$|\\\)) latex math')
67 try:
68 # py3
69 assertRegex = self.assertRegex
70 except AttributeError:
71 # py2
72 assertRegex = self.assertRegexpMatches
73 assertRegex(
74 markdown2latex(s, markup='markdown_strict+tex_math_dollars'),
75 expected)
76
77 @dec.onlyif_cmds_exist('pandoc')
78 def test_pandoc_extra_args(self):
79 # pass --no-wrap
80 s = '\n'.join([
81 "#latex {{long_line | md2l('markdown', ['--no-wrap'])}}",
82 "#rst {{long_line | md2r(['--columns', '5'])}}",
83 ])
84 long_line = ' '.join(['long'] * 30)
85 env = Environment()
86 env.filters.update({
87 'md2l': markdown2latex,
88 'md2r': markdown2rst,
89 })
90 tpl = env.from_string(s)
91 rendered = tpl.render(long_line=long_line)
92 _, latex, rst = rendered.split('#')
93
94 self.assertEqual(latex.strip(), 'latex %s' % long_line)
95 self.assertEqual(rst.strip(), 'rst %s' % long_line.replace(' ', '\n'))
96
97 def test_markdown2html(self):
98 """markdown2html test"""
99 for index, test in enumerate(self.tests):
100 self._try_markdown(markdown2html, test, self.tokens[index])
101
102 def test_markdown2html_heading_anchors(self):
103 for md, tokens in [
104 ('# test',
105 ('<h1', '>test', 'id="test"', u'&#182;</a>', "anchor-link")
106 ),
107 ('###test head space',
108 ('<h3', '>test head space', 'id="test-head-space"', u'&#182;</a>', "anchor-link")
109 )
110 ]:
111 self._try_markdown(markdown2html, md, tokens)
112
113 def test_markdown2html_math(self):
114 # Mathematical expressions should be passed through unaltered
115 cases = [("\\begin{equation*}\n"
116 "\\left( \\sum_{k=1}^n a_k b_k \\right)^2 \\leq \\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)\n"
117 "\\end{equation*}"),
118 ("$$\n"
119 "a = 1 *3* 5\n"
120 "$$"),
121 "$ a = 1 *3* 5 $",
122 ]
123 for case in cases:
124 self.assertIn(case, markdown2html(case))
125
126 def test_markdown2html_math_mixed(self):
127 """ensure markdown between inline and inline-block math"""
128 case = """The entries of $C$ are given by the exact formula:
129 $$
130 C_{ik} = \sum_{j=1}^n A_{ij} B_{jk}
131 $$
132 but there are many ways to _implement_ this computation. $\approx 2mnp$ flops"""
133 self._try_markdown(markdown2html, case,
134 case.replace("_implement_", "<em>implement</em>"))
135
136 def test_markdown2html_math_paragraph(self):
137 """these should all parse without modification"""
138 cases = [
139 # https://github.com/ipython/ipython/issues/6724
140 """Water that is stored in $t$, $s_t$, must equal the storage content of the previous stage,
141 $s_{t-1}$, plus a stochastic inflow, $I_t$, minus what is being released in $t$, $r_t$.
142 With $s_0$ defined as the initial storage content in $t=1$, we have""",
143 # https://github.com/jupyter/nbviewer/issues/420
144 """$C_{ik}$
145 $$
146 C_{ik} = \sum_{j=1}
147 $$
148 $C_{ik}$""",
149 """$m$
150 $$
151 C = \begin{pmatrix}
152 0 & 0 & 0 & \cdots & 0 & 0 & -c_0 \\
153 0 & 0 & 0 & \cdots & 0 & 1 & -c_{m-1}
154 \end{pmatrix}
155 $$
156 $x^m$""",
157 """$r=\overline{1,n}$
158 $$ {\bf
159 b}_{i}^{r}(t)=(1-t)\,{\bf b}_{i}^{r-1}(t)+t\,{\bf b}_{i+1}^{r-1}(t),\:
160 i=\overline{0,n-r}, $$
161 i.e. the $i^{th}$"""
162 ]
163
164 for case in cases:
165 self.assertIn(case, markdown2html(case))
166
167 @dec.onlyif_cmds_exist('pandoc')
168 def test_markdown2rst(self):
169 """markdown2rst test"""
170
171 #Modify token array for rst, escape asterik
172 tokens = copy(self.tokens)
173 tokens[0] = r'\*test'
174 tokens[1] = r'\*\*test'
175
176 for index, test in enumerate(self.tests):
177 self._try_markdown(markdown2rst, test, tokens[index])
178
179
180 def _try_markdown(self, method, test, tokens):
181 results = method(test)
182 if isinstance(tokens, string_types):
183 assert tokens in results
184 else:
185 for token in tokens:
186 assert token in results
@@ -1,165 +0,0 b''
1 """
2 Module with tests for Strings
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 import os
17
18 from ...tests.base import TestsBase
19 from ..strings import (wrap_text, html2text, add_anchor, strip_dollars,
20 strip_files_prefix, get_lines, comment_lines, ipython2python, posix_path,
21 add_prompts, prevent_list_blocks
22 )
23
24
25 #-----------------------------------------------------------------------------
26 # Class
27 #-----------------------------------------------------------------------------
28
29 class TestStrings(TestsBase):
30
31 def test_wrap_text(self):
32 """wrap_text test"""
33 test_text = """
34 Tush! never tell me; I take it much unkindly
35 That thou, Iago, who hast had my purse
36 As if the strings were thine, shouldst know of this.
37 """
38 for length in [30,5,1]:
39 self._confirm_wrap_text(test_text, length)
40
41
42 def _confirm_wrap_text(self, text, length):
43 for line in wrap_text(text, length).split('\n'):
44 assert len(line) <= length
45
46
47 def test_html2text(self):
48 """html2text test"""
49 #TODO: More tests
50 self.assertEqual(html2text('<name>joe</name>'), 'joe')
51
52
53 def test_add_anchor(self):
54 """add_anchor test"""
55 #TODO: More tests
56 results = add_anchor('<b>Hello World!</b>')
57 assert 'Hello World!' in results
58 assert 'id="' in results
59 assert 'class="anchor-link"' in results
60 assert '<b' in results
61 assert '</b>' in results
62
63 def test_add_anchor_fail(self):
64 """add_anchor does nothing when it fails"""
65 html = '<h1>Hello <br>World!</h1>'
66 results = add_anchor(html)
67 self.assertEqual(html, results)
68
69 def test_strip_dollars(self):
70 """strip_dollars test"""
71 tests = [
72 ('', ''),
73 ('$$', ''),
74 ('$H$', 'H'),
75 ('$He', 'He'),
76 ('H$el', 'H$el'),
77 ('Hell$', 'Hell'),
78 ('Hello', 'Hello'),
79 ('W$o$rld', 'W$o$rld')]
80 for test in tests:
81 self._try_strip_dollars(test[0], test[1])
82
83
84 def _try_strip_dollars(self, test, result):
85 self.assertEqual(strip_dollars(test), result)
86
87
88 def test_strip_files_prefix(self):
89 """strip_files_prefix test"""
90 tests = [
91 ('', ''),
92 ('/files', '/files'),
93 ('test="/files"', 'test="/files"'),
94 ('My files are in `files/`', 'My files are in `files/`'),
95 ('<a href="files/test.html">files/test.html</a>', '<a href="test.html">files/test.html</a>'),
96 ('<a href="/files/test.html">files/test.html</a>', '<a href="test.html">files/test.html</a>'),
97 ("<a href='files/test.html'>files/test.html</a>", "<a href='test.html'>files/test.html</a>"),
98 ('<img src="files/url/location.gif">', '<img src="url/location.gif">'),
99 ('<img src="/files/url/location.gif">', '<img src="url/location.gif">'),
100 ('hello![caption]', 'hello![caption]'),
101 ('hello![caption](/url/location.gif)', 'hello![caption](/url/location.gif)'),
102 ('hello![caption](url/location.gif)', 'hello![caption](url/location.gif)'),
103 ('hello![caption](url/location.gif)', 'hello![caption](url/location.gif)'),
104 ('hello![caption](files/url/location.gif)', 'hello![caption](url/location.gif)'),
105 ('hello![caption](/files/url/location.gif)', 'hello![caption](url/location.gif)'),
106 ('hello [text](/files/url/location.gif)', 'hello [text](url/location.gif)'),
107 ('hello [text space](files/url/location.gif)', 'hello [text space](url/location.gif)'),
108 ]
109 for test in tests:
110 self._try_files_prefix(test[0], test[1])
111
112
113 def _try_files_prefix(self, test, result):
114 self.assertEqual(strip_files_prefix(test), result)
115
116
117 def test_comment_lines(self):
118 """comment_lines test"""
119 for line in comment_lines('hello\nworld\n!').split('\n'):
120 assert line.startswith('# ')
121 for line in comment_lines('hello\nworld\n!', 'beep').split('\n'):
122 assert line.startswith('beep')
123
124
125 def test_get_lines(self):
126 """get_lines test"""
127 text = "hello\nworld\n!"
128 self.assertEqual(get_lines(text, start=1), "world\n!")
129 self.assertEqual(get_lines(text, end=2), "hello\nworld")
130 self.assertEqual(get_lines(text, start=2, end=5), "!")
131 self.assertEqual(get_lines(text, start=-2), "world\n!")
132
133
134 def test_ipython2python(self):
135 """ipython2python test"""
136 #TODO: More tests
137 results = ipython2python(u'%%pylab\nprint("Hello-World")').replace("u'", "'")
138 self.fuzzy_compare(results, u"get_ipython().run_cell_magic('pylab', '', 'print(\"Hello-World\")')",
139 ignore_spaces=True, ignore_newlines=True)
140
141 def test_posix_path(self):
142 """posix_path test"""
143 path_list = ['foo', 'bar']
144 expected = '/'.join(path_list)
145 native = os.path.join(*path_list)
146 filtered = posix_path(native)
147 self.assertEqual(filtered, expected)
148
149 def test_add_prompts(self):
150 """add_prompts test"""
151 text1 = """for i in range(10):\n i += 1\n print i"""
152 text2 = """>>> for i in range(10):\n... i += 1\n... print i"""
153 self.assertEqual(text2, add_prompts(text1))
154
155 def test_prevent_list_blocks(self):
156 """prevent_list_blocks test"""
157 tests = [
158 ('1. arabic point', '1\\. arabic point'),
159 ('* bullet asterisk', '\\* bullet asterisk'),
160 ('+ bullet Plus Sign', '\\+ bullet Plus Sign'),
161 ('- bullet Hyphen-Minus', '\\- bullet Hyphen-Minus'),
162 (' 1. spaces + arabic point', ' 1\\. spaces + arabic point'),
163 ]
164 for test in tests:
165 self.assertEqual(prevent_list_blocks(test[0]), test[1])
@@ -1,407 +0,0 b''
1 #!/usr/bin/env python
2 """NbConvert is a utility for conversion of .ipynb files.
3
4 Command-line interface for the NbConvert conversion utility.
5 """
6
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
9
10 from __future__ import print_function
11
12 import logging
13 import sys
14 import os
15 import glob
16
17 from IPython.core.application import BaseIPythonApplication, base_aliases, base_flags
18 from IPython.core.profiledir import ProfileDir
19 from IPython.config import catch_config_error, Configurable
20 from IPython.utils.traitlets import (
21 Unicode, List, Instance, DottedObjectName, Type, CaselessStrEnum, Bool,
22 )
23 from IPython.utils.importstring import import_item
24
25 from .exporters.export import get_export_names, exporter_map
26 from jupyter_nbconvert import exporters, preprocessors, writers, postprocessors
27 from .utils.base import NbConvertBase
28 from .utils.exceptions import ConversionException
29
30 #-----------------------------------------------------------------------------
31 #Classes and functions
32 #-----------------------------------------------------------------------------
33
34 class DottedOrNone(DottedObjectName):
35 """
36 A string holding a valid dotted object name in Python, such as A.b3._c
37 Also allows for None type."""
38
39 default_value = u''
40
41 def validate(self, obj, value):
42 if value is not None and len(value) > 0:
43 return super(DottedOrNone, self).validate(obj, value)
44 else:
45 return value
46
47 nbconvert_aliases = {}
48 nbconvert_aliases.update(base_aliases)
49 nbconvert_aliases.update({
50 'to' : 'NbConvertApp.export_format',
51 'template' : 'TemplateExporter.template_file',
52 'writer' : 'NbConvertApp.writer_class',
53 'post': 'NbConvertApp.postprocessor_class',
54 'output': 'NbConvertApp.output_base',
55 'reveal-prefix': 'RevealHelpPreprocessor.url_prefix',
56 'nbformat': 'NotebookExporter.nbformat_version',
57 })
58
59 nbconvert_flags = {}
60 nbconvert_flags.update(base_flags)
61 nbconvert_flags.update({
62 'execute' : (
63 {'ExecutePreprocessor' : {'enabled' : True}},
64 "Execute the notebook prior to export."
65 ),
66 'stdout' : (
67 {'NbConvertApp' : {'writer_class' : "StdoutWriter"}},
68 "Write notebook output to stdout instead of files."
69 ),
70 'inplace' : (
71 {
72 'NbConvertApp' : {'use_output_suffix' : False},
73 'FilesWriter': {'build_directory': ''}
74 },
75 """Run nbconvert in place, overwriting the existing notebook (only
76 relevant when converting to notebook format)"""
77 )
78 })
79
80
81 class NbConvertApp(BaseIPythonApplication):
82 """Application used to convert from notebook file type (``*.ipynb``)"""
83
84 name = 'ipython-nbconvert'
85 aliases = nbconvert_aliases
86 flags = nbconvert_flags
87
88 def _log_level_default(self):
89 return logging.INFO
90
91 def _classes_default(self):
92 classes = [NbConvertBase, ProfileDir]
93 for pkg in (exporters, preprocessors, writers, postprocessors):
94 for name in dir(pkg):
95 cls = getattr(pkg, name)
96 if isinstance(cls, type) and issubclass(cls, Configurable):
97 classes.append(cls)
98
99 return classes
100
101 description = Unicode(
102 u"""This application is used to convert notebook files (*.ipynb)
103 to various other formats.
104
105 WARNING: THE COMMANDLINE INTERFACE MAY CHANGE IN FUTURE RELEASES.""")
106
107 output_base = Unicode('', config=True, help='''overwrite base name use for output files.
108 can only be used when converting one notebook at a time.
109 ''')
110
111 use_output_suffix = Bool(
112 True,
113 config=True,
114 help="""Whether to apply a suffix prior to the extension (only relevant
115 when converting to notebook format). The suffix is determined by
116 the exporter, and is usually '.nbconvert'.""")
117
118 examples = Unicode(u"""
119 The simplest way to use nbconvert is
120
121 > ipython nbconvert mynotebook.ipynb
122
123 which will convert mynotebook.ipynb to the default format (probably HTML).
124
125 You can specify the export format with `--to`.
126 Options include {0}
127
128 > ipython nbconvert --to latex mynotebook.ipynb
129
130 Both HTML and LaTeX support multiple output templates. LaTeX includes
131 'base', 'article' and 'report'. HTML includes 'basic' and 'full'. You
132 can specify the flavor of the format used.
133
134 > ipython nbconvert --to html --template basic mynotebook.ipynb
135
136 You can also pipe the output to stdout, rather than a file
137
138 > ipython nbconvert mynotebook.ipynb --stdout
139
140 PDF is generated via latex
141
142 > ipython nbconvert mynotebook.ipynb --to pdf
143
144 You can get (and serve) a Reveal.js-powered slideshow
145
146 > ipython nbconvert myslides.ipynb --to slides --post serve
147
148 Multiple notebooks can be given at the command line in a couple of
149 different ways:
150
151 > ipython nbconvert notebook*.ipynb
152 > ipython nbconvert notebook1.ipynb notebook2.ipynb
153
154 or you can specify the notebooks list in a config file, containing::
155
156 c.NbConvertApp.notebooks = ["my_notebook.ipynb"]
157
158 > ipython nbconvert --config mycfg.py
159 """.format(get_export_names()))
160
161 # Writer specific variables
162 writer = Instance('jupyter_nbconvert.writers.base.WriterBase',
163 help="""Instance of the writer class used to write the
164 results of the conversion.""", allow_none=True)
165 writer_class = DottedObjectName('FilesWriter', config=True,
166 help="""Writer class used to write the
167 results of the conversion""")
168 writer_aliases = {'fileswriter': 'jupyter_nbconvert.writers.files.FilesWriter',
169 'debugwriter': 'jupyter_nbconvert.writers.debug.DebugWriter',
170 'stdoutwriter': 'jupyter_nbconvert.writers.stdout.StdoutWriter'}
171 writer_factory = Type(allow_none=True)
172
173 def _writer_class_changed(self, name, old, new):
174 if new.lower() in self.writer_aliases:
175 new = self.writer_aliases[new.lower()]
176 self.writer_factory = import_item(new)
177
178 # Post-processor specific variables
179 postprocessor = Instance('jupyter_nbconvert.postprocessors.base.PostProcessorBase',
180 help="""Instance of the PostProcessor class used to write the
181 results of the conversion.""", allow_none=True)
182
183 postprocessor_class = DottedOrNone(config=True,
184 help="""PostProcessor class used to write the
185 results of the conversion""")
186 postprocessor_aliases = {'serve': 'jupyter_nbconvert.postprocessors.serve.ServePostProcessor'}
187 postprocessor_factory = Type(allow_none=True)
188
189 def _postprocessor_class_changed(self, name, old, new):
190 if new.lower() in self.postprocessor_aliases:
191 new = self.postprocessor_aliases[new.lower()]
192 if new:
193 self.postprocessor_factory = import_item(new)
194
195
196 # Other configurable variables
197 export_format = CaselessStrEnum(get_export_names(),
198 default_value="html",
199 config=True,
200 help="""The export format to be used."""
201 )
202
203 notebooks = List([], config=True, help="""List of notebooks to convert.
204 Wildcards are supported.
205 Filenames passed positionally will be added to the list.
206 """)
207
208 @catch_config_error
209 def initialize(self, argv=None):
210 self.init_syspath()
211 super(NbConvertApp, self).initialize(argv)
212 self.init_notebooks()
213 self.init_writer()
214 self.init_postprocessor()
215
216
217
218 def init_syspath(self):
219 """
220 Add the cwd to the sys.path ($PYTHONPATH)
221 """
222 sys.path.insert(0, os.getcwd())
223
224
225 def init_notebooks(self):
226 """Construct the list of notebooks.
227 If notebooks are passed on the command-line,
228 they override notebooks specified in config files.
229 Glob each notebook to replace notebook patterns with filenames.
230 """
231
232 # Specifying notebooks on the command-line overrides (rather than adds)
233 # the notebook list
234 if self.extra_args:
235 patterns = self.extra_args
236 else:
237 patterns = self.notebooks
238
239 # Use glob to replace all the notebook patterns with filenames.
240 filenames = []
241 for pattern in patterns:
242
243 # Use glob to find matching filenames. Allow the user to convert
244 # notebooks without having to type the extension.
245 globbed_files = glob.glob(pattern)
246 globbed_files.extend(glob.glob(pattern + '.ipynb'))
247 if not globbed_files:
248 self.log.warn("pattern %r matched no files", pattern)
249
250 for filename in globbed_files:
251 if not filename in filenames:
252 filenames.append(filename)
253 self.notebooks = filenames
254
255 def init_writer(self):
256 """
257 Initialize the writer (which is stateless)
258 """
259 self._writer_class_changed(None, self.writer_class, self.writer_class)
260 self.writer = self.writer_factory(parent=self)
261 if hasattr(self.writer, 'build_directory') and self.writer.build_directory != '':
262 self.use_output_suffix = False
263
264 def init_postprocessor(self):
265 """
266 Initialize the postprocessor (which is stateless)
267 """
268 self._postprocessor_class_changed(None, self.postprocessor_class,
269 self.postprocessor_class)
270 if self.postprocessor_factory:
271 self.postprocessor = self.postprocessor_factory(parent=self)
272
273 def start(self):
274 """
275 Ran after initialization completed
276 """
277 super(NbConvertApp, self).start()
278 self.convert_notebooks()
279
280 def init_single_notebook_resources(self, notebook_filename):
281 """Step 1: Initialize resources
282
283 This intializes the resources dictionary for a single notebook. This
284 method should return the resources dictionary, and MUST include the
285 following keys:
286
287 - profile_dir: the location of the profile directory
288 - unique_key: the notebook name
289 - output_files_dir: a directory where output files (not including
290 the notebook itself) should be saved
291
292 """
293
294 # Get a unique key for the notebook and set it in the resources object.
295 basename = os.path.basename(notebook_filename)
296 notebook_name = basename[:basename.rfind('.')]
297 if self.output_base:
298 # strip duplicate extension from output_base, to avoid Basname.ext.ext
299 if getattr(self.exporter, 'file_extension', False):
300 base, ext = os.path.splitext(self.output_base)
301 if ext == self.exporter.file_extension:
302 self.output_base = base
303 notebook_name = self.output_base
304
305 self.log.debug("Notebook name is '%s'", notebook_name)
306
307 # first initialize the resources we want to use
308 resources = {}
309 resources['profile_dir'] = self.profile_dir.location
310 resources['unique_key'] = notebook_name
311 resources['output_files_dir'] = '%s_files' % notebook_name
312
313 return resources
314
315 def export_single_notebook(self, notebook_filename, resources):
316 """Step 2: Export the notebook
317
318 Exports the notebook to a particular format according to the specified
319 exporter. This function returns the output and (possibly modified)
320 resources from the exporter.
321
322 """
323 try:
324 output, resources = self.exporter.from_filename(notebook_filename, resources=resources)
325 except ConversionException:
326 self.log.error("Error while converting '%s'", notebook_filename, exc_info=True)
327 self.exit(1)
328
329 return output, resources
330
331 def write_single_notebook(self, output, resources):
332 """Step 3: Write the notebook to file
333
334 This writes output from the exporter to file using the specified writer.
335 It returns the results from the writer.
336
337 """
338 if 'unique_key' not in resources:
339 raise KeyError("unique_key MUST be specified in the resources, but it is not")
340
341 notebook_name = resources['unique_key']
342 if self.use_output_suffix and not self.output_base:
343 notebook_name += resources.get('output_suffix', '')
344
345 write_results = self.writer.write(
346 output, resources, notebook_name=notebook_name)
347 return write_results
348
349 def postprocess_single_notebook(self, write_results):
350 """Step 4: Postprocess the notebook
351
352 This postprocesses the notebook after it has been written, taking as an
353 argument the results of writing the notebook to file. This only actually
354 does anything if a postprocessor has actually been specified.
355
356 """
357 # Post-process if post processor has been defined.
358 if hasattr(self, 'postprocessor') and self.postprocessor:
359 self.postprocessor(write_results)
360
361 def convert_single_notebook(self, notebook_filename):
362 """Convert a single notebook. Performs the following steps:
363
364 1. Initialize notebook resources
365 2. Export the notebook to a particular format
366 3. Write the exported notebook to file
367 4. (Maybe) postprocess the written file
368
369 """
370 self.log.info("Converting notebook %s to %s", notebook_filename, self.export_format)
371 resources = self.init_single_notebook_resources(notebook_filename)
372 output, resources = self.export_single_notebook(notebook_filename, resources)
373 write_results = self.write_single_notebook(output, resources)
374 self.postprocess_single_notebook(write_results)
375
376 def convert_notebooks(self):
377 """
378 Convert the notebooks in the self.notebook traitlet
379 """
380 # check that the output base isn't specified if there is more than
381 # one notebook to convert
382 if self.output_base != '' and len(self.notebooks) > 1:
383 self.log.error(
384 """
385 UsageError: --output flag or `NbConvertApp.output_base` config option
386 cannot be used when converting multiple notebooks.
387 """
388 )
389 self.exit(1)
390
391 # initialize the exporter
392 self.exporter = exporter_map[self.export_format](config=self.config)
393
394 # no notebooks to convert!
395 if len(self.notebooks) == 0:
396 self.print_help()
397 sys.exit(-1)
398
399 # convert each notebook
400 for notebook_filename in self.notebooks:
401 self.convert_single_notebook(notebook_filename)
402
403 #-----------------------------------------------------------------------------
404 # Main entry point
405 #-----------------------------------------------------------------------------
406
407 launch_new_instance = NbConvertApp.launch_instance
@@ -1,7 +0,0 b''
1 from .base import PostProcessorBase
2
3 # protect against unavailable tornado
4 try:
5 from .serve import ServePostProcessor
6 except ImportError:
7 pass
@@ -1,35 +0,0 b''
1 """
2 Basic post processor
3 """
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
6 #
7 #Distributed under the terms of the Modified BSD License.
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 from ..utils.base import NbConvertBase
17
18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
22 class PostProcessorBase(NbConvertBase):
23
24 def __call__(self, input):
25 """
26 See def postprocess() ...
27 """
28 self.postprocess(input)
29
30
31 def postprocess(self, input):
32 """
33 Post-process output from a writer.
34 """
35 raise NotImplementedError('postprocess')
@@ -1,105 +0,0 b''
1 """PostProcessor for serving reveal.js HTML slideshows."""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from __future__ import print_function
7
8 import os
9 import webbrowser
10
11 from tornado import web, ioloop, httpserver
12 from tornado.httpclient import AsyncHTTPClient
13
14 from IPython.utils.traitlets import Bool, Unicode, Int
15
16 from .base import PostProcessorBase
17
18
19 class ProxyHandler(web.RequestHandler):
20 """handler the proxies requests from a local prefix to a CDN"""
21 @web.asynchronous
22 def get(self, prefix, url):
23 """proxy a request to a CDN"""
24 proxy_url = "/".join([self.settings['cdn'], url])
25 client = self.settings['client']
26 client.fetch(proxy_url, callback=self.finish_get)
27
28 def finish_get(self, response):
29 """finish the request"""
30 # rethrow errors
31 response.rethrow()
32
33 for header in ["Content-Type", "Cache-Control", "Date", "Last-Modified", "Expires"]:
34 if header in response.headers:
35 self.set_header(header, response.headers[header])
36 self.finish(response.body)
37
38
39 class ServePostProcessor(PostProcessorBase):
40 """Post processor designed to serve files
41
42 Proxies reveal.js requests to a CDN if no local reveal.js is present
43 """
44
45
46 open_in_browser = Bool(True, config=True,
47 help="""Should the browser be opened automatically?"""
48 )
49 reveal_cdn = Unicode("https://cdn.jsdelivr.net/reveal.js/2.6.2", config=True,
50 help="""URL for reveal.js CDN."""
51 )
52 reveal_prefix = Unicode("reveal.js", config=True, help="URL prefix for reveal.js")
53 ip = Unicode("127.0.0.1", config=True, help="The IP address to listen on.")
54 port = Int(8000, config=True, help="port for the server to listen on.")
55
56 def postprocess(self, input):
57 """Serve the build directory with a webserver."""
58 dirname, filename = os.path.split(input)
59 handlers = [
60 (r"/(.+)", web.StaticFileHandler, {'path' : dirname}),
61 (r"/", web.RedirectHandler, {"url": "/%s" % filename})
62 ]
63
64 if ('://' in self.reveal_prefix or self.reveal_prefix.startswith("//")):
65 # reveal specifically from CDN, nothing to do
66 pass
67 elif os.path.isdir(os.path.join(dirname, self.reveal_prefix)):
68 # reveal prefix exists
69 self.log.info("Serving local %s", self.reveal_prefix)
70 else:
71 self.log.info("Redirecting %s requests to %s", self.reveal_prefix, self.reveal_cdn)
72 handlers.insert(0, (r"/(%s)/(.*)" % self.reveal_prefix, ProxyHandler))
73
74 app = web.Application(handlers,
75 cdn=self.reveal_cdn,
76 client=AsyncHTTPClient(),
77 )
78 # hook up tornado logging to our logger
79 try:
80 from tornado import log
81 log.app_log = self.log
82 except ImportError:
83 # old tornado (<= 3), ignore
84 pass
85
86 http_server = httpserver.HTTPServer(app)
87 http_server.listen(self.port, address=self.ip)
88 url = "http://%s:%i/%s" % (self.ip, self.port, filename)
89 print("Serving your slides at %s" % url)
90 print("Use Control-C to stop this server")
91 if self.open_in_browser:
92 webbrowser.open(url, new=2)
93 try:
94 ioloop.IOLoop.instance().start()
95 except KeyboardInterrupt:
96 print("\nInterrupted")
97
98 def main(path):
99 """allow running this module to serve the slides"""
100 server = ServePostProcessor()
101 server(path)
102
103 if __name__ == '__main__':
104 import sys
105 main(sys.argv[1])
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,31 +0,0 b''
1 """
2 Module with tests for the serve post-processor
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from ...tests.base import TestsBase
18 from ..serve import ServePostProcessor
19
20
21 #-----------------------------------------------------------------------------
22 # Class
23 #-----------------------------------------------------------------------------
24
25 class TestServe(TestsBase):
26 """Contains test functions for serve.py"""
27
28
29 def test_constructor(self):
30 """Can a ServePostProcessor be constructed?"""
31 ServePostProcessor()
@@ -1,14 +0,0 b''
1 # Class base Preprocessors
2 from .base import Preprocessor
3 from .convertfigures import ConvertFiguresPreprocessor
4 from .svg2pdf import SVG2PDFPreprocessor
5 from .extractoutput import ExtractOutputPreprocessor
6 from .revealhelp import RevealHelpPreprocessor
7 from .latex import LatexPreprocessor
8 from .csshtmlheader import CSSHTMLHeaderPreprocessor
9 from .highlightmagics import HighlightMagicsPreprocessor
10 from .clearoutput import ClearOutputPreprocessor
11 from .execute import ExecutePreprocessor
12
13 # decorated function Preprocessors
14 from .coalescestreams import coalesce_streams
@@ -1,92 +0,0 b''
1 """Base class for preprocessors"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from ..utils.base import NbConvertBase
7 from IPython.utils.traitlets import Bool
8
9
10 class Preprocessor(NbConvertBase):
11 """ A configurable preprocessor
12
13 Inherit from this class if you wish to have configurability for your
14 preprocessor.
15
16 Any configurable traitlets this class exposed will be configurable in
17 profiles using c.SubClassName.attribute = value
18
19 you can overwrite :meth:`preprocess_cell` to apply a transformation
20 independently on each cell or :meth:`preprocess` if you prefer your own
21 logic. See corresponding docstring for informations.
22
23 Disabled by default and can be enabled via the config by
24 'c.YourPreprocessorName.enabled = True'
25 """
26
27 enabled = Bool(False, config=True)
28
29 def __init__(self, **kw):
30 """
31 Public constructor
32
33 Parameters
34 ----------
35 config : Config
36 Configuration file structure
37 **kw : misc
38 Additional arguments
39 """
40
41 super(Preprocessor, self).__init__(**kw)
42
43
44 def __call__(self, nb, resources):
45 if self.enabled:
46 self.log.debug("Applying preprocessor: %s", self.__class__.__name__)
47 return self.preprocess(nb,resources)
48 else:
49 return nb, resources
50
51
52 def preprocess(self, nb, resources):
53 """
54 Preprocessing to apply on each notebook.
55
56 Must return modified nb, resources.
57
58 If you wish to apply your preprocessing to each cell, you might want
59 to override preprocess_cell method instead.
60
61 Parameters
62 ----------
63 nb : NotebookNode
64 Notebook being converted
65 resources : dictionary
66 Additional resources used in the conversion process. Allows
67 preprocessors to pass variables into the Jinja engine.
68 """
69 for index, cell in enumerate(nb.cells):
70 nb.cells[index], resources = self.preprocess_cell(cell, resources, index)
71 return nb, resources
72
73
74 def preprocess_cell(self, cell, resources, index):
75 """
76 Override if you want to apply some preprocessing to each cell.
77 Must return modified cell and resource dictionary.
78
79 Parameters
80 ----------
81 cell : NotebookNode cell
82 Notebook cell being processed
83 resources : dictionary
84 Additional resources used in the conversion process. Allows
85 preprocessors to pass variables into the Jinja engine.
86 index : int
87 Index of the cell being processed
88 """
89
90 raise NotImplementedError('should be implemented by subclass')
91 return cell, resources
92
@@ -1,20 +0,0 b''
1 """Module containing a preprocessor that removes the outputs from code cells"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import Preprocessor
7
8 class ClearOutputPreprocessor(Preprocessor):
9 """
10 Removes the output from all code cells in a notebook.
11 """
12
13 def preprocess_cell(self, cell, resources, cell_index):
14 """
15 Apply a transformation on each cell. See base.py for details.
16 """
17 if cell.cell_type == 'code':
18 cell.outputs = []
19 cell.execution_count = None
20 return cell, resources
@@ -1,75 +0,0 b''
1 """Preprocessor for merging consecutive stream outputs for easier handling."""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import re
7 from IPython.utils.log import get_logger
8
9 def cell_preprocessor(function):
10 """
11 Wrap a function to be executed on all cells of a notebook
12
13 The wrapped function should have these parameters:
14
15 cell : NotebookNode cell
16 Notebook cell being processed
17 resources : dictionary
18 Additional resources used in the conversion process. Allows
19 preprocessors to pass variables into the Jinja engine.
20 index : int
21 Index of the cell being processed
22 """
23
24 def wrappedfunc(nb, resources):
25 get_logger().debug(
26 "Applying preprocessor: %s", function.__name__
27 )
28 for index, cell in enumerate(nb.cells):
29 nb.cells[index], resources = function(cell, resources, index)
30 return nb, resources
31 return wrappedfunc
32
33 cr_pat = re.compile(r'.*\r(?=[^\n])')
34
35 @cell_preprocessor
36 def coalesce_streams(cell, resources, index):
37 """
38 Merge consecutive sequences of stream output into single stream
39 to prevent extra newlines inserted at flush calls
40
41 Parameters
42 ----------
43 cell : NotebookNode cell
44 Notebook cell being processed
45 resources : dictionary
46 Additional resources used in the conversion process. Allows
47 transformers to pass variables into the Jinja engine.
48 index : int
49 Index of the cell being processed
50 """
51
52 outputs = cell.get('outputs', [])
53 if not outputs:
54 return cell, resources
55
56 last = outputs[0]
57 new_outputs = [last]
58 for output in outputs[1:]:
59 if (output.output_type == 'stream' and
60 last.output_type == 'stream' and
61 last.name == output.name
62 ):
63 last.text += output.text
64
65 else:
66 new_outputs.append(output)
67 last = output
68
69 # process \r characters
70 for output in new_outputs:
71 if output.output_type == 'stream' and '\r' in output.text:
72 output.text = cr_pat.sub('', output.text)
73
74 cell.outputs = new_outputs
75 return cell, resources
@@ -1,58 +0,0 b''
1 """Module containing a preprocessor that converts outputs in the notebook from
2 one format to another.
3 """
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
6 #
7 # Distributed under the terms of the Modified BSD License.
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 from .base import Preprocessor
17 from IPython.utils.traitlets import Unicode
18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
22
23 class ConvertFiguresPreprocessor(Preprocessor):
24 """
25 Converts all of the outputs in a notebook from one format to another.
26 """
27
28 from_format = Unicode(config=True, help='Format the converter accepts')
29 to_format = Unicode(config=True, help='Format the converter writes')
30
31 def __init__(self, **kw):
32 """
33 Public constructor
34 """
35 super(ConvertFiguresPreprocessor, self).__init__(**kw)
36
37
38 def convert_figure(self, data_format, data):
39 raise NotImplementedError()
40
41
42 def preprocess_cell(self, cell, resources, cell_index):
43 """
44 Apply a transformation on each cell,
45
46 See base.py
47 """
48
49 # Loop through all of the datatypes of the outputs in the cell.
50 for output in cell.get('outputs', []):
51 if output.output_type in {'execute_result', 'display_data'} \
52 and self.from_format in output.data \
53 and self.to_format not in output.data:
54
55 output.data[self.to_format] = self.convert_figure(
56 self.from_format, output.data[self.from_format])
57
58 return cell, resources
@@ -1,85 +0,0 b''
1 """Module that pre-processes the notebook for export to HTML.
2 """
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5 import os
6 import io
7 import hashlib
8
9 from IPython.utils import path
10 from IPython.utils.traitlets import Unicode
11 from IPython.utils.py3compat import str_to_bytes
12 from .base import Preprocessor
13
14 class CSSHTMLHeaderPreprocessor(Preprocessor):
15 """
16 Preprocessor used to pre-process notebook for HTML output. Adds IPython notebook
17 front-end CSS and Pygments CSS to HTML output.
18 """
19 highlight_class = Unicode('.highlight', config=True,
20 help="CSS highlight class identifier")
21
22 def __init__(self, *pargs, **kwargs):
23 Preprocessor.__init__(self, *pargs, **kwargs)
24 self._default_css_hash = None
25
26 def preprocess(self, nb, resources):
27 """Fetch and add CSS to the resource dictionary
28
29 Fetch CSS from IPython and Pygments to add at the beginning
30 of the html files. Add this css in resources in the
31 "inlining.css" key
32
33 Parameters
34 ----------
35 nb : NotebookNode
36 Notebook being converted
37 resources : dictionary
38 Additional resources used in the conversion process. Allows
39 preprocessors to pass variables into the Jinja engine.
40 """
41 resources['inlining'] = {}
42 resources['inlining']['css'] = self._generate_header(resources)
43 return nb, resources
44
45 def _generate_header(self, resources):
46 """
47 Fills self.header with lines of CSS extracted from IPython
48 and Pygments.
49 """
50 from pygments.formatters import HtmlFormatter
51 header = []
52
53 # Construct path to IPy CSS
54 from IPython.html import DEFAULT_STATIC_FILES_PATH
55 sheet_filename = os.path.join(DEFAULT_STATIC_FILES_PATH,
56 'style', 'style.min.css')
57
58 # Load style CSS file.
59 with io.open(sheet_filename, encoding='utf-8') as f:
60 header.append(f.read())
61
62 # Add pygments CSS
63 formatter = HtmlFormatter()
64 pygments_css = formatter.get_style_defs(self.highlight_class)
65 header.append(pygments_css)
66
67 # Load the user's custom CSS and IPython's default custom CSS. If they
68 # differ, assume the user has made modifications to his/her custom CSS
69 # and that we should inline it in the nbconvert output.
70 profile_dir = resources['profile_dir']
71 custom_css_filename = os.path.join(profile_dir, 'static', 'custom', 'custom.css')
72 if os.path.isfile(custom_css_filename):
73 if self._default_css_hash is None:
74 self._default_css_hash = self._hash(os.path.join(DEFAULT_STATIC_FILES_PATH, 'custom', 'custom.css'))
75 if self._hash(custom_css_filename) != self._default_css_hash:
76 with io.open(custom_css_filename, encoding='utf-8') as f:
77 header.append(f.read())
78 return header
79
80 def _hash(self, filename):
81 """Compute the hash of a file."""
82 md5 = hashlib.md5()
83 with open(filename) as f:
84 md5.update(str_to_bytes(f.read()))
85 return md5.digest()
@@ -1,143 +0,0 b''
1 """Module containing a preprocessor that removes the outputs from code cells"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import os
7 from textwrap import dedent
8
9 try:
10 from queue import Empty # Py 3
11 except ImportError:
12 from Queue import Empty # Py 2
13
14 from IPython.utils.traitlets import List, Unicode, Bool
15
16 from IPython.nbformat.v4 import output_from_msg
17 from .base import Preprocessor
18 from IPython.utils.traitlets import Integer
19
20
21 class ExecutePreprocessor(Preprocessor):
22 """
23 Executes all the cells in a notebook
24 """
25
26 timeout = Integer(30, config=True,
27 help="The time to wait (in seconds) for output from executions."
28 )
29
30 interrupt_on_timeout = Bool(
31 False, config=True,
32 help=dedent(
33 """
34 If execution of a cell times out, interrupt the kernel and
35 continue executing other cells rather than throwing an error and
36 stopping.
37 """
38 )
39 )
40
41 extra_arguments = List(Unicode)
42
43 def preprocess(self, nb, resources):
44 path = resources.get('metadata', {}).get('path', '')
45 if path == '':
46 path = None
47
48 from IPython.kernel.manager import start_new_kernel
49 kernel_name = nb.metadata.get('kernelspec', {}).get('name', 'python')
50 self.log.info("Executing notebook with kernel: %s" % kernel_name)
51 self.km, self.kc = start_new_kernel(
52 kernel_name=kernel_name,
53 extra_arguments=self.extra_arguments,
54 stderr=open(os.devnull, 'w'),
55 cwd=path)
56 self.kc.allow_stdin = False
57
58 try:
59 nb, resources = super(ExecutePreprocessor, self).preprocess(nb, resources)
60 finally:
61 self.kc.stop_channels()
62 self.km.shutdown_kernel(now=True)
63
64 return nb, resources
65
66 def preprocess_cell(self, cell, resources, cell_index):
67 """
68 Apply a transformation on each code cell. See base.py for details.
69 """
70 if cell.cell_type != 'code':
71 return cell, resources
72 try:
73 outputs = self.run_cell(cell)
74 except Exception as e:
75 self.log.error("failed to run cell: " + repr(e))
76 self.log.error(str(cell.source))
77 raise
78 cell.outputs = outputs
79 return cell, resources
80
81 def run_cell(self, cell):
82 msg_id = self.kc.execute(cell.source)
83 self.log.debug("Executing cell:\n%s", cell.source)
84 # wait for finish, with timeout
85 while True:
86 try:
87 msg = self.kc.shell_channel.get_msg(timeout=self.timeout)
88 except Empty:
89 self.log.error("Timeout waiting for execute reply")
90 if self.interrupt_on_timeout:
91 self.log.error("Interrupting kernel")
92 self.km.interrupt_kernel()
93 break
94 else:
95 raise
96
97 if msg['parent_header'].get('msg_id') == msg_id:
98 break
99 else:
100 # not our reply
101 continue
102
103 outs = []
104
105 while True:
106 try:
107 msg = self.kc.iopub_channel.get_msg(timeout=self.timeout)
108 except Empty:
109 self.log.warn("Timeout waiting for IOPub output")
110 break
111 if msg['parent_header'].get('msg_id') != msg_id:
112 # not an output from our execution
113 continue
114
115 msg_type = msg['msg_type']
116 self.log.debug("output: %s", msg_type)
117 content = msg['content']
118
119 # set the prompt number for the input and the output
120 if 'execution_count' in content:
121 cell['execution_count'] = content['execution_count']
122
123 if msg_type == 'status':
124 if content['execution_state'] == 'idle':
125 break
126 else:
127 continue
128 elif msg_type == 'execute_input':
129 continue
130 elif msg_type == 'clear_output':
131 outs = []
132 continue
133 elif msg_type.startswith('comm'):
134 continue
135
136 try:
137 out = output_from_msg(msg)
138 except ValueError:
139 self.log.error("unhandled iopub msg: " + msg_type)
140 else:
141 outs.append(out)
142
143 return outs
@@ -1,98 +0,0 b''
1 """A preprocessor that extracts all of the outputs from the
2 notebook file. The extracted outputs are returned in the 'resources' dictionary.
3 """
4
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 import base64
9 import sys
10 import os
11 from mimetypes import guess_extension
12
13 from IPython.utils.traitlets import Unicode, Set
14 from .base import Preprocessor
15 from IPython.utils import py3compat
16
17
18 class ExtractOutputPreprocessor(Preprocessor):
19 """
20 Extracts all of the outputs from the notebook file. The extracted
21 outputs are returned in the 'resources' dictionary.
22 """
23
24 output_filename_template = Unicode(
25 "{unique_key}_{cell_index}_{index}{extension}", config=True)
26
27 extract_output_types = Set({'image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf'}, config=True)
28
29 def preprocess_cell(self, cell, resources, cell_index):
30 """
31 Apply a transformation on each cell,
32
33 Parameters
34 ----------
35 cell : NotebookNode cell
36 Notebook cell being processed
37 resources : dictionary
38 Additional resources used in the conversion process. Allows
39 preprocessors to pass variables into the Jinja engine.
40 cell_index : int
41 Index of the cell being processed (see base.py)
42 """
43
44 #Get the unique key from the resource dict if it exists. If it does not
45 #exist, use 'output' as the default. Also, get files directory if it
46 #has been specified
47 unique_key = resources.get('unique_key', 'output')
48 output_files_dir = resources.get('output_files_dir', None)
49
50 #Make sure outputs key exists
51 if not isinstance(resources['outputs'], dict):
52 resources['outputs'] = {}
53
54 #Loop through all of the outputs in the cell
55 for index, out in enumerate(cell.get('outputs', [])):
56 if out.output_type not in {'display_data', 'execute_result'}:
57 continue
58 #Get the output in data formats that the template needs extracted
59 for mime_type in self.extract_output_types:
60 if mime_type in out.data:
61 data = out.data[mime_type]
62
63 #Binary files are base64-encoded, SVG is already XML
64 if mime_type in {'image/png', 'image/jpeg', 'application/pdf'}:
65
66 # data is b64-encoded as text (str, unicode)
67 # decodestring only accepts bytes
68 data = py3compat.cast_bytes(data)
69 data = base64.decodestring(data)
70 elif sys.platform == 'win32':
71 data = data.replace('\n', '\r\n').encode("UTF-8")
72 else:
73 data = data.encode("UTF-8")
74
75 ext = guess_extension(mime_type)
76 if ext is None:
77 ext = '.' + mime_type.rsplit('/')[-1]
78
79 filename = self.output_filename_template.format(
80 unique_key=unique_key,
81 cell_index=cell_index,
82 index=index,
83 extension=ext)
84
85 # On the cell, make the figure available via
86 # cell.outputs[i].metadata.filenames['mime/type']
87 # where
88 # cell.outputs[i].data['mime/type'] contains the data
89 if output_files_dir is not None:
90 filename = os.path.join(output_files_dir, filename)
91 out.metadata.setdefault('filenames', {})
92 out.metadata['filenames'][mime_type] = filename
93
94 #In the resources, make the figure available via
95 # resources['outputs']['filename'] = data
96 resources['outputs'][filename] = data
97
98 return cell, resources
@@ -1,100 +0,0 b''
1 """This preprocessor detect cells using a different language through
2 magic extensions such as `%%R` or `%%octave`. Cell's metadata is marked
3 so that the appropriate highlighter can be used in the `highlight`
4 filter.
5 """
6
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
9
10 from __future__ import print_function, absolute_import
11
12 import re
13
14 # Our own imports
15 from .base import Preprocessor
16 from IPython.utils.traitlets import Dict
17
18
19 class HighlightMagicsPreprocessor(Preprocessor):
20 """
21 Detects and tags code cells that use a different languages than Python.
22 """
23
24 # list of magic language extensions and their associated pygment lexers
25 default_languages = Dict(
26 default_value={
27 '%%R': 'r',
28 '%%bash': 'bash',
29 '%%cython': 'cython',
30 '%%javascript': 'javascript',
31 '%%julia': 'julia',
32 '%%latex': 'latex',
33 '%%octave': 'octave',
34 '%%perl': 'perl',
35 '%%ruby': 'ruby',
36 '%%sh': 'sh'})
37
38 # user defined language extensions
39 languages = Dict(
40 config=True,
41 help=("Syntax highlighting for magic's extension languages. "
42 "Each item associates a language magic extension such as %%R, "
43 "with a pygments lexer such as r."))
44
45 def __init__(self, config=None, **kw):
46 """Public constructor"""
47
48 super(HighlightMagicsPreprocessor, self).__init__(config=config, **kw)
49
50 # Update the default languages dict with the user configured ones
51 self.default_languages.update(self.languages)
52
53 # build a regular expression to catch language extensions and choose
54 # an adequate pygments lexer
55 any_language = "|".join(self.default_languages.keys())
56 self.re_magic_language = re.compile(
57 r'^\s*({0})\s+'.format(any_language))
58
59 def which_magic_language(self, source):
60 """
61 When a cell uses another language through a magic extension,
62 the other language is returned.
63 If no language magic is detected, this function returns None.
64
65 Parameters
66 ----------
67 source: str
68 Source code of the cell to highlight
69 """
70
71 m = self.re_magic_language.match(source)
72
73 if m:
74 # By construction of the re, the matched language must be in the
75 # languages dictionary
76 return self.default_languages[m.group(1)]
77 else:
78 return None
79
80 def preprocess_cell(self, cell, resources, cell_index):
81 """
82 Tags cells using a magic extension language
83
84 Parameters
85 ----------
86 cell : NotebookNode cell
87 Notebook cell being processed
88 resources : dictionary
89 Additional resources used in the conversion process. Allows
90 preprocessors to pass variables into the Jinja engine.
91 cell_index : int
92 Index of the cell being processed (see base.py)
93 """
94
95 # Only tag code cells
96 if cell.cell_type == "code":
97 magic_language = self.which_magic_language(cell.source)
98 if magic_language:
99 cell['metadata']['magics_language'] = magic_language
100 return cell, resources
@@ -1,47 +0,0 b''
1 """Module that allows latex output notebooks to be conditioned before
2 they are converted.
3 """
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
6 #
7 # Distributed under the terms of the Modified BSD License.
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 from __future__ import print_function, absolute_import
17
18 from .base import Preprocessor
19
20 #-----------------------------------------------------------------------------
21 # Classes
22 #-----------------------------------------------------------------------------
23
24 class LatexPreprocessor(Preprocessor):
25 """Preprocessor for latex destined documents.
26
27 Mainly populates the `latex` key in the resources dict,
28 adding definitions for pygments highlight styles.
29 """
30
31 def preprocess(self, nb, resources):
32 """Preprocessing to apply on each notebook.
33
34 Parameters
35 ----------
36 nb : NotebookNode
37 Notebook being converted
38 resources : dictionary
39 Additional resources used in the conversion process. Allows
40 preprocessors to pass variables into the Jinja engine.
41 """
42 # Generate Pygments definitions for Latex
43 from pygments.formatters import LatexFormatter
44
45 resources.setdefault("latex", {})
46 resources["latex"].setdefault("pygments_definitions", LatexFormatter().get_style_defs())
47 return nb, resources
@@ -1,62 +0,0 b''
1 """Module that pre-processes the notebook for export via Reveal."""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import Preprocessor
7 from IPython.utils.traitlets import Unicode
8
9
10 class RevealHelpPreprocessor(Preprocessor):
11
12 url_prefix = Unicode('reveal.js', config=True,
13 help="""The URL prefix for reveal.js.
14 This can be a a relative URL for a local copy of reveal.js,
15 or point to a CDN.
16
17 For speaker notes to work, a local reveal.js prefix must be used.
18 """
19 )
20
21 def preprocess(self, nb, resources):
22 """
23 Called once to 'preprocess' contents of the notebook.
24
25 Parameters
26 ----------
27 nb : NotebookNode
28 Notebook being converted
29 resources : dictionary
30 Additional resources used in the conversion process. Allows
31 preprocessors to pass variables into the Jinja engine.
32 """
33
34 for index, cell in enumerate(nb.cells):
35
36 #Make sure the cell has slideshow metadata.
37 cell.metadata.slide_type = cell.get('metadata', {}).get('slideshow', {}).get('slide_type', '-')
38
39 # Get the slide type. If type is start, subslide, or slide,
40 # end the last subslide/slide.
41 if cell.metadata.slide_type in ['slide']:
42 nb.cells[index - 1].metadata.slide_helper = 'slide_end'
43 if cell.metadata.slide_type in ['subslide']:
44 nb.cells[index - 1].metadata.slide_helper = 'subslide_end'
45 # Prevent the rendering of "do nothing" cells before fragments
46 # Group fragments passing frag_number to the data-fragment-index
47 if cell.metadata.slide_type in ['fragment']:
48 nb.cells[index].metadata.frag_number = index
49 i = 1
50 while i < len(nb.cells) - index:
51 nb.cells[index + i].metadata.frag_helper = 'fragment_end'
52 nb.cells[index + i].metadata.frag_number = index
53 i += 1
54 # Restart the slide_helper when the cell status is changed
55 # to other types.
56 if cell.metadata.slide_type in ['-', 'skip', 'notes', 'fragment']:
57 nb.cells[index - 1].metadata.slide_helper = '-'
58
59 if not isinstance(resources['reveal'], dict):
60 resources['reveal'] = {}
61 resources['reveal']['url_prefix'] = self.url_prefix
62 return nb, resources
@@ -1,83 +0,0 b''
1 """Module containing a preprocessor that converts outputs in the notebook from
2 one format to another.
3 """
4
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 import base64
9 import io
10 import os
11 import sys
12 import subprocess
13
14 from IPython.utils.py3compat import cast_unicode_py2
15 from IPython.utils.tempdir import TemporaryDirectory
16 from IPython.utils.traitlets import Unicode
17
18 from .convertfigures import ConvertFiguresPreprocessor
19
20
21 INKSCAPE_APP = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
22
23
24 class SVG2PDFPreprocessor(ConvertFiguresPreprocessor):
25 """
26 Converts all of the outputs in a notebook from SVG to PDF.
27 """
28
29 def _from_format_default(self):
30 return 'image/svg+xml'
31 def _to_format_default(self):
32 return 'application/pdf'
33
34 command = Unicode(config=True,
35 help="""The command to use for converting SVG to PDF
36
37 This string is a template, which will be formatted with the keys
38 to_filename and from_filename.
39
40 The conversion call must read the SVG from {from_flename},
41 and write a PDF to {to_filename}.
42 """)
43
44 def _command_default(self):
45 return self.inkscape + \
46 ' --without-gui --export-pdf="{to_filename}" "{from_filename}"'
47
48 inkscape = Unicode(config=True, help="The path to Inkscape, if necessary")
49 def _inkscape_default(self):
50 if sys.platform == "darwin":
51 if os.path.isfile(INKSCAPE_APP):
52 return INKSCAPE_APP
53 return "inkscape"
54
55
56 def convert_figure(self, data_format, data):
57 """
58 Convert a single SVG figure to PDF. Returns converted data.
59 """
60
61 #Work in a temporary directory
62 with TemporaryDirectory() as tmpdir:
63
64 #Write fig to temp file
65 input_filename = os.path.join(tmpdir, 'figure.svg')
66 # SVG data is unicode text
67 with io.open(input_filename, 'w', encoding='utf8') as f:
68 f.write(cast_unicode_py2(data))
69
70 #Call conversion application
71 output_filename = os.path.join(tmpdir, 'figure.pdf')
72 shell = self.command.format(from_filename=input_filename,
73 to_filename=output_filename)
74 subprocess.call(shell, shell=True) #Shell=True okay since input is trusted.
75
76 #Read output from drive
77 # return value expects a filename
78 if os.path.isfile(output_filename):
79 with open(output_filename, 'rb') as f:
80 # PDF is a nb supported binary, data type, so base64 encode.
81 return base64.encodestring(f.read())
82 else:
83 raise TypeError("Inkscape svg to pdf conversion failed")
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,41 +0,0 b''
1 """utility functions for preprocessor tests"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from IPython.nbformat import v4 as nbformat
7
8 from ...tests.base import TestsBase
9 from ...exporters.exporter import ResourcesDict
10
11
12 class PreprocessorTestsBase(TestsBase):
13 """Contains test functions preprocessor tests"""
14
15
16 def build_notebook(self):
17 """Build a notebook in memory for use with preprocessor tests"""
18
19 outputs = [
20 nbformat.new_output("stream", name="stdout", text="a"),
21 nbformat.new_output("display_data", data={'text/plain': 'b'}),
22 nbformat.new_output("stream", name="stdout", text="c"),
23 nbformat.new_output("stream", name="stdout", text="d"),
24 nbformat.new_output("stream", name="stderr", text="e"),
25 nbformat.new_output("stream", name="stderr", text="f"),
26 nbformat.new_output("display_data", data={'image/png': 'Zw=='}), # g
27 nbformat.new_output("display_data", data={'application/pdf': 'aA=='}), # h
28 ]
29
30 cells=[nbformat.new_code_cell(source="$ e $", execution_count=1, outputs=outputs),
31 nbformat.new_markdown_cell(source="$ e $")]
32
33 return nbformat.new_notebook(cells=cells)
34
35
36 def build_resources(self):
37 """Build an empty resources dictionary."""
38
39 res = ResourcesDict()
40 res['metadata'] = ResourcesDict()
41 return res
@@ -1,39 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [],
10 "source": [
11 "from IPython.display import clear_output"
12 ]
13 },
14 {
15 "cell_type": "code",
16 "execution_count": 2,
17 "metadata": {
18 "collapsed": false
19 },
20 "outputs": [
21 {
22 "name": "stdout",
23 "output_type": "stream",
24 "text": [
25 "9\n"
26 ]
27 }
28 ],
29 "source": [
30 "for i in range(10):\n",
31 " clear_output()\n",
32 " print(i)"
33 ]
34 }
35 ],
36 "metadata": {},
37 "nbformat": 4,
38 "nbformat_minor": 0
39 } No newline at end of file
@@ -1,23 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": null,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [],
10 "source": [
11 "try:\n",
12 " input = raw_input\n",
13 "except:\n",
14 " pass\n",
15 "\n",
16 "name = input(\"name: \")"
17 ]
18 }
19 ],
20 "metadata": {},
21 "nbformat": 4,
22 "nbformat_minor": 0
23 }
@@ -1,48 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [],
10 "source": [
11 "i, j = 1, 1"
12 ]
13 },
14 {
15 "cell_type": "code",
16 "execution_count": 2,
17 "metadata": {
18 "collapsed": false
19 },
20 "outputs": [
21 {
22 "name": "stdout",
23 "output_type": "stream",
24 "text": [
25 "2\n",
26 "3\n",
27 "5\n",
28 "8\n",
29 "13\n",
30 "21\n",
31 "34\n",
32 "55\n",
33 "89\n",
34 "144\n"
35 ]
36 }
37 ],
38 "source": [
39 "for m in range(10):\n",
40 " i, j = j, i + j\n",
41 " print(j)"
42 ]
43 }
44 ],
45 "metadata": {},
46 "nbformat": 4,
47 "nbformat_minor": 0
48 } No newline at end of file
@@ -1,26 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [
10 {
11 "name": "stdout",
12 "output_type": "stream",
13 "text": [
14 "Hello World\n"
15 ]
16 }
17 ],
18 "source": [
19 "print(\"Hello World\")"
20 ]
21 }
22 ],
23 "metadata": {},
24 "nbformat": 4,
25 "nbformat_minor": 0
26 } No newline at end of file
@@ -1,196 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [],
10 "source": [
11 "from IPython.display import Image"
12 ]
13 },
14 {
15 "cell_type": "code",
16 "execution_count": 2,
17 "metadata": {
18 "collapsed": false
19 },
20 "outputs": [
21 {
22 "data": {
23 "image/png": [
24 "iVBORw0KGgoAAAANSUhEUgAAAMgAAABQCAYAAABcbTqwAAAABHNCSVQICAgIfAhkiAAAABl0RVh0\n",
25 "U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7Z15eJNV2vDvJ0/2vUmapk3b\n",
26 "dG9pKYWyFARkd6GojOI2vs6HfjqKI17i+LnNfM68LpfMq4KjM6/44jbgqKCfKLIoUFrWUigglO5N\n",
27 "1yxttmZfnzzP90dImrZpmqY75nddVZJnO0nOfc597u0gBEFUQ4wYMUJCmuwGxIgxlYkJSIwYYYgJ\n",
28 "SIwYYYgJSIwYYYgJSIxh8Xg8SHV1Na+srEw42W2ZaMiT3YAYU5vLly9zdu7cmeXxeEh5eXnGVatW\n",
29 "6Se7TRPJlBGQbqONcr5Rzdaa7BSDxUExWl1ko81JNtmcFLPNRTbZnWTMi5PYdCrGYVAxLouK8ehU\n",
30 "jMemYVwmDeOz6Vg8j+lZXJBqEXAY2GR/nhsFq9VK8Xg8v1pNY1IF5Gy9in2yVsG72NLD69QYGQAI\n",
31 "ABAABMD1/wx4TYDR6qQYrQ4KaAGACDoHfK9JCEIUyESWFUXpvQ+sKNSjKImAGDGiZFIExGBxkl/b\n",
32 "U5laWa+O6xMEJMwVkfdxnCCQmnYNt6ZNwz14vkn0xsaVbRlJQteoGnyDg+M4kEi/2kkiLBP+rdR1\n",
33 "GRgPvnMov7JBHTfez5KrDKyN/7Uv/0h1M2+8nzXdwDAMOX/+PO/9999P37lzp2yy2zNVmXAB+eDH\n",
34 "y1KjzUUZ+D4SbgIZBS7MS9r69ck0lc486Jm/ZiorK+N27tyZVVNTI3C5XOhkt2eqMqECclmuYV5q\n",
35 "1fQbzedlJ8C7jy6DY2/eB6/cVwLpCWM/2NscHvKrn5el4fiY3zrGDc6ECkhVcw8n+DWXQYV3//dy\n",
36 "WFKQDGw6Fe5amA2v/ceScXl2TVsPt6FTwxiXm8e4YZlQATFYHP3UnNIFGUCn9LcT5EgFUJgWPy7P\n",
37 "r2nvZo7LjWPcsEyoFavX6pzUdUB9h5YFAJPq6HI6nSStVkvV6XQUp9OJZmZm2sVisTvS6+VyOUMm\n",
38 "kznJZPKUMV/jOA4EQSAoio64TV6vF+ns7KSr1Wp6YmKiMzU11RnNfQB8hge1Wk1Tq9U0j8dD4vF4\n",
39 "nszMTDuDwYhauZ5QAbG7sH4z1o9VcnjytllAp/Y1o1FhgJp27bg8X2uyT4qAWiwW9OTJk8LKykpR\n",
40 "T0/PIDWPy+W6c3JyzBs3buyi0Wghf8y9e/cmXrp0SaDX6+nbtm37hcPheMM986233spWKpUsAIBN\n",
41 "mza1FBQUWAEADh8+HH/w4EGp1+sNmEVqa2v5Tz/99Gz/661bt9aw2ewh749hGFJWViZsbGzkajQa\n",
42 "ul6vpxEEARKJxDF//nzD7bffrhnObFxTU8P+/vvvpSqViolhff2CTCbjSUlJ9vXr1ysLCwutYW8C\n",
43 "PgE7fvy4sLy8PEGn09EIguhn7mEymdiaNWvUt956q5ZCoYxY8CbVUWh1euCZ/zkO9y/Ng7mZYjhy\n",
44 "uQP2nqqfzCaNOfv27ZP8/PPPiV6vN9AJ2Gy2RywWOx0OB6pWq5lms5laXV0t0mq19GeffbYlVOc8\n",
45 "fvx4YnCnHg6Xy4X6rVPB1+E4jmAYRiKIvr7ify+C2yLHjx8XHj58ONFoNNIGHlQqlSylUsmqra3l\n",
46 "bdmypWWoDrl///6EAwcOSP2dmU6nYxKJxKlUKpkej4fU2dnJ/uCDD3LWrl2rXL9+fU+oe+A4DqdO\n",
47 "nRIcOnQoyWAw0FAUJSQSiUMsFjvtdjtZrVYzrFYrxW63k3/44YeUioqKhOeff75RIpFEPFsDTIFQ\n",
48 "kyttWrjSph3sFZ/m4DgOO3bsSLt8+bIQAEAsFjvWrVunKiwstAQLgF6vp/z973/PUqvVzI6ODvbb\n",
49 "b7+d8+qrrzZEq2YMR2lpqaa0tFRz6tQpwa5du9IBAAoLC3ufeeaZ1uGubWho4DU0NPAQBCHmzp2r\n",
50 "z8/PN+Xl5dnsdjt69uxZQXl5uQQAoLm5mfvDDz9INmzYoB54j48//ji1qqoqHgBAIBC4Hnnkkbac\n",
51 "nBwbiUQCj8eD1NTUcHbv3p1mtVopBw8eTO7u7mY8+eST7cH3aG5uZn7++edpGo2GQSaT8aVLl/bc\n",
52 "dddd3TweLxBihGEYcuDAAfGhQ4ekBEEgJpOJumvXrtQXXnihZSTf16QLyI2Kx+Mh+YUDAOD111+v\n",
53 "C6V2CIVCz3PPPdf82muv5VssFopKpWKePn06btmyZYYJbXCEpKenWx588MGu9PR0R/D7aWlpSgRB\n",
54 "iOPHjycCAJSVlUnWrl2rYTKZgcGgvr6e5ReO+Ph4x4svvtgU3KkpFApRXFxs5vP5zdu3b891Op3o\n",
55 "xYsXhTU1NfrCwkKL/7yGhga2RuOzSBYXF+t/97vfKQa2k0wmE+vXr+9xOByov00tLS1cl8tFGkqN\n",
56 "DUUsvmCCCKeT8/l8bN68eQHjQXl5uXhCGjVCMjMzza+88krTQOHwc9NNNwWEGsMwUkdHB93/Gsdx\n",
57 "2LNnT4r/9e23395vxA8mIyPDUVpaqvS/3rt3bzIepRPrjjvuCKhoBEEgKpVqkGoYjpiATBEWLlwY\n",
58 "6FxKpZLV2Ng45UzSFAolbC+VyWRODofj8b9WqVQBAampqeH4jQZsNtuzaNGi3nD3WrJkiYFMJuMA\n",
59 "AN3d3cyLFy9G5UFms9leNpsdaBOO4yOK2ZhQFeuvDy7ssLuwrtBHh1e5d5VdTThwrmVKjq6jJSMj\n",
60 "w4GiKO5fzHd1dTFyc3Ptk92ukSKTyazXrl2LA/Cpmf73Ozs7A9a7pKQk+3Bmajab7U1LS7O2tLRw\n",
61 "AXzfx/z5803RtIlGo3mtVmtUFswJFZB4HnNUeRpsBjWsaXO6w2QyMYvFQgUAMBgM1MluTzRQqdSQ\n",
62 "s4xarQ4ICI/H84Q6ZyBcLjdwXnd3Nz3cuePFmAiIXG2inWpQczu1FnqnzkLXmx3UgBmRGJjXAX2v\n",
63 "g/8/6Lygk68fs9idYyPQ5vNs6Ngm6/9sAgAQAGqCC5jZdmDNsIFgpRmQ8bEmhYLFYgUExGg0TksB\n",
64 "GQqtVhvo4JEKSLC6ptFopp+AdGgt1A+P1CZV1CgFfQ6aAR18yI4fyXkhjo0FXjsJ3N30wQICAC4V\n",
65 "HSyXfPpu91dWyHqzFWiJEf2goyXYb2CxWG4oCyOFQgnM/h6PJ6J1QLCKNtTMNN5EvUjfc0YufHD7\n",
66 "sZnlNUohQYTNdpq+2BrYcG1jPlivTUiQo9VqDQhFsHpxIyASiQJJa2ZzZKkHwYOEUDg5SW9RCciR\n",
67 "Kwreeweuyrw4cWMKRjBeCxla30gDInIvdrQELyRFItGIPL5TnYSEhEAHj1R9DP4+EhISnOPRruEY\n",
68 "sYBUy7Ws17+5mIHfqLNGKJwdTFB8PK7WM41GQw1WKeLj44ccMV0u17Qzz6empgZ8J11dXSyHwxH2\n",
69 "M3i9XiR43ZKSkhLS9zLejPiL/vDnOqnbi0+7H2jUdO9JBNw9boPCyZMnA153CoWCFxUVmYOP0+n0\n",
70 "gAUw2GQaLURwMNYEUFhYaJFIJHYAnxOxurqaH+78y5cvc/0ziEQiccyZM8cc7vzxYkQdvUllol/r\n",
71 "6uUMf+ZomYLxWLgdhd4T3KgvD+MJtlqt6Llz50T+1yUlJdqB0bopKSkBn8iJEyeGTZgZGNU6EIFA\n",
72 "EFjjGI3GCYlyXrt2bSA269ChQ4lWq3XIVN+KiorA97Fu3TrVZBWVGNFT95yRj08m0wTBpJF9nc5r\n",
73 "jy4HW3806kITr7zySkF5eblgYESu3W5Ht23blmUymagAvtmjtLR0UATr7NmzA57nuro6/q5du5JD\n",
74 "qSk1NTXsN998M1elUoX1xMtksoDKolarmd3d3eNuVi4pKTGmpqZaAQB0Oh39ww8/TB84cOA4Dp9+\n",
75 "+mlKY2MjHwAgIyPDUlJSYhzvtg1FxKZEHAcor1MJxrMxoyKCSSdbKvJ1CnuUYRymaj4QRFQVJvR6\n",
76 "Pf3LL79M379/f7JUKrXHx8c7tVotXS6Xc/yh5kwmE9u0aVOLSCQaZMFatWqVXi6Xsy9cuCACADh1\n",
77 "6lTCpUuXBOnp6VaBQOA2Go0UhULBMhgMg2KNEAQZ9O1wOBzvihUrusvLyyUYhpG2b9+eM2fOHENB\n",
78 "QYG5oKDAOh4jNolEghdeeKF5x44dadeuXYtramrivfzyyzOzs7PN6enpNpVKxWhubuao1WomgC8Q\n",
79 "8bHHHusY84aMgIgFpF1rptmc2LS2zRekiX1qir2JFdUNcDsKjlYaMDNHbHLcsmVL4+HDhxMaGhr4\n",
80 "jY2NvMbGxn6xRUKh0Ll58+YWqVQ65L0fffTRToFA4C4rK5NgGEay2WwUf1iHH6lUaisuLu5tbGzk\n",
81 "NDU18QAAhsqou//++1Verxc5c+ZMvMFgoJWVlSWWlZUlRpKQFS00Gg3fvHlz6zfffJNUUVGRYDAY\n",
82 "aFVVVfH+KF8AACqV6l2zZo16qFyQiSTiDn+1XR9dp5oisBhkrChTYgOCAHC2Rx8IaL3GjEZA8vPz\n",
83 "rfn5+VaFQkFvaGhgaTQautVqJctkMltBQYE1OTl5WDMmmUwmNmzYoF6xYoWutraW7Q+/4PP5nri4\n",
84 "OI9MJnP403ffeeedwFoxOOQ8GBRFiYcfflixdu3anqamJlZPTw/N5XKhdDo9IFCFhYXmzZs3NwEA\n",
85 "cDicYUOF1q1b17148WI9AEBSUlLIz0QikeD+++9XbdiwQd3W1sZobm5mdXd305OSkhw5OTk2mUzm\n",
86 "CDeDLVy40OhXEYPXUkOxcePGdrfbTQrXpqGIWEDqlMYpF106Ev5w16IuNoOGg6GMB7gj+jpQtnoW\n",
87 "wF1hI1HDkZyc7IxEGMIhFAo9N998c9g26PX6gKrFYrHCzgZCodCzaNGikHo+n8/H+Hy+JdSxUKSk\n",
88 "pDhTUlIi+nwoihJZWVn2rKysEQVlxsfHu+Pj4yP2E+Xl5dlGcv9gIlY0WzWWaVsyZ26u1HjP0gID\n",
89 "eIwoKD4YXRVBe/OUHyhwHIfe3t6AgITLL48RnohnkF7r4GqIE8IoLb4rZqfr//TbZb4Q+863UwEz\n",
90 "je5zuDVTPohQp9NR/dYyiURiH6/03V8DEQuI1emZVgt0cRzLtemO+Yq1C3J8qoP6Xwlgqhy9FQ4z\n",
91 "T/nvoaurK+CBzs/PjyqHIoaPUQjI2AxKCAAkCdjO7CS+LUPCc6AoQvTdeuAzCICQ9hhfBDAZJREZ\n",
92 "SXHOWWliO5/D8KkVLjUFOramga0maidfP3AnCl4nCVD6lCxkajQayV9//XUqgM+8u2DBgqjXSzEi\n",
93 "FBCvF0cw79gGJgo5DPczpbO7FhckWTgM2tjryI52GpgrudD9b+moFuWh8OjIgCZPqWBCj8eDlJWV\n",
94 "iY4ePSoxm81UAIC77767KzMzc1JimG4UIhIQFCURdArqdXq8Y9LRVhel6l7aME8REAyXggb2eia4\n",
95 "2hm+qNng5KoBs0hw7sagxCovAq4OBthbmYDbyb773Jjqt8vlIp0+fTquo6ODqVQqmWq1mukPdqTT\n",
96 "6VhpaanqtttuG58KfL8iIlax2HTKqAUEAYA/318iXzc/w7cuMB6LA83uFPBaKP06/sCkqUGJVUP9\n",
97 "23/tOAsFRTSsPwBFUUIoFDr1ev24ZMKRyWRi3759Kf7icAiCEGKx2JGXl2dev369erwcfb82RiIg\n",
98 "mM7iHJUF586SjJ518zOMgJlR6P5nKliqBVMyMDEcJBoeyfqDTCYTW7durW1paWFWVo6BcWAAKIoS\n",
99 "t9xyixpFUSI9Pd2WmZnpGEm9pxiREbGACDk0d7vWErUPQCpkOZ9bX6wCAADl2+ngqJ+euz6hI8v0\n",
100 "i8YRFil33nnnpIdi3OhE7CjMSuSNarH3yr0L2ukUMg6GA6JpKxwAAIzQRdNiTF3MNgf69ZEq4b8O\n",
101 "nhENf3Z/Ip5B8qT866PgyFUiLpPqmZeZYAOvBQXt18kjvsFUgjsn4rCLGFODl//5rez0L81xty6a\n",
102 "qQMA3UiujXgGmZnCj1pNyE6K88XC2BuYQEzz/fC482MCMs3AvL5qimTSyLcEj1hAUkUcN4dOGb7w\n",
103 "W4gmzEiO8wmXs2VaRwQDysaAPTOmYk0zsOthNyg6jgICALA4LyEqr2xO0vXZxzX6XOpJRbDCMG7b\n",
104 "8cYYN7z+GSSKmLQRCci6ualRbV9GRq9ntBHTrxpHPxLuiTnepiF+FQsdTxULAGB+ltgm4TMmpT7R\n",
105 "pMPMsQIr79f52ac5/hkERUc+Po/4is23zxy0WcmvguTfqya7CTGiw4v7VayRzyAjDt1ePSvZVHFN\n",
106 "pTt6VTFim/K0hX+zHuKWjMp6pek1k89caeGotL3Ubr2JKhHy3HNnpFnn5MrsNEr4rQA0vWbyxfp2\n",
107 "Vk2LkuXBMKQwK9k2Ny/NJhXHDXJa2hwu0uGzV/kpCUJXycyMkJl0ap2Rsq/ikuC3ty7U8TmD03Fr\n",
108 "W5WMK01dzLuWzellMfp7501WB1p1Tc6ub1MzUhOFrtnZKfZ06dBF7vxgXhyplSsYV5q7mLWtKpbJ\n",
109 "aifftqjQsH558aB1bV2bil51Tc7xYF6kIENqn52Tah/YjoGYrA70fG0rq7q+neP2YIhUHOdaUJBu\n",
110 "nZWV4sD6ZpCJ2cTzpbvndCn0Vnq90siO5vppBTXBBWl/jHrWvNTQwfz4h5OSc9fkfP9UH2DfCUhL\n",
111 "FNl3/nljsziOG9JCuOvgGdH7e46leLC+TUD3HrsACAKwcd0S5TMPrOkmBRkOHv7Lzly5QsNcNX+G\n",
112 "PpSAlF2o4/7xva+zCQIgns/x3Lt6/qCt3vaf/EXw9ZEqybLiXHNwx3z3i58Sdx+uTCQIAiGREAK/\n",
113 "Xnr2jqWzNa8+dqeCGkLQPZgX+eLwWdGXP51L0PRaAlmOCIIQW357qzL43Dallrbpb7uy1DoT3X8O\n",
114 "QRCIkMd2/23zva3z89NDCvyFujbWs9u+zLLaXWQAgOC2yRKFDr3JV4AuGjNvVALCplPwT/6wvPHj\n",
115 "soaEXRWNSRh2g1Za5C3shcy/dgCZG1Xg3+5DZ0XbvzqSCgBw28KZupuLc015skSHWMDFTv/SxHnr\n",
116 "84OydrWO+ch/fpK7+7XfNwi4/XPHX/zgG9lPlTUiBo3i/cO9KztXzJ1hwrxe5Oj5Ov6n+08lffbj\n",
117 "aWldm4q14+X/JfcLybwZaWa5QsOsqm3lYV4cGahWlJ2v4/tjOY9X1/NDCUjl1RZehjTeHjxD/eWj\n",
118 "71O+P3FJnJUstr36+F0dBRlSZ61cwfjTh9+l/XjqF7HZ5iC///xDbcH3MVrs6Oa3v8i82qLg0Chk\n",
119 "fMOqeT2Fmck2iYjndro8pFyZJLCmq2tT0Z/auivHZHOQn/jNcsUDt5boUBIJ/v1Tpeij7yqSn3jr\n",
120 "X7m7/vp4/cxMaT8z+4lLjZz/8/c9WS4PRpqTm2p+fP0y9YKCDFtnt556/EI978ufz0n8gjNhMwgA\n",
121 "AEoiwRNr8nvWFct6q+UaVpPayGzrNjMcLn992b4oWx6LPjaRpeQ4N5CFrpDh7kNG84aLEIaga/37\n",
122 "g8S7gZFlB3a+HXglw+7THY4vDldKvF4ceeLu5YqnNqzsFzd1y8KZJomI1/y7v+zMV2h66V/+dE70\n",
123 "9H2rAuccOnOV91NljYhCRvGdf3qksTArOdAxslISetKTRM6X/vFtZtW1Vv63ZRcE961eYAAAWL0g\n",
124 "37jn6HmJ1e4iV15tYS+dk9NPNTx3rTUQ5nOxoZ3ncLlJDFrf1gKd3XpqR7ee8fDamwJrrjNXmtnf\n",
125 "n7gkBgDY/tyDrakSoRsAoCgn1f7PF/6j5c4/vl948nJTXJtSqwpWt9776kji1RYFR8BluXf/5+ON\n",
126 "yQmCIXNo3vrsQGqvxU5ZvSBf/9S9fd/VUxtW9sgVGsax83XCz348lfDusw+0+495MC/yxqc/ylwe\n",
127 "jJSeJLL/44WH5ezrM15mstiVmSzWPFx6k7b02e0zdUYrNRoz76jTR6VCllsqTHcDwPhnrvFu1kPi\n",
128 "49Nmsex3UNEo5JD686ysFMeMtCRrXZuKvf/k5fin7l3ZQ0IQcHkw5L2vjqQAAKycN8MQLBx+bltU\n",
129 "aNpXccl0rkbO/+i7Culdy4p7aRQyMS8/3cZnMzxGq4NSdqGOFywgV5o6mXqTlbpiXp6+vLpB6HJj\n",
130 "pIqLDZzbb5oVSMs9WlXLAwBYNX9G4L0vfz4nBgDIShHb/MLhR5YocicIuK4eg5m25+h54UsbSwO/\n",
131 "j9vjK4gXx2Vh4YSjrk1Fv9qi4AAArF6QP6gfLSjIMB87XyesuNggsNidnRymL5r627JqgcZgpgEA\n",
132 "PH3faiU7xDqFTqUQpOuF88bdUTjpYEYy2OqZfX91Q/zV9v1Zg/6cnSPa4XS0BBxU5KFHrvkF6WYA\n",
133 "gB6DmdbYrqYDAFxt7mL2XP/h1y6eNeR20LctKjQAAOiMVmpDm4oBAEBCECgpzDQBAJy52tKvQHRZ\n",
134 "tS9I9Pe/Wd6dKOI5AQCOX6jvd87pK808AZflmZMrswMAuD0YUnlVzgcAWDlvRshBMD8jyQoA0KUx\n",
135 "9Mt9CYR4DNMxD56+IgAAoFHJ+Ip5MwYVqfavPTAvjnSo+8oZHTpzRQjgK3Q51PqkXzuiqBY55QsQ\n",
136 "9MN0Ih6MFfGRJ0wN+De72AjZ78gnqrkB82KYxaGQywro+Wq9iTojPclZf72zAwAMHLGDSUmICxxr\n",
137 "VeloRTmpdgCAlfNmGH+uvCbSGMy0a3Ilw6+3n7nSzEsQcF356UnOJUU5xm/KLviMBzjegZJIYHW4\n",
138 "SDUtCs7qBfkBh3C7Wkfzf45DZ66KTlxqjAMAgoQggFxf92iNvm3j9Mb+G2X6rxvOQdfZ3Vcu9eFX\n",
139 "/ycXQRACQRBAAALPCHxHOiPF/3kUGl9po1SJ0MFjM4ZU4wO/Q5iBaiiml4BMM7AIHFRsZt/6rFvv\n",
140 "K0nUptIFRuL4OM6Q+Sc8Vt+mqEpNbyCZbVlxroVGIeMuD0Y6WlXLn5kpdXTrTZSWLg3r7hVzewAA\n",
141 "Vi3IN31TdkFitjnJ52rk7MVF2daKiw1cD+YlLZ+bF1Cv2pS6QOdNlQgdDNrgraATRTwXAICQ17+t\n",
142 "fhVzuBlEpfV1dC6LgaUkCEI6Y/3P8FvVbA4XyWC2UQEAZmYmh10r+o1I0XjSYwIyjvhVLEqYkcvt\n",
143 "6TPfErjvtGChaVVqaUXZoTeP6bXYAr+fWNDXORk0Kl6cJzNX1sj5p39p4m357S3qY+fr/GsLIwDA\n",
144 "goJ0K4/N8JisDsrRqlr+4qJs68lLjTwqhYwvK84NrFs8QdXon75vlbogQxpxsCYWYQyUf4SXJQod\n",
145 "27Y82B7JvYPXE8N1fAyPTFBDMb3WIJGATJ26blgEKoa2t2+/Pr8FKFHEC6hOjR3qIQM8e/R912an\n",
146 "9N+i7ObiXCMAQItCw1JpeymnfmnisZk0bGFhlu16m2DhzOtrlSvNfJwgoKq2lTcnJ9UcbNXKShYH\n",
147 "7mu1jyyWzhuhgy5VInQCADicnojvT6dSCA7Tt6lQU2d32EzXSNsRihtHQOgZAKkvAczcB5D1DgC3\n",
148 "ZLJbFBRFOvQPE6xOZaf6OnlwZ2/u7BlSQJoVvmM0ChnPSZX0E5BbSmaa/Nse7D/5S9zlhg7ugvwM\n",
149 "U3BbVl6fTTS9Ftq/D1eKjBY7ZemcnH6F5jKk8S4SyXef2lbliFKuI12kpyfFOwEAunr0DJcHizhc\n",
150 "2q92tSm1TGygEzYI/wxFGe9o3tEzjqHishcB4lYAkCgA7CKAtFcB0LGpFRcNHqxPNRlqcWi2OdAz\n",
151 "V5vjAADm5qWZ4vm+6unz89Nt2SkJNgCAps6ekJ0SJwg4fLZGCABwz8p5PQNDMUR8NjYjLdEGALD7\n",
152 "8NlElwfrt7YA6FurAADs+K5cCgCwekFBv3OoFDKRIY23AwB8V35xRBsoRTpyF+fJrAAAZpuT/H3F\n",
153 "pYg3KVq7eJYeAMDlwUi1rcqQ1WO8OB6w00z9GYQyfMxOVLBmAdDT+r9HogII1/Z/jyqZsK2EgwXk\n",
154 "5OUmntHSf1crL47DXz76PsXl9vkKnrxnuTr4+KN3LlUDAPzS1Mn95tiFQVVRdnxbnqAxmGlsJg17\n",
155 "8p4VIYs3LJ3jK7tqtbvIZJRErAzybQD0rVX852SliG2JIt4go8BrT/ymg0JG8a4eA2Pr5weTQj3r\n",
156 "aksX40pzV7/ZLtJF+rLiXMuakgIdAMCO/1curWtTDersJqsDPXjmCh8PcgLfu3qBnkmnegEA3vhk\n",
157 "vyzU7FNe3RAYJf3+k5EwsYt0Rq4NjGVjf198iGzgge+zCqIugz9SggXk4Okr8ccv1AtuLs7pzUoW\n",
158 "O5xujHTyUiO/uauHBQDwxN3LFQsK+sdNrV08y9TRrVd89F158t92HZI1dfYwlszONlvsTrTiYgPv\n",
159 "aFWtSMRnu7c9+4B8KBPnLSUFxo++q0gGACjKTjWH6iDL5+YZK2t8fo7FRdkh6/gWZEgdT9+7SrH9\n",
160 "qyOpXx2pSmzq7GHeVJRliudzsHM1ck5VbStPb7JS581IM33yfx9t8V/nvW50iMSD/dffr++6Jlew\n",
161 "1ToT/bHXP8srXVKknZkptat0RurZK8282lYV24vjiDiO2+D3ebAZNPzdZx9o2bLtq6ymzh7WY69/\n",
162 "mn3nzXN0yQkCd0O7inHkXK2grk3FnpGWaH3uoVsHfceRMMECUjCq0I0hcbQA2OoBWDP63vPaAQxH\n",
163 "+5/HmTM+zw9BsIBsvn91Z0O7mnmsqk74c+W1wPsiPtv91IaVintWzgvpgNt0z4oemUTo/O9vj0u/\n",
164 "KTsv2XvsvAQAgEGjektmZhhff/LujgRB6CBHAICslARXsjjOaXe60Q2r5oVM9lpTUmD6265DRLJY\n",
165 "4Fy3pGjIaIiNdyzRshg0747vyqUXG9p5FxvaAyErSSK+87mHbu144JaSfgl1I0l1ZTNo+Cd/frTp\n",
166 "7S8OS8urG4R7j52X7D3mO0Yho/jNxTmGJ36zvHtGev8NcG6alWV9//mHmv9r96GUGrmS7ffIC7gs\n",
167 "T4Y03v7mprvl65bOjnqPQ4QgiOpoL46K7o+lYPxJAgBDV0mMprIiWQggvAMgbhWA9TKA9juf4Pin\n",
168 "5LhVWkh7pXNcP1sQap2Jctsz784CAHj/+YealhXnWowWOypXaGiaXjOlIEPqCOcEHIjZ5kCvNncx\n",
169 "4uO4WHZqgpMUYepvZ7eeKhXHudEw4OU8RgAAAbxJREFUXuR2lY6aliSKqC1eHAdFj4HaqtTSeGym\n",
170 "NytF7OKyQs9gLg+G4DiOkFGUCGfqHojZ5kDlCg2t12InZyTFO1MkgrDt92O02NH6djUjK0Xs9K/n\n",
171 "RsvECwjhRaDjT9ngbOGMqYCE86QzMm2Q849GIFEnrIxjV4+Bum7Le4UAAP/94sONi4uyJ2z2ijF2\n",
172 "TLyZF0EJSH5ZDqy5Q8YYjSmsmWbIeEM+kcIB0F/FGsnoGWNqMTmedDLPCykvt4HpRC/0fJYKXvPY\n",
173 "716FsjFIfLQLRHdMjCAOwB1kUYkJyPRlckNNeMuMwL3JBKbTPDAeE4G9jje6YtYIADPfDHGr9CBY\n",
174 "bQTS5G1yEzyDRGN/jzE1mPxYLIRCAH+FEfgrjOAxkMF2lQ32OjY4mlng6mKGLRWEUHGgp9mAmWMD\n",
175 "Zr4V2EU2oAjGZHE2WrCgGKZoPLgxpgaTLyDBUAQY8Jcbgb+8zyzntZHAo6cAZiAD7iYByvICyvEC\n",
176 "mesFlIsBMjWjZThMulfEZ7t1Ris1pmJNXybeivUrAicIOHulmV2YlRI2XyHG1CUmIDFihGFq6icx\n",
177 "YkwRYgISI0YYYgISI0YY/j+SFgT3yDrlYgAAAABJRU5ErkJggg==\n"
178 ],
179 "text/plain": [
180 "<IPython.core.display.Image object>"
181 ]
182 },
183 "execution_count": 2,
184 "metadata": {},
185 "output_type": "execute_result"
186 }
187 ],
188 "source": [
189 "Image('python.png')"
190 ]
191 }
192 ],
193 "metadata": {},
194 "nbformat": 4,
195 "nbformat_minor": 0
196 }
@@ -1,49 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [
10 {
11 "ename": "KeyboardInterrupt",
12 "evalue": "",
13 "output_type": "error",
14 "traceback": [
15 "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
16 "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
17 "\u001b[0;32m<ipython-input-1-31d18a52bf41>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mwhile\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
18 "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
19 ]
20 }
21 ],
22 "source": [
23 "while True: continue"
24 ]
25 },
26 {
27 "cell_type": "code",
28 "execution_count": 2,
29 "metadata": {
30 "collapsed": false
31 },
32 "outputs": [
33 {
34 "name": "stdout",
35 "output_type": "stream",
36 "text": [
37 "done\n"
38 ]
39 }
40 ],
41 "source": [
42 "print(\"done\")"
43 ]
44 }
45 ],
46 "metadata": {},
47 "nbformat": 4,
48 "nbformat_minor": 0
49 }
@@ -1,48 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [],
10 "source": [
11 "from IPython.display import SVG"
12 ]
13 },
14 {
15 "cell_type": "code",
16 "execution_count": 2,
17 "metadata": {
18 "collapsed": false
19 },
20 "outputs": [
21 {
22 "data": {
23 "image/svg+xml": [
24 "<svg height=\"100\" width=\"100\">\n",
25 " <circle cx=\"50\" cy=\"50\" fill=\"red\" r=\"40\" stroke=\"black\" stroke-width=\"2\"/>\n",
26 "</svg>"
27 ],
28 "text/plain": [
29 "<IPython.core.display.SVG object>"
30 ]
31 },
32 "execution_count": 2,
33 "metadata": {},
34 "output_type": "execute_result"
35 }
36 ],
37 "source": [
38 "SVG(data='''\n",
39 "<svg height=\"100\" width=\"100\">\n",
40 " <circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"2\" fill=\"red\" />\n",
41 "</svg>''')"
42 ]
43 }
44 ],
45 "metadata": {},
46 "nbformat": 4,
47 "nbformat_minor": 0
48 } No newline at end of file
@@ -1,51 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [
10 {
11 "ename": "Exception",
12 "evalue": "message",
13 "output_type": "error",
14 "traceback": [
15 "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
16 "\u001b[1;31mException\u001b[0m Traceback (most recent call last)",
17 "\u001b[1;32m<ipython-input-1-335814d14fc1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"message\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
18 "\u001b[1;31mException\u001b[0m: message"
19 ]
20 }
21 ],
22 "source": [
23 "raise Exception(\"message\")"
24 ]
25 },
26 {
27 "cell_type": "code",
28 "execution_count": 2,
29 "metadata": {
30 "collapsed": false
31 },
32 "outputs": [
33 {
34 "name": "stdout",
35 "output_type": "stream",
36 "text": [
37 "ok\n"
38 ]
39 }
40 ],
41 "source": [
42 "print('ok')"
43 ]
44 }
45 ],
46 "metadata": {
47 "signature": "sha256:9d47889f0678e9685429071216d0f3354db59bb66489f3225bcadfb6a1a9bbba"
48 },
49 "nbformat": 4,
50 "nbformat_minor": 0
51 } No newline at end of file
@@ -1,26 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "code",
5 "execution_count": 1,
6 "metadata": {
7 "collapsed": false
8 },
9 "outputs": [
10 {
11 "name": "stdout",
12 "output_type": "stream",
13 "text": [
14 "\u2603\n"
15 ]
16 }
17 ],
18 "source": [
19 "print('\u2603')"
20 ]
21 }
22 ],
23 "metadata": {},
24 "nbformat": 4,
25 "nbformat_minor": 0
26 } No newline at end of file
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
@@ -1,33 +0,0 b''
1 """
2 Module with tests for the clearoutput preprocessor.
3 """
4
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 from .base import PreprocessorTestsBase
9 from ..clearoutput import ClearOutputPreprocessor
10
11
12 class TestClearOutput(PreprocessorTestsBase):
13 """Contains test functions for clearoutput.py"""
14
15
16 def build_preprocessor(self):
17 """Make an instance of a preprocessor"""
18 preprocessor = ClearOutputPreprocessor()
19 preprocessor.enabled = True
20 return preprocessor
21
22 def test_constructor(self):
23 """Can a ClearOutputPreprocessor be constructed?"""
24 self.build_preprocessor()
25
26 def test_output(self):
27 """Test the output of the ClearOutputPreprocessor"""
28 nb = self.build_notebook()
29 res = self.build_resources()
30 preprocessor = self.build_preprocessor()
31 nb, res = preprocessor(nb, res)
32 assert nb.cells[0].outputs == []
33 assert nb.cells[0].execution_count is None
@@ -1,58 +0,0 b''
1 """Tests for the coalescestreams preprocessor"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from IPython.nbformat import v4 as nbformat
7
8 from .base import PreprocessorTestsBase
9 from ..coalescestreams import coalesce_streams
10
11
12 class TestCoalesceStreams(PreprocessorTestsBase):
13 """Contains test functions for coalescestreams.py"""
14
15 def test_coalesce_streams(self):
16 """coalesce_streams preprocessor output test"""
17 nb = self.build_notebook()
18 res = self.build_resources()
19 nb, res = coalesce_streams(nb, res)
20 outputs = nb.cells[0].outputs
21 self.assertEqual(outputs[0].text, "a")
22 self.assertEqual(outputs[1].output_type, "display_data")
23 self.assertEqual(outputs[2].text, "cd")
24 self.assertEqual(outputs[3].text, "ef")
25
26 def test_coalesce_sequenced_streams(self):
27 """Can the coalesce streams preprocessor merge a sequence of streams?"""
28 outputs = [nbformat.new_output(output_type="stream", name="stdout", text="0"),
29 nbformat.new_output(output_type="stream", name="stdout", text="1"),
30 nbformat.new_output(output_type="stream", name="stdout", text="2"),
31 nbformat.new_output(output_type="stream", name="stdout", text="3"),
32 nbformat.new_output(output_type="stream", name="stdout", text="4"),
33 nbformat.new_output(output_type="stream", name="stdout", text="5"),
34 nbformat.new_output(output_type="stream", name="stdout", text="6"),
35 nbformat.new_output(output_type="stream", name="stdout", text="7")]
36 cells=[nbformat.new_code_cell(source="# None", execution_count=1,outputs=outputs)]
37
38 nb = nbformat.new_notebook(cells=cells)
39 res = self.build_resources()
40 nb, res = coalesce_streams(nb, res)
41 outputs = nb.cells[0].outputs
42 self.assertEqual(outputs[0].text, u'01234567')
43
44 def test_coalesce_replace_streams(self):
45 """Are \\r characters handled?"""
46 outputs = [nbformat.new_output(output_type="stream", name="stdout", text="z"),
47 nbformat.new_output(output_type="stream", name="stdout", text="\ra"),
48 nbformat.new_output(output_type="stream", name="stdout", text="\nz\rb"),
49 nbformat.new_output(output_type="stream", name="stdout", text="\nz"),
50 nbformat.new_output(output_type="stream", name="stdout", text="\rc\n"),
51 nbformat.new_output(output_type="stream", name="stdout", text="z\rz\rd")]
52 cells=[nbformat.new_code_cell(source="# None", execution_count=1,outputs=outputs)]
53
54 nb = nbformat.new_notebook(cells=cells)
55 res = self.build_resources()
56 nb, res = coalesce_streams(nb, res)
57 outputs = nb.cells[0].outputs
58 self.assertEqual(outputs[0].text, u'a\nb\nc\nd')
@@ -1,47 +0,0 b''
1 """
2 Module with tests for the csshtmlheader preprocessor
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from .base import PreprocessorTestsBase
18 from ..csshtmlheader import CSSHTMLHeaderPreprocessor
19
20
21 #-----------------------------------------------------------------------------
22 # Class
23 #-----------------------------------------------------------------------------
24
25 class TestCSSHTMLHeader(PreprocessorTestsBase):
26 """Contains test functions for csshtmlheader.py"""
27
28
29 def build_preprocessor(self):
30 """Make an instance of a preprocessor"""
31 preprocessor = CSSHTMLHeaderPreprocessor()
32 preprocessor.enabled = True
33 return preprocessor
34
35
36 def test_constructor(self):
37 """Can a CSSHTMLHeaderPreprocessor be constructed?"""
38 self.build_preprocessor()
39
40
41 def test_output(self):
42 """Test the output of the CSSHTMLHeaderPreprocessor"""
43 nb = self.build_notebook()
44 res = self.build_resources()
45 preprocessor = self.build_preprocessor()
46 nb, res = preprocessor(nb, res)
47 assert 'css' in res['inlining']
@@ -1,151 +0,0 b''
1 """
2 Module with tests for the execute preprocessor.
3 """
4
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 import copy
9 import glob
10 import io
11 import os
12 import re
13
14 try:
15 from queue import Empty # Py 3
16 except ImportError:
17 from Queue import Empty # Py 2
18
19 from IPython import nbformat
20
21 from .base import PreprocessorTestsBase
22 from ..execute import ExecutePreprocessor
23
24 from jupyter_nbconvert.filters import strip_ansi
25 from nose.tools import assert_raises
26
27 addr_pat = re.compile(r'0x[0-9a-f]{7,9}')
28
29 class TestExecute(PreprocessorTestsBase):
30 """Contains test functions for execute.py"""
31
32 @staticmethod
33 def normalize_output(output):
34 """
35 Normalizes outputs for comparison.
36 """
37 output = dict(output)
38 if 'metadata' in output:
39 del output['metadata']
40 if 'text' in output:
41 output['text'] = re.sub(addr_pat, '<HEXADDR>', output['text'])
42 if 'text/plain' in output.get('data', {}):
43 output['data']['text/plain'] = \
44 re.sub(addr_pat, '<HEXADDR>', output['data']['text/plain'])
45 if 'traceback' in output:
46 tb = []
47 for line in output['traceback']:
48 tb.append(strip_ansi(line))
49 output['traceback'] = tb
50
51 return output
52
53
54 def assert_notebooks_equal(self, expected, actual):
55 expected_cells = expected['cells']
56 actual_cells = actual['cells']
57 self.assertEqual(len(expected_cells), len(actual_cells))
58
59 for expected_cell, actual_cell in zip(expected_cells, actual_cells):
60 expected_outputs = expected_cell.get('outputs', [])
61 actual_outputs = actual_cell.get('outputs', [])
62 normalized_expected_outputs = list(map(self.normalize_output, expected_outputs))
63 normalized_actual_outputs = list(map(self.normalize_output, actual_outputs))
64 self.assertEqual(normalized_expected_outputs, normalized_actual_outputs)
65
66 expected_execution_count = expected_cell.get('execution_count', None)
67 actual_execution_count = actual_cell.get('execution_count', None)
68 self.assertEqual(expected_execution_count, actual_execution_count)
69
70
71 def build_preprocessor(self, opts):
72 """Make an instance of a preprocessor"""
73 preprocessor = ExecutePreprocessor()
74 preprocessor.enabled = True
75 for opt in opts:
76 setattr(preprocessor, opt, opts[opt])
77 return preprocessor
78
79
80 def test_constructor(self):
81 """Can a ExecutePreprocessor be constructed?"""
82 self.build_preprocessor({})
83
84
85 def run_notebook(self, filename, opts, resources):
86 """Loads and runs a notebook, returning both the version prior to
87 running it and the version after running it.
88
89 """
90 with io.open(filename) as f:
91 input_nb = nbformat.read(f, 4)
92 preprocessor = self.build_preprocessor(opts)
93 cleaned_input_nb = copy.deepcopy(input_nb)
94 for cell in cleaned_input_nb.cells:
95 if 'execution_count' in cell:
96 del cell['execution_count']
97 cell['outputs'] = []
98 output_nb, _ = preprocessor(cleaned_input_nb, resources)
99 return input_nb, output_nb
100
101 def test_run_notebooks(self):
102 """Runs a series of test notebooks and compares them to their actual output"""
103 current_dir = os.path.dirname(__file__)
104 input_files = glob.glob(os.path.join(current_dir, 'files', '*.ipynb'))
105 for filename in input_files:
106 if os.path.basename(filename) == "Disable Stdin.ipynb":
107 continue
108 elif os.path.basename(filename) == "Interrupt.ipynb":
109 opts = dict(timeout=1, interrupt_on_timeout=True)
110 else:
111 opts = {}
112 res = self.build_resources()
113 res['metadata']['path'] = os.path.dirname(filename)
114 input_nb, output_nb = self.run_notebook(filename, opts, res)
115 self.assert_notebooks_equal(input_nb, output_nb)
116
117 def test_empty_path(self):
118 """Can the kernel be started when the path is empty?"""
119 current_dir = os.path.dirname(__file__)
120 filename = os.path.join(current_dir, 'files', 'HelloWorld.ipynb')
121 res = self.build_resources()
122 res['metadata']['path'] = ''
123 input_nb, output_nb = self.run_notebook(filename, {}, res)
124 self.assert_notebooks_equal(input_nb, output_nb)
125
126 def test_disable_stdin(self):
127 """Test disabling standard input"""
128 current_dir = os.path.dirname(__file__)
129 filename = os.path.join(current_dir, 'files', 'Disable Stdin.ipynb')
130 res = self.build_resources()
131 res['metadata']['path'] = os.path.dirname(filename)
132 input_nb, output_nb = self.run_notebook(filename, {}, res)
133
134 # We need to special-case this particular notebook, because the
135 # traceback contains machine-specific stuff like where IPython
136 # is installed. It is sufficient here to just check that an error
137 # was thrown, and that it was a StdinNotImplementedError
138 self.assertEqual(len(output_nb['cells']), 1)
139 self.assertEqual(len(output_nb['cells'][0]['outputs']), 1)
140 output = output_nb['cells'][0]['outputs'][0]
141 self.assertEqual(output['output_type'], 'error')
142 self.assertEqual(output['ename'], 'StdinNotImplementedError')
143 self.assertEqual(output['evalue'], 'raw_input was called, but this frontend does not support input requests.')
144
145 def test_timeout(self):
146 """Check that an error is raised when a computation times out"""
147 current_dir = os.path.dirname(__file__)
148 filename = os.path.join(current_dir, 'files', 'Interrupt.ipynb')
149 res = self.build_resources()
150 res['metadata']['path'] = os.path.dirname(filename)
151 assert_raises(Empty, self.run_notebook, filename, dict(timeout=1), res)
@@ -1,58 +0,0 b''
1 """Tests for the extractoutput preprocessor"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import PreprocessorTestsBase
7 from ..extractoutput import ExtractOutputPreprocessor
8
9
10 class TestExtractOutput(PreprocessorTestsBase):
11 """Contains test functions for extractoutput.py"""
12
13 def build_preprocessor(self):
14 """Make an instance of a preprocessor"""
15 preprocessor = ExtractOutputPreprocessor()
16 preprocessor.extract_output_types = {'text/plain', 'image/png', 'application/pdf'}
17 preprocessor.enabled = True
18 return preprocessor
19
20 def test_constructor(self):
21 """Can a ExtractOutputPreprocessor be constructed?"""
22 self.build_preprocessor()
23
24 def test_output(self):
25 """Test the output of the ExtractOutputPreprocessor"""
26 nb = self.build_notebook()
27 res = self.build_resources()
28 preprocessor = self.build_preprocessor()
29 nb, res = preprocessor(nb, res)
30 # Check if text was extracted.
31 output = nb.cells[0].outputs[1]
32 self.assertIn('filenames', output.metadata)
33 self.assertIn('text/plain', output.metadata.filenames)
34 text_filename = output.metadata.filenames['text/plain']
35
36 # Check if png was extracted.
37 output = nb.cells[0].outputs[6]
38 self.assertIn('filenames', output.metadata)
39 self.assertIn('image/png', output.metadata.filenames)
40 png_filename = output.metadata.filenames['image/png']
41
42 # Check that pdf was extracted
43 output = nb.cells[0].outputs[7]
44 self.assertIn('filenames', output.metadata)
45 self.assertIn('application/pdf', output.metadata.filenames)
46 pdf_filename = output.metadata.filenames['application/pdf']
47
48 # Verify text output
49 self.assertIn(text_filename, res['outputs'])
50 self.assertEqual(res['outputs'][text_filename], b'b')
51
52 # Verify png output
53 self.assertIn(png_filename, res['outputs'])
54 self.assertEqual(res['outputs'][png_filename], b'g')
55
56 # Verify pdf output
57 self.assertIn(pdf_filename, res['outputs'])
58 self.assertEqual(res['outputs'][pdf_filename], b'h')
@@ -1,50 +0,0 b''
1 """Tests for the HighlightMagics preprocessor"""
2
3 from .base import PreprocessorTestsBase
4 from ..highlightmagics import HighlightMagicsPreprocessor
5
6
7 class TestHighlightMagics(PreprocessorTestsBase):
8 """Contains test functions for highlightmagics.py"""
9
10
11 def build_preprocessor(self):
12 """Make an instance of a preprocessor"""
13 preprocessor = HighlightMagicsPreprocessor()
14 preprocessor.enabled = True
15 return preprocessor
16
17 def test_constructor(self):
18 """Can a HighlightMagicsPreprocessor be constructed?"""
19 self.build_preprocessor()
20
21 def test_tagging(self):
22 """Test the HighlightMagicsPreprocessor tagging"""
23 nb = self.build_notebook()
24 res = self.build_resources()
25 preprocessor = self.build_preprocessor()
26 nb.cells[0].source = """%%R -i x,y -o XYcoef
27 lm.fit <- lm(y~x)
28 par(mfrow=c(2,2))
29 print(summary(lm.fit))
30 plot(lm.fit)
31 XYcoef <- coef(lm.fit)"""
32
33 nb, res = preprocessor(nb, res)
34
35 assert('magics_language' in nb.cells[0]['metadata'])
36
37 self.assertEqual(nb.cells[0]['metadata']['magics_language'], 'r')
38
39 def test_no_false_positive(self):
40 """Test that HighlightMagicsPreprocessor does not tag false positives"""
41 nb = self.build_notebook()
42 res = self.build_resources()
43 preprocessor = self.build_preprocessor()
44 nb.cells[0].source = """# this should not be detected
45 print(\"""
46 %%R -i x, y
47 \""")"""
48 nb, res = preprocessor(nb, res)
49
50 assert('magics_language' not in nb.cells[0]['metadata']) No newline at end of file
@@ -1,36 +0,0 b''
1 """Tests for the latex preprocessor"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from .base import PreprocessorTestsBase
7 from ..latex import LatexPreprocessor
8
9
10 class TestLatex(PreprocessorTestsBase):
11 """Contains test functions for latex.py"""
12
13
14 def build_preprocessor(self):
15 """Make an instance of a preprocessor"""
16 preprocessor = LatexPreprocessor()
17 preprocessor.enabled = True
18 return preprocessor
19
20 def test_constructor(self):
21 """Can a LatexPreprocessor be constructed?"""
22 self.build_preprocessor()
23
24
25 def test_output(self):
26 """Test the output of the LatexPreprocessor"""
27 nb = self.build_notebook()
28 res = self.build_resources()
29 preprocessor = self.build_preprocessor()
30 nb, res = preprocessor(nb, res)
31
32 # Make sure the code cell wasn't modified.
33 self.assertEqual(nb.cells[0].source, '$ e $')
34
35 # Verify that the markdown cell wasn't processed.
36 self.assertEqual(nb.cells[1].source, '$ e $')
@@ -1,78 +0,0 b''
1 """Tests for the revealhelp preprocessor"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from IPython.nbformat import v4 as nbformat
7
8 from .base import PreprocessorTestsBase
9 from ..revealhelp import RevealHelpPreprocessor
10
11
12 class Testrevealhelp(PreprocessorTestsBase):
13 """Contains test functions for revealhelp.py"""
14
15 def build_notebook(self):
16 """Build a reveal slides notebook in memory for use with tests.
17 Overrides base in PreprocessorTestsBase"""
18
19 outputs = [nbformat.new_output(output_type="stream", name="stdout", text="a")]
20
21 slide_metadata = {'slideshow' : {'slide_type': 'slide'}}
22 subslide_metadata = {'slideshow' : {'slide_type': 'subslide'}}
23
24 cells=[nbformat.new_code_cell(source="", execution_count=1, outputs=outputs),
25 nbformat.new_markdown_cell(source="", metadata=slide_metadata),
26 nbformat.new_code_cell(source="", execution_count=2, outputs=outputs),
27 nbformat.new_markdown_cell(source="", metadata=slide_metadata),
28 nbformat.new_markdown_cell(source="", metadata=subslide_metadata)]
29
30 return nbformat.new_notebook(cells=cells)
31
32
33 def build_preprocessor(self):
34 """Make an instance of a preprocessor"""
35 preprocessor = RevealHelpPreprocessor()
36 preprocessor.enabled = True
37 return preprocessor
38
39
40 def test_constructor(self):
41 """Can a RevealHelpPreprocessor be constructed?"""
42 self.build_preprocessor()
43
44
45 def test_reveal_attribute(self):
46 """Make sure the reveal url_prefix resources is set"""
47 nb = self.build_notebook()
48 res = self.build_resources()
49 preprocessor = self.build_preprocessor()
50 nb, res = preprocessor(nb, res)
51 assert 'reveal' in res
52 assert 'url_prefix' in res['reveal']
53
54
55 def test_reveal_output(self):
56 """Make sure that the reveal preprocessor """
57 nb = self.build_notebook()
58 res = self.build_resources()
59 preprocessor = self.build_preprocessor()
60 nb, res = preprocessor(nb, res)
61 cells = nb.cells
62
63 # Make sure correct metadata tags are available on every cell.
64 for cell in cells:
65 assert 'slide_type' in cell.metadata
66
67 # Make sure slide end is only applied to the cells preceeding slide
68 # cells.
69 assert 'slide_helper' in cells[1].metadata
70 self.assertEqual(cells[1].metadata['slide_helper'], '-')
71
72 # Verify 'slide-end'
73 assert 'slide_helper' in cells[0].metadata
74 self.assertEqual(cells[0].metadata['slide_helper'], 'slide_end')
75 assert 'slide_helper' in cells[2].metadata
76 self.assertEqual(cells[2].metadata['slide_helper'], 'slide_end')
77 assert 'slide_helper' in cells[3].metadata
78 self.assertEqual(cells[3].metadata['slide_helper'], 'subslide_end')
@@ -1,73 +0,0 b''
1 """Tests for the svg2pdf preprocessor"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from IPython.testing import decorators as dec
7 from IPython.nbformat import v4 as nbformat
8
9 from .base import PreprocessorTestsBase
10 from ..svg2pdf import SVG2PDFPreprocessor
11
12
13 class Testsvg2pdf(PreprocessorTestsBase):
14 """Contains test functions for svg2pdf.py"""
15
16 simple_svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
17 <!-- Created with Inkscape (http://www.inkscape.org/) -->
18 <svg
19 xmlns:svg="http://www.w3.org/2000/svg"
20 xmlns="http://www.w3.org/2000/svg"
21 version="1.0"
22 x="0.00000000"
23 y="0.00000000"
24 width="500.00000"
25 height="500.00000"
26 id="svg2">
27 <defs
28 id="defs4" />
29 <g
30 id="layer1">
31 <rect
32 width="300.00000"
33 height="300.00000"
34 x="100.00000"
35 y="100.00000"
36 style="opacity:1.0000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:8.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000"
37 id="rect5719" />
38 </g>
39 </svg>"""
40
41 def build_notebook(self):
42 """Build a reveal slides notebook in memory for use with tests.
43 Overrides base in PreprocessorTestsBase"""
44
45 outputs = [nbformat.new_output(output_type='display_data',
46 data={'image/svg+xml':self.simple_svg})
47 ]
48
49 cells=[nbformat.new_code_cell(source="", execution_count=1, outputs=outputs)]
50
51 return nbformat.new_notebook(cells=cells)
52
53
54 def build_preprocessor(self):
55 """Make an instance of a preprocessor"""
56 preprocessor = SVG2PDFPreprocessor()
57 preprocessor.enabled = True
58 return preprocessor
59
60
61 def test_constructor(self):
62 """Can a SVG2PDFPreprocessor be constructed?"""
63 self.build_preprocessor()
64
65
66 @dec.onlyif_cmds_exist('inkscape')
67 def test_output(self):
68 """Test the output of the SVG2PDFPreprocessor"""
69 nb = self.build_notebook()
70 res = self.build_resources()
71 preprocessor = self.build_preprocessor()
72 nb, res = preprocessor(nb, res)
73 self.assertIn('application/pdf', nb.cells[0].outputs[0].data)
@@ -1,9 +0,0 b''
1 README FIRST
2 ============
3
4 Please do not add new templates for nbconvert here.
5
6 In order to speed up the distribution of nbconvert templates and make it
7 simpler to share such contributions, we encourage [sharing those links on our
8 wiki
9 page](https://github.com/ipython/ipython/wiki/Cookbook:%20nbconvert%20templates).
@@ -1,201 +0,0 b''
1 {%- extends 'display_priority.tpl' -%}
2
3
4 {% block codecell %}
5 <div class="cell border-box-sizing code_cell rendered">
6 {{ super() }}
7 </div>
8 {%- endblock codecell %}
9
10 {% block input_group -%}
11 <div class="input">
12 {{ super() }}
13 </div>
14 {% endblock input_group %}
15
16 {% block output_group %}
17 <div class="output_wrapper">
18 <div class="output">
19 {{ super() }}
20 </div>
21 </div>
22 {% endblock output_group %}
23
24 {% block in_prompt -%}
25 <div class="prompt input_prompt">
26 {%- if cell.execution_count is defined -%}
27 In&nbsp;[{{ cell.execution_count|replace(None, "&nbsp;") }}]:
28 {%- else -%}
29 In&nbsp;[&nbsp;]:
30 {%- endif -%}
31 </div>
32 {%- endblock in_prompt %}
33
34 {% block empty_in_prompt -%}
35 <div class="prompt input_prompt">
36 </div>
37 {%- endblock empty_in_prompt %}
38
39 {#
40 output_prompt doesn't do anything in HTML,
41 because there is a prompt div in each output area (see output block)
42 #}
43 {% block output_prompt %}
44 {% endblock output_prompt %}
45
46 {% block input %}
47 <div class="inner_cell">
48 <div class="input_area">
49 {{ cell.source | highlight_code(metadata=cell.metadata) }}
50 </div>
51 </div>
52 {%- endblock input %}
53
54 {% block output %}
55 <div class="output_area">
56 {%- if output.output_type == 'execute_result' -%}
57 <div class="prompt output_prompt">
58 {%- if cell.execution_count is defined -%}
59 Out[{{ cell.execution_count|replace(None, "&nbsp;") }}]:
60 {%- else -%}
61 Out[&nbsp;]:
62 {%- endif -%}
63 {%- else -%}
64 <div class="prompt">
65 {%- endif -%}
66 </div>
67 {{ super() }}
68 </div>
69 {% endblock output %}
70
71 {% block markdowncell scoped %}
72 <div class="cell border-box-sizing text_cell rendered">
73 {{ self.empty_in_prompt() }}
74 <div class="inner_cell">
75 <div class="text_cell_render border-box-sizing rendered_html">
76 {{ cell.source | markdown2html | strip_files_prefix }}
77 </div>
78 </div>
79 </div>
80 {%- endblock markdowncell %}
81
82 {% block unknowncell scoped %}
83 unknown type {{ cell.type }}
84 {% endblock unknowncell %}
85
86 {% block execute_result -%}
87 {%- set extra_class="output_execute_result" -%}
88 {% block data_priority scoped %}
89 {{ super() }}
90 {% endblock %}
91 {%- set extra_class="" -%}
92 {%- endblock execute_result %}
93
94 {% block stream_stdout -%}
95 <div class="output_subarea output_stream output_stdout output_text">
96 <pre>
97 {{- output.text | ansi2html -}}
98 </pre>
99 </div>
100 {%- endblock stream_stdout %}
101
102 {% block stream_stderr -%}
103 <div class="output_subarea output_stream output_stderr output_text">
104 <pre>
105 {{- output.text | ansi2html -}}
106 </pre>
107 </div>
108 {%- endblock stream_stderr %}
109
110 {% block data_svg scoped -%}
111 <div class="output_svg output_subarea {{extra_class}}">
112 {%- if output.svg_filename %}
113 <img src="{{output.svg_filename | posix_path}}"
114 {%- else %}
115 {{ output.data['image/svg+xml'] }}
116 {%- endif %}
117 </div>
118 {%- endblock data_svg %}
119
120 {% block data_html scoped -%}
121 <div class="output_html rendered_html output_subarea {{extra_class}}">
122 {{ output.data['text/html'] }}
123 </div>
124 {%- endblock data_html %}
125
126 {% block data_markdown scoped -%}
127 <div class="output_markdown rendered_html output_subarea {{extra_class}}">
128 {{ output.data['text/markdown'] | markdown2html }}
129 </div>
130 {%- endblock data_markdown %}
131
132 {% block data_png scoped %}
133 <div class="output_png output_subarea {{extra_class}}">
134 {%- if 'image/png' in output.metadata.get('filenames', {}) %}
135 <img src="{{output.metadata.filenames['image/png'] | posix_path}}"
136 {%- else %}
137 <img src="data:image/png;base64,{{ output.data['image/png'] }}"
138 {%- endif %}
139 {%- if 'width' in output.metadata.get('image/png', {}) %}
140 width={{output.metadata['image/png']['width']}}
141 {%- endif %}
142 {%- if 'height' in output.metadata.get('image/png', {}) %}
143 height={{output.metadata['image/png']['height']}}
144 {%- endif %}
145 {%- if output.metadata.get('image/png', {}).get('unconfined') %}
146 class="unconfined"
147 {%- endif %}
148 >
149 </div>
150 {%- endblock data_png %}
151
152 {% block data_jpg scoped %}
153 <div class="output_jpeg output_subarea {{extra_class}}">
154 {%- if 'image/jpeg' in output.metadata.get('filenames', {}) %}
155 <img src="{{output.metadata.filenames['image/jpeg'] | posix_path}}"
156 {%- else %}
157 <img src="data:image/jpeg;base64,{{ output.data['image/jpeg'] }}"
158 {%- endif %}
159 {%- if 'width' in output.metadata.get('image/jpeg', {}) %}
160 width={{output.metadata['image/jpeg']['width']}}
161 {%- endif %}
162 {%- if 'height' in output.metadata.get('image/jpeg', {}) %}
163 height={{output.metadata['image/jpeg']['height']}}
164 {%- endif %}
165 >
166 </div>
167 {%- endblock data_jpg %}
168
169 {% block data_latex scoped %}
170 <div class="output_latex output_subarea {{extra_class}}">
171 {{ output.data['text/latex'] }}
172 </div>
173 {%- endblock data_latex %}
174
175 {% block error -%}
176 <div class="output_subarea output_text output_error">
177 <pre>
178 {{- super() -}}
179 </pre>
180 </div>
181 {%- endblock error %}
182
183 {%- block traceback_line %}
184 {{ line | ansi2html }}
185 {%- endblock traceback_line %}
186
187 {%- block data_text scoped %}
188 <div class="output_text output_subarea {{extra_class}}">
189 <pre>
190 {{- output.data['text/plain'] | ansi2html -}}
191 </pre>
192 </div>
193 {%- endblock -%}
194
195 {%- block data_javascript scoped %}
196 <div class="output_subarea output_javascript {{extra_class}}">
197 <script type="text/javascript">
198 {{ output.data['application/javascript'] }}
199 </script>
200 </div>
201 {%- endblock -%}
@@ -1,71 +0,0 b''
1 {%- extends 'basic.tpl' -%}
2 {% from 'mathjax.tpl' import mathjax %}
3
4
5 {%- block header -%}
6 <!DOCTYPE html>
7 <html>
8 <head>
9
10 <meta charset="utf-8" />
11 <title>{{resources['metadata']['name']}}</title>
12
13 <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
14 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
15
16 {% for css in resources.inlining.css -%}
17 <style type="text/css">
18 {{ css }}
19 </style>
20 {% endfor %}
21
22 <style type="text/css">
23 /* Overrides of notebook CSS for static HTML export */
24 body {
25 overflow: visible;
26 padding: 8px;
27 }
28
29 div#notebook {
30 overflow: visible;
31 border-top: none;
32 }
33
34 @media print {
35 div.cell {
36 display: block;
37 page-break-inside: avoid;
38 }
39 div.output_wrapper {
40 display: block;
41 page-break-inside: avoid;
42 }
43 div.output {
44 display: block;
45 page-break-inside: avoid;
46 }
47 }
48 </style>
49
50 <!-- Custom stylesheet, it must be in the same directory as the html file -->
51 <link rel="stylesheet" href="custom.css">
52
53 <!-- Loading mathjax macro -->
54 {{ mathjax() }}
55
56 </head>
57 {%- endblock header -%}
58
59 {% block body %}
60 <body>
61 <div tabindex="-1" id="notebook" class="border-box-sizing">
62 <div class="container" id="notebook-container">
63 {{ super() }}
64 </div>
65 </div>
66 </body>
67 {%- endblock body %}
68
69 {% block footer %}
70 </html>
71 {% endblock footer %}
@@ -1,23 +0,0 b''
1 {%- macro mathjax() -%}
2 <!-- Load mathjax -->
3 <script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
4 <!-- MathJax configuration -->
5 <script type="text/x-mathjax-config">
6 MathJax.Hub.Config({
7 tex2jax: {
8 inlineMath: [ ['$','$'], ["\\(","\\)"] ],
9 displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
10 processEscapes: true,
11 processEnvironments: true
12 },
13 // Center justify equations in code and markdown cells. Elsewhere
14 // we use CSS to left justify single line equations in code cells.
15 displayAlign: 'center',
16 "HTML-CSS": {
17 styles: {'.MathJax_Display': {"margin": 0}},
18 linebreaks: { automatic: true }
19 }
20 });
21 </script>
22 <!-- End of mathjax configuration -->
23 {%- endmacro %} No newline at end of file
@@ -1,203 +0,0 b''
1 {%- extends 'basic.tpl' -%}
2 {% from 'mathjax.tpl' import mathjax %}
3
4 {%- block any_cell scoped -%}
5 {%- if cell.metadata.slide_type in ['slide'] -%}
6 <section>
7 <section>
8 {{ super() }}
9 {%- elif cell.metadata.slide_type in ['subslide'] -%}
10 <section>
11 {{ super() }}
12 {%- elif cell.metadata.slide_type in ['-'] -%}
13 {%- if cell.metadata.frag_helper in ['fragment_end'] -%}
14 <div class="fragment" data-fragment-index="{{ cell.metadata.frag_number }}">
15 {{ super() }}
16 </div>
17 {%- else -%}
18 {{ super() }}
19 {%- endif -%}
20 {%- elif cell.metadata.slide_type in ['skip'] -%}
21 <div style=display:none>
22 {{ super() }}
23 </div>
24 {%- elif cell.metadata.slide_type in ['notes'] -%}
25 <aside class="notes">
26 {{ super() }}
27 </aside>
28 {%- elif cell.metadata.slide_type in ['fragment'] -%}
29 <div class="fragment" data-fragment-index="{{ cell.metadata.frag_number }}">
30 {{ super() }}
31 </div>
32 {%- endif -%}
33 {%- if cell.metadata.slide_helper in ['subslide_end'] -%}
34 </section>
35 {%- elif cell.metadata.slide_helper in ['slide_end'] -%}
36 </section>
37 </section>
38 {%- endif -%}
39 {%- endblock any_cell -%}
40
41 {% block header %}
42 <!DOCTYPE html>
43 <html>
44 <head>
45
46 <meta charset="utf-8" />
47 <meta http-equiv="X-UA-Compatible" content="chrome=1" />
48
49 <meta name="apple-mobile-web-app-capable" content="yes" />
50 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
51
52 <title>{{resources['metadata']['name']}} slides</title>
53
54 <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
55 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
56
57 <!-- General and theme style sheets -->
58 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/reveal.css">
59 <link rel="stylesheet" href="{{resources.reveal.url_prefix}}/css/theme/simple.css" id="theme">
60
61 <!-- If the query includes 'print-pdf', include the PDF print sheet -->
62 <script>
63 if( window.location.search.match( /print-pdf/gi ) ) {
64 var link = document.createElement( 'link' );
65 link.rel = 'stylesheet';
66 link.type = 'text/css';
67 link.href = '{{resources.reveal.url_prefix}}/css/print/pdf.css';
68 document.getElementsByTagName( 'head' )[0].appendChild( link );
69 }
70
71 </script>
72
73 <!--[if lt IE 9]>
74 <script src="{{resources.reveal.url_prefix}}/lib/js/html5shiv.js"></script>
75 <![endif]-->
76
77 <!-- Get Font-awesome from cdn -->
78 <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css">
79
80 {% for css in resources.inlining.css -%}
81 <style type="text/css">
82 {{ css }}
83 </style>
84 {% endfor %}
85
86 <style type="text/css">
87 /* Overrides of notebook CSS for static HTML export */
88 html {
89 overflow-y: auto;
90 }
91 .reveal {
92 font-size: 160%;
93 }
94 .reveal pre {
95 width: inherit;
96 padding: 0.4em;
97 margin: 0px;
98 font-family: monospace, sans-serif;
99 font-size: 80%;
100 box-shadow: 0px 0px 0px rgba(0, 0, 0, 0);
101 }
102 .reveal pre code {
103 padding: 0px;
104 }
105 .reveal section img {
106 border: 0px solid black;
107 box-shadow: 0 0 10px rgba(0, 0, 0, 0);
108 }
109 .reveal i {
110 font-style: normal;
111 font-family: FontAwesome;
112 font-size: 2em;
113 }
114 .reveal .slides {
115 text-align: left;
116 }
117 .reveal.fade {
118 opacity: 1;
119 }
120 .reveal .progress {
121 position: static;
122 }
123 div.input_area {
124 padding: 0.06em;
125 }
126 div.code_cell {
127 background-color: transparent;
128 }
129 div.prompt {
130 width: 11ex;
131 padding: 0.4em;
132 margin: 0px;
133 font-family: monospace, sans-serif;
134 font-size: 80%;
135 text-align: right;
136 }
137 div.output_area pre {
138 font-family: monospace, sans-serif;
139 font-size: 80%;
140 }
141 div.output_prompt {
142 /* 5px right shift to account for margin in parent container */
143 margin: 5px 5px 0 0;
144 }
145 .rendered_html p {
146 text-align: inherit;
147 }
148 </style>
149
150 <!-- Custom stylesheet, it must be in the same directory as the html file -->
151 <link rel="stylesheet" href="custom.css">
152
153 </head>
154 {% endblock header%}
155
156
157 {% block body %}
158 <body>
159 <div class="reveal">
160 <div class="slides">
161 {{ super() }}
162 </div>
163 </div>
164
165 <script src="{{resources.reveal.url_prefix}}/lib/js/head.min.js"></script>
166
167 <script src="{{resources.reveal.url_prefix}}/js/reveal.js"></script>
168
169 <script>
170
171 // Full list of configuration options available here: https://github.com/hakimel/reveal.js#configuration
172 Reveal.initialize({
173 controls: true,
174 progress: true,
175 history: true,
176
177 theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
178 transition: Reveal.getQueryHash().transition || 'linear', // default/cube/page/concave/zoom/linear/none
179
180 // Optional libraries used to extend on reveal.js
181 dependencies: [
182 { src: "{{resources.reveal.url_prefix}}/lib/js/classList.js", condition: function() { return !document.body.classList; } },
183 { src: "{{resources.reveal.url_prefix}}/plugin/notes/notes.js", async: true, condition: function() { return !!document.body.classList; } }
184 ]
185 });
186 </script>
187
188 <!-- Loading mathjax macro -->
189 {{ mathjax() }}
190
191 <script>
192 Reveal.addEventListener( 'slidechanged', function( event ) {
193 window.scrollTo(0,0);
194 MathJax.Hub.Rerender(event.currentSlide);
195 });
196 </script>
197
198 </body>
199 {% endblock body %}
200
201 {% block footer %}
202 </html>
203 {% endblock footer %}
@@ -1,17 +0,0 b''
1
2 % Default to the notebook output style
3 ((* if not cell_style is defined *))
4 ((* set cell_style = 'style_ipython.tplx' *))
5 ((* endif *))
6
7 % Inherit from the specified cell style.
8 ((* extends cell_style *))
9
10
11 %===============================================================================
12 % Latex Article
13 %===============================================================================
14
15 ((* block docclass *))
16 \documentclass{article}
17 ((* endblock docclass *)) No newline at end of file
@@ -1,203 +0,0 b''
1 ((= Latex base template (must inherit)
2 This template builds upon the abstract template, adding common latex output
3 functions. Figures, data_text,
4 This template does not define a docclass, the inheriting class must define this.=))
5
6 ((*- extends 'display_priority.tplx' -*))
7
8 %===============================================================================
9 % Abstract overrides
10 %===============================================================================
11
12 ((* block header *))
13 ((* block docclass *))((* endblock docclass *))
14
15 ((* block packages *))
16 \usepackage{graphicx} % Used to insert images
17 \usepackage{adjustbox} % Used to constrain images to a maximum size
18 \usepackage{color} % Allow colors to be defined
19 \usepackage{enumerate} % Needed for markdown enumerations to work
20 \usepackage{geometry} % Used to adjust the document margins
21 \usepackage{amsmath} % Equations
22 \usepackage{amssymb} % Equations
23 \usepackage{eurosym} % defines \euro
24 \usepackage[mathletters]{ucs} % Extended unicode (utf-8) support
25 \usepackage[utf8x]{inputenc} % Allow utf-8 characters in the tex document
26 \usepackage{fancyvrb} % verbatim replacement that allows latex
27 \usepackage{grffile} % extends the file name processing of package graphics
28 % to support a larger range
29 % The hyperref package gives us a pdf with properly built
30 % internal navigation ('pdf bookmarks' for the table of contents,
31 % internal cross-reference links, web links for URLs, etc.)
32 \usepackage{hyperref}
33 \usepackage{longtable} % longtable support required by pandoc >1.10
34 \usepackage{booktabs} % table support for pandoc > 1.12.2
35 ((* endblock packages *))
36
37 ((* block definitions *))
38 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
39 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
40 \definecolor{darkgreen}{rgb}{.12,.54,.11}
41 \definecolor{myteal}{rgb}{.26, .44, .56}
42 \definecolor{gray}{gray}{0.45}
43 \definecolor{lightgray}{gray}{.95}
44 \definecolor{mediumgray}{gray}{.8}
45 \definecolor{inputbackground}{rgb}{.95, .95, .85}
46 \definecolor{outputbackground}{rgb}{.95, .95, .95}
47 \definecolor{traceback}{rgb}{1, .95, .95}
48 % ansi colors
49 \definecolor{red}{rgb}{.6,0,0}
50 \definecolor{green}{rgb}{0,.65,0}
51 \definecolor{brown}{rgb}{0.6,0.6,0}
52 \definecolor{blue}{rgb}{0,.145,.698}
53 \definecolor{purple}{rgb}{.698,.145,.698}
54 \definecolor{cyan}{rgb}{0,.698,.698}
55 \definecolor{lightgray}{gray}{0.5}
56
57 % bright ansi colors
58 \definecolor{darkgray}{gray}{0.25}
59 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
60 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
61 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
62 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
63 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
64
65 % commands and environments needed by pandoc snippets
66 % extracted from the output of `pandoc -s`
67 \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
68 % Add ',fontsize=\small' for more characters per line
69 \newenvironment{Shaded}{}{}
70 \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}}
71 \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}}
72 \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
73 \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
74 \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}}
75 \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}}
76 \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}}
77 \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}}
78 \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}}
79 \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}}
80 \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}}
81 \newcommand{\RegionMarkerTok}[1]{{#1}}
82 \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}}
83 \newcommand{\NormalTok}[1]{{#1}}
84
85 % Define a nice break command that doesn't care if a line doesn't already
86 % exist.
87 \def\br{\hspace*{\fill} \\* }
88 % Math Jax compatability definitions
89 \def\gt{>}
90 \def\lt{<}
91 % Document parameters
92 ((* block title *))\title{((( resources.metadata.name | ascii_only | escape_latex )))}((* endblock title *))
93 ((* block date *))((* endblock date *))
94 ((* block author *))((* endblock author *))
95 ((* endblock definitions *))
96
97 ((* block commands *))
98 % Prevent overflowing lines due to hard-to-break entities
99 \sloppy
100 % Setup hyperref package
101 \hypersetup{
102 breaklinks=true, % so long urls are correctly broken across lines
103 colorlinks=true,
104 urlcolor=blue,
105 linkcolor=darkorange,
106 citecolor=darkgreen,
107 }
108 % Slightly bigger margins than the latex defaults
109 ((* block margins *))
110 \geometry{verbose,tmargin=1in,bmargin=1in,lmargin=1in,rmargin=1in}
111 ((* endblock margins *))
112 ((* endblock commands *))
113 ((* endblock header *))
114
115 ((* block body *))
116 \begin{document}
117
118 ((* block predoc *))
119 ((* block maketitle *))\maketitle((* endblock maketitle *))
120 ((* block abstract *))((* endblock abstract *))
121 ((* endblock predoc *))
122
123 ((( super() )))
124
125 % Add a bibliography block to the postdoc
126 ((* block postdoc *))
127 ((* block bibliography *))((* endblock bibliography *))
128 ((* endblock postdoc *))
129 \end{document}
130 ((* endblock body *))
131
132 %===============================================================================
133 % Support blocks
134 %===============================================================================
135
136 % Displaying simple data text
137 ((* block data_text *))
138 \begin{verbatim}
139 ((( output.data['text/plain'] )))
140 \end{verbatim}
141 ((* endblock data_text *))
142
143 % Display python error text as-is
144 ((* block error *))
145 \begin{Verbatim}[commandchars=\\\{\}]
146 ((( super() )))
147 \end{Verbatim}
148 ((* endblock error *))
149 ((* block traceback_line *))
150 ((( line | indent | strip_ansi | escape_latex )))
151 ((* endblock traceback_line *))
152
153 % Display stream ouput with coloring
154 ((* block stream *))
155 \begin{Verbatim}[commandchars=\\\{\}]
156 ((( output.text | escape_latex | ansi2latex )))
157 \end{Verbatim}
158 ((* endblock stream *))
159
160 % Display latex
161 ((* block data_latex -*))
162 ((*- if output.data['text/latex'].startswith('$'): -*))
163 ((= Replace $ symbols with more explicit, equation block. =))
164 \begin{equation*}\adjustbox{max width=\hsize}{$
165 ((( output.data['text/latex'] | strip_dollars )))
166 $}\end{equation*}
167 ((*- else -*))
168 ((( output.data['text/latex'] )))
169 ((*- endif *))
170 ((* endblock data_latex *))
171
172 % Default mechanism for rendering figures
173 ((*- block data_png -*))((( draw_figure(output.metadata.filenames['image/png']) )))((*- endblock -*))
174 ((*- block data_jpg -*))((( draw_figure(output.metadata.filenames['image/jpeg']) )))((*- endblock -*))
175 ((*- block data_svg -*))((( draw_figure(output.metadata.filenames['image/svg+xml']) )))((*- endblock -*))
176 ((*- block data_pdf -*))((( draw_figure(output.metadata.filenames['application/pdf']) )))((*- endblock -*))
177
178 % Draw a figure using the graphicx package.
179 ((* macro draw_figure(filename) -*))
180 ((* set filename = filename | posix_path *))
181 ((*- block figure scoped -*))
182 \begin{center}
183 \adjustimage{max size={0.9\linewidth}{0.9\paperheight}}{((( filename )))}
184 \end{center}
185 { \hspace*{\fill} \\}
186 ((*- endblock figure -*))
187 ((*- endmacro *))
188
189 % Redirect execute_result to display data priority.
190 ((* block execute_result scoped *))
191 ((* block data_priority scoped *))
192 ((( super() )))
193 ((* endblock *))
194 ((* endblock execute_result *))
195
196 % Render markdown
197 ((* block markdowncell scoped *))
198 ((( cell.source | citation2latex | strip_files_prefix | markdown2latex )))
199 ((* endblock markdowncell *))
200
201 % Don't display unknown types
202 ((* block unknowncell scoped *))
203 ((* endblock unknowncell *))
@@ -1,26 +0,0 b''
1
2 % Default to the notebook output style
3 ((* if not cell_style is defined *))
4 ((* set cell_style = 'style_ipython.tplx' *))
5 ((* endif *))
6
7 % Inherit from the specified cell style.
8 ((* extends cell_style *))
9
10
11 %===============================================================================
12 % Latex Book
13 %===============================================================================
14
15 ((* block predoc *))
16 ((( super() )))
17 ((* block tableofcontents *))\tableofcontents((* endblock tableofcontents *))
18 ((* endblock predoc *))
19
20 ((* block docclass *))
21 \documentclass{report}
22 ((* endblock docclass *))
23
24 ((* block markdowncell scoped *))
25 ((( cell.source | citation2latex | strip_files_prefix | markdown2latex(extra_args=["--chapters"]) )))
26 ((* endblock markdowncell *))
@@ -1,44 +0,0 b''
1 ((= Auto-generated template file, DO NOT edit directly!
2 To edit this file, please refer to ../../skeleton/README.md =))
3
4
5 ((*- extends 'null.tplx' -*))
6
7 ((=display data priority=))
8
9
10 ((*- block data_priority scoped -*))
11 ((*- for type in output.data | filter_data_type -*))
12 ((*- if type == 'application/pdf' -*))
13 ((*- block data_pdf -*))
14 ((*- endblock -*))
15 ((*- elif type == 'image/svg+xml' -*))
16 ((*- block data_svg -*))
17 ((*- endblock -*))
18 ((*- elif type == 'image/png' -*))
19 ((*- block data_png -*))
20 ((*- endblock -*))
21 ((*- elif type == 'text/html' -*))
22 ((*- block data_html -*))
23 ((*- endblock -*))
24 ((*- elif type == 'text/markdown' -*))
25 ((*- block data_markdown -*))
26 ((*- endblock -*))
27 ((*- elif type == 'image/jpeg' -*))
28 ((*- block data_jpg -*))
29 ((*- endblock -*))
30 ((*- elif type == 'text/plain' -*))
31 ((*- block data_text -*))
32 ((*- endblock -*))
33 ((*- elif type == 'text/latex' -*))
34 ((*- block data_latex -*))
35 ((*- endblock -*))
36 ((*- elif type == 'application/javascript' -*))
37 ((*- block data_javascript -*))
38 ((*- endblock -*))
39 ((*- else -*))
40 ((*- block data_other -*))
41 ((*- endblock -*))
42 ((*- endif -*))
43 ((*- endfor -*))
44 ((*- endblock data_priority -*))
@@ -1,93 +0,0 b''
1 ((= Auto-generated template file, DO NOT edit directly!
2 To edit this file, please refer to ../../skeleton/README.md =))
3
4
5 ((=
6
7 DO NOT USE THIS AS A BASE,
8 IF YOU ARE COPY AND PASTING THIS FILE
9 YOU ARE PROBABLY DOING THINGS INCORRECTLY.
10
11 Null template, does nothing except defining a basic structure
12 To layout the different blocks of a notebook.
13
14 Subtemplates can override blocks to define their custom representation.
15
16 If one of the block you do overwrite is not a leave block, consider
17 calling super.
18
19 ((*- block nonLeaveBlock -*))
20 #add stuff at beginning
21 ((( super() )))
22 #add stuff at end
23 ((*- endblock nonLeaveBlock -*))
24
25 consider calling super even if it is a leave block, we might insert more blocks later.
26
27 =))
28 ((*- block header -*))
29 ((*- endblock header -*))
30 ((*- block body -*))
31 ((*- for cell in nb.cells -*))
32 ((*- block any_cell scoped -*))
33 ((*- if cell.cell_type == 'code' -*))
34 ((*- block codecell scoped -*))
35 ((*- block input_group -*))
36 ((*- block in_prompt -*))((*- endblock in_prompt -*))
37 ((*- block input -*))((*- endblock input -*))
38 ((*- endblock input_group -*))
39 ((*- if cell.outputs -*))
40 ((*- block output_group -*))
41 ((*- block output_prompt -*))((*- endblock output_prompt -*))
42 ((*- block outputs scoped -*))
43 ((*- for output in cell.outputs -*))
44 ((*- block output scoped -*))
45 ((*- if output.output_type == 'execute_result' -*))
46 ((*- block execute_result scoped -*))((*- endblock execute_result -*))
47 ((*- elif output.output_type == 'stream' -*))
48 ((*- block stream scoped -*))
49 ((*- if output.name == 'stdout' -*))
50 ((*- block stream_stdout scoped -*))
51 ((*- endblock stream_stdout -*))
52 ((*- elif output.name == 'stderr' -*))
53 ((*- block stream_stderr scoped -*))
54 ((*- endblock stream_stderr -*))
55 ((*- endif -*))
56 ((*- endblock stream -*))
57 ((*- elif output.output_type == 'display_data' -*))
58 ((*- block display_data scoped -*))
59 ((*- block data_priority scoped -*))
60 ((*- endblock data_priority -*))
61 ((*- endblock display_data -*))
62 ((*- elif output.output_type == 'error' -*))
63 ((*- block error scoped -*))
64 ((*- for line in output.traceback -*))
65 ((*- block traceback_line scoped -*))((*- endblock traceback_line -*))
66 ((*- endfor -*))
67 ((*- endblock error -*))
68 ((*- endif -*))
69 ((*- endblock output -*))
70 ((*- endfor -*))
71 ((*- endblock outputs -*))
72 ((*- endblock output_group -*))
73 ((*- endif -*))
74 ((*- endblock codecell -*))
75 ((*- elif cell.cell_type in ['markdown'] -*))
76 ((*- block markdowncell scoped-*))
77 ((*- endblock markdowncell -*))
78 ((*- elif cell.cell_type in ['raw'] -*))
79 ((*- block rawcell scoped -*))
80 ((*- if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) -*))
81 ((( cell.source )))
82 ((*- endif -*))
83 ((*- endblock rawcell -*))
84 ((*- else -*))
85 ((*- block unknowncell scoped-*))
86 ((*- endblock unknowncell -*))
87 ((*- endif -*))
88 ((*- endblock any_cell -*))
89 ((*- endfor -*))
90 ((*- endblock body -*))
91
92 ((*- block footer -*))
93 ((*- endblock footer -*))
@@ -1,45 +0,0 b''
1 ((= Black&white ipython input/output style =))
2
3 ((*- extends 'base.tplx' -*))
4
5 %===============================================================================
6 % Input
7 %===============================================================================
8
9 ((* block input scoped *))
10 ((( add_prompt(cell.source, cell, 'In ') )))
11 ((* endblock input *))
12
13
14 %===============================================================================
15 % Output
16 %===============================================================================
17
18 ((* block execute_result scoped *))
19 ((*- for type in output.data | filter_data_type -*))
20 ((*- if type in ['text/plain']*))
21 ((( add_prompt(output.data['text/plain'], cell, 'Out') )))
22 ((*- else -*))
23 \verb+Out[((( cell.execution_count )))]:+((( super() )))
24 ((*- endif -*))
25 ((*- endfor -*))
26 ((* endblock execute_result *))
27
28
29 %==============================================================================
30 % Support Macros
31 %==============================================================================
32
33 % Name: draw_prompt
34 % Purpose: Renders an output/input prompt
35 ((* macro add_prompt(text, cell, prompt) -*))
36 ((*- if cell.execution_count is defined -*))
37 ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*))
38 ((*- else -*))
39 ((*- set execution_count = " " -*))
40 ((*- endif -*))
41 ((*- set indentation = " " * (execution_count | length + 7) -*))
42 \begin{verbatim}
43 (((- text | add_prompts(first=prompt ~ '[' ~ execution_count ~ ']: ', cont=indentation) -)))
44 \end{verbatim}
45 ((*- endmacro *))
@@ -1,13 +0,0 b''
1 ((= Black&white Python input/output style =))
2
3 ((*- extends 'base.tplx' -*))
4
5 %===============================================================================
6 % Input
7 %===============================================================================
8
9 ((* block input scoped *))
10 \begin{verbatim}
11 ((( cell.source | add_prompts )))
12 \end{verbatim}
13 ((* endblock input *))
@@ -1,58 +0,0 b''
1 ((= IPython input/output style =))
2
3 ((*- extends 'base.tplx' -*))
4
5 % Custom definitions
6 ((* block definitions *))
7 ((( super() )))
8
9 % Pygments definitions
10 ((( resources.latex.pygments_definitions )))
11
12 % Exact colors from NB
13 \definecolor{incolor}{rgb}{0.0, 0.0, 0.5}
14 \definecolor{outcolor}{rgb}{0.545, 0.0, 0.0}
15
16 ((* endblock definitions *))
17
18 %===============================================================================
19 % Input
20 %===============================================================================
21
22 ((* block input scoped *))
23 ((( add_prompt(cell.source | highlight_code(strip_verbatim=True), cell, 'In ', 'incolor') )))
24 ((* endblock input *))
25
26
27 %===============================================================================
28 % Output
29 %===============================================================================
30
31 ((* block execute_result scoped *))
32 ((*- for type in output.data | filter_data_type -*))
33 ((*- if type in ['text/plain']*))
34 ((( add_prompt(output.data['text/plain'] | escape_latex, cell, 'Out', 'outcolor') )))
35 ((* else -*))
36 \texttt{\color{outcolor}Out[{\color{outcolor}((( cell.execution_count )))}]:}((( super() )))
37 ((*- endif -*))
38 ((*- endfor -*))
39 ((* endblock execute_result *))
40
41
42 %==============================================================================
43 % Support Macros
44 %==============================================================================
45
46 % Name: draw_prompt
47 % Purpose: Renders an output/input prompt
48 ((* macro add_prompt(text, cell, prompt, prompt_color) -*))
49 ((*- if cell.execution_count is defined -*))
50 ((*- set execution_count = "" ~ (cell.execution_count | replace(None, " ")) -*))
51 ((*- else -*))
52 ((*- set execution_count = " " -*))
53 ((*- endif -*))
54 ((*- set indention = " " * (execution_count | length + 7) -*))
55 \begin{Verbatim}[commandchars=\\\{\}]
56 ((( text | add_prompts(first='{\color{' ~ prompt_color ~ '}' ~ prompt ~ '[{\\color{' ~ prompt_color ~ '}' ~ execution_count ~ '}]:} ', cont=indention) )))
57 \end{Verbatim}
58 ((*- endmacro *))
@@ -1,21 +0,0 b''
1 ((= Python input/output style =))
2
3 ((*- extends 'base.tplx' -*))
4
5 % Custom definitions
6 ((* block definitions *))
7 ((( super() )))
8
9 % Pygments definitions
10 ((( resources.latex.pygments_definitions )))
11 ((* endblock definitions *))
12
13 %===============================================================================
14 % Input
15 %===============================================================================
16
17 ((* block input scoped *))
18 \begin{Verbatim}[commandchars=\\\{\}]
19 ((( cell.source | highlight_code(strip_verbatim=True) | add_prompts )))
20 \end{Verbatim}
21 ((* endblock input *))
@@ -1,67 +0,0 b''
1 {% extends 'display_priority.tpl' %}
2
3
4 {% block in_prompt %}
5 {% endblock in_prompt %}
6
7 {% block output_prompt %}
8 {%- endblock output_prompt %}
9
10 {% block input %}
11 {{ cell.source | indent(4)}}
12 {% endblock input %}
13
14 {% block error %}
15 {{ super() }}
16 {% endblock error %}
17
18 {% block traceback_line %}
19 {{ line | indent | strip_ansi }}
20 {% endblock traceback_line %}
21
22 {% block execute_result %}
23
24 {% block data_priority scoped %}
25 {{ super() }}
26 {% endblock %}
27 {% endblock execute_result %}
28
29 {% block stream %}
30 {{ output.text | indent }}
31 {% endblock stream %}
32
33 {% block data_svg %}
34 ![svg]({{ output.svg_filename | path2url }})
35 {% endblock data_svg %}
36
37 {% block data_png %}
38 ![png]({{ output.metadata.filenames['image/png'] | path2url }})
39 {% endblock data_png %}
40
41 {% block data_jpg %}
42 ![jpeg]({{ output.metadata.filenames['image/jpeg'] | path2url }})
43 {% endblock data_jpg %}
44
45 {% block data_latex %}
46 {{ output.data['text/latex'] }}
47 {% endblock data_latex %}
48
49 {% block data_html scoped %}
50 {{ output.data['text/html'] }}
51 {% endblock data_html %}
52
53 {% block data_markdown scoped %}
54 {{ output.data['text/markdown'] }}
55 {% endblock data_markdown %}
56
57 {% block data_text scoped %}
58 {{ output.data['text/plain'] | indent }}
59 {% endblock data_text %}
60
61 {% block markdowncell scoped %}
62 {{ cell.source }}
63 {% endblock markdowncell %}
64
65 {% block unknowncell scoped %}
66 unknown type {{ cell.type }}
67 {% endblock unknowncell %} No newline at end of file
@@ -1,17 +0,0 b''
1 {%- extends 'null.tpl' -%}
2
3 {% block header %}
4 # coding: utf-8
5 {% endblock header %}
6
7 {% block in_prompt %}
8 # In[{{ cell.execution_count if cell.execution_count else ' ' }}]:
9 {% endblock in_prompt %}
10
11 {% block input %}
12 {{ cell.source | ipython2python }}
13 {% endblock input %}
14
15 {% block markdowncell scoped %}
16 {{ cell.source | comment_lines }}
17 {% endblock markdowncell %}
@@ -1,86 +0,0 b''
1 {%- extends 'display_priority.tpl' -%}
2
3
4 {% block in_prompt %}
5 {% endblock in_prompt %}
6
7 {% block output_prompt %}
8 {% endblock output_prompt %}
9
10 {% block input %}
11 {%- if cell.source.strip() -%}
12 .. code:: python
13
14 {{ cell.source | indent}}
15 {% endif -%}
16 {% endblock input %}
17
18 {% block error %}
19 ::
20
21 {{ super() }}
22 {% endblock error %}
23
24 {% block traceback_line %}
25 {{ line | indent | strip_ansi }}
26 {% endblock traceback_line %}
27
28 {% block execute_result %}
29 {% block data_priority scoped %}
30 {{ super() }}
31 {% endblock %}
32 {% endblock execute_result %}
33
34 {% block stream %}
35 .. parsed-literal::
36
37 {{ output.text | indent }}
38 {% endblock stream %}
39
40 {% block data_svg %}
41 .. image:: {{ output.metadata.filenames['image/svg+xml'] | urlencode }}
42 {% endblock data_svg %}
43
44 {% block data_png %}
45 .. image:: {{ output.metadata.filenames['image/png'] | urlencode }}
46 {% endblock data_png %}
47
48 {% block data_jpg %}
49 .. image:: {{ output.metadata.filenames['image/jpeg'] | urlencode }}
50 {% endblock data_jpg %}
51
52 {% block data_latex %}
53 .. math::
54
55 {{ output.data['text/latex'] | strip_dollars | indent }}
56 {% endblock data_latex %}
57
58 {% block data_text scoped %}
59 .. parsed-literal::
60
61 {{ output.data['text/plain'] | indent }}
62 {% endblock data_text %}
63
64 {% block data_html scoped %}
65 .. raw:: html
66
67 {{ output.data['text/html'] | indent }}
68 {% endblock data_html %}
69
70 {% block markdowncell scoped %}
71 {{ cell.source | markdown2rst }}
72 {% endblock markdowncell %}
73
74 {%- block rawcell scoped -%}
75 {%- if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) %}
76 {{cell.source}}
77 {% endif -%}
78 {%- endblock rawcell -%}
79
80 {% block headingcell scoped %}
81 {{ ("#" * cell.level + cell.source) | replace('\n', ' ') | markdown2rst }}
82 {% endblock headingcell %}
83
84 {% block unknowncell scoped %}
85 unknown type {{cell.type}}
86 {% endblock unknowncell %}
@@ -1,5 +0,0 b''
1 {%- extends 'null.tpl' -%}
2
3 {% block input %}
4 {{ cell.source }}
5 {% endblock input %}
@@ -1,24 +0,0 b''
1 TPLS := $(patsubst %.tpl,../latex/skeleton/%.tplx,$(wildcard *.tpl))
2
3 all: clean $(TPLS)
4
5 # Convert standard Jinja2 syntax to LaTeX safe Jinja2
6 # see http://flask.pocoo.org/snippets/55/ for more info
7 ../latex/skeleton/%.tplx: %.tpl
8 @echo 'generating tex equivalent of $^: $@'
9 @echo '((= Auto-generated template file, DO NOT edit directly!\n' \
10 ' To edit this file, please refer to ../../skeleton/README.md' \
11 '=))\n\n' > $@
12 @sed \
13 -e 's/{%/((*/g' \
14 -e 's/%}/*))/g' \
15 -e 's/{{/(((/g' \
16 -e 's/}}/)))/g' \
17 -e 's/{#/((=/g' \
18 -e 's/#}/=))/g' \
19 -e "s/tpl'/tplx'/g" \
20 $^ >> $@
21
22 clean:
23 @echo "cleaning generated tplx files..."
24 @-rm ../latex/skeleton/*.tplx
@@ -1,12 +0,0 b''
1 ## Template skeleton
2
3 This directory contains the template skeleton files.
4
5 Do not modify the contents of the `../latex/skeleton` folder. Instead,
6 if you need to, make modifications to the files in this folder and then run
7 `make` to generate the corresponding latex skeleton files in the
8 `../latex/skeleton` folder.
9
10 If you would like to share your resulting templates with others, we encourage
11 [sharing those links on our wiki
12 page](https://github.com/ipython/ipython/wiki/Cookbook:%20nbconvert%20templates).
@@ -1,40 +0,0 b''
1 {%- extends 'null.tpl' -%}
2
3 {#display data priority#}
4
5
6 {%- block data_priority scoped -%}
7 {%- for type in output.data | filter_data_type -%}
8 {%- if type == 'application/pdf' -%}
9 {%- block data_pdf -%}
10 {%- endblock -%}
11 {%- elif type == 'image/svg+xml' -%}
12 {%- block data_svg -%}
13 {%- endblock -%}
14 {%- elif type == 'image/png' -%}
15 {%- block data_png -%}
16 {%- endblock -%}
17 {%- elif type == 'text/html' -%}
18 {%- block data_html -%}
19 {%- endblock -%}
20 {%- elif type == 'text/markdown' -%}
21 {%- block data_markdown -%}
22 {%- endblock -%}
23 {%- elif type == 'image/jpeg' -%}
24 {%- block data_jpg -%}
25 {%- endblock -%}
26 {%- elif type == 'text/plain' -%}
27 {%- block data_text -%}
28 {%- endblock -%}
29 {%- elif type == 'text/latex' -%}
30 {%- block data_latex -%}
31 {%- endblock -%}
32 {%- elif type == 'application/javascript' -%}
33 {%- block data_javascript -%}
34 {%- endblock -%}
35 {%- else -%}
36 {%- block data_other -%}
37 {%- endblock -%}
38 {%- endif -%}
39 {%- endfor -%}
40 {%- endblock data_priority -%}
@@ -1,89 +0,0 b''
1 {#
2
3 DO NOT USE THIS AS A BASE,
4 IF YOU ARE COPY AND PASTING THIS FILE
5 YOU ARE PROBABLY DOING THINGS INCORRECTLY.
6
7 Null template, does nothing except defining a basic structure
8 To layout the different blocks of a notebook.
9
10 Subtemplates can override blocks to define their custom representation.
11
12 If one of the block you do overwrite is not a leave block, consider
13 calling super.
14
15 {%- block nonLeaveBlock -%}
16 #add stuff at beginning
17 {{ super() }}
18 #add stuff at end
19 {%- endblock nonLeaveBlock -%}
20
21 consider calling super even if it is a leave block, we might insert more blocks later.
22
23 #}
24 {%- block header -%}
25 {%- endblock header -%}
26 {%- block body -%}
27 {%- for cell in nb.cells -%}
28 {%- block any_cell scoped -%}
29 {%- if cell.cell_type == 'code' -%}
30 {%- block codecell scoped -%}
31 {%- block input_group -%}
32 {%- block in_prompt -%}{%- endblock in_prompt -%}
33 {%- block input -%}{%- endblock input -%}
34 {%- endblock input_group -%}
35 {%- if cell.outputs -%}
36 {%- block output_group -%}
37 {%- block output_prompt -%}{%- endblock output_prompt -%}
38 {%- block outputs scoped -%}
39 {%- for output in cell.outputs -%}
40 {%- block output scoped -%}
41 {%- if output.output_type == 'execute_result' -%}
42 {%- block execute_result scoped -%}{%- endblock execute_result -%}
43 {%- elif output.output_type == 'stream' -%}
44 {%- block stream scoped -%}
45 {%- if output.name == 'stdout' -%}
46 {%- block stream_stdout scoped -%}
47 {%- endblock stream_stdout -%}
48 {%- elif output.name == 'stderr' -%}
49 {%- block stream_stderr scoped -%}
50 {%- endblock stream_stderr -%}
51 {%- endif -%}
52 {%- endblock stream -%}
53 {%- elif output.output_type == 'display_data' -%}
54 {%- block display_data scoped -%}
55 {%- block data_priority scoped -%}
56 {%- endblock data_priority -%}
57 {%- endblock display_data -%}
58 {%- elif output.output_type == 'error' -%}
59 {%- block error scoped -%}
60 {%- for line in output.traceback -%}
61 {%- block traceback_line scoped -%}{%- endblock traceback_line -%}
62 {%- endfor -%}
63 {%- endblock error -%}
64 {%- endif -%}
65 {%- endblock output -%}
66 {%- endfor -%}
67 {%- endblock outputs -%}
68 {%- endblock output_group -%}
69 {%- endif -%}
70 {%- endblock codecell -%}
71 {%- elif cell.cell_type in ['markdown'] -%}
72 {%- block markdowncell scoped-%}
73 {%- endblock markdowncell -%}
74 {%- elif cell.cell_type in ['raw'] -%}
75 {%- block rawcell scoped -%}
76 {%- if cell.metadata.get('raw_mimetype', '').lower() in resources.get('raw_mimetypes', ['']) -%}
77 {{ cell.source }}
78 {%- endif -%}
79 {%- endblock rawcell -%}
80 {%- else -%}
81 {%- block unknowncell scoped-%}
82 {%- endblock unknowncell -%}
83 {%- endif -%}
84 {%- endblock any_cell -%}
85 {%- endfor -%}
86 {%- endblock body -%}
87
88 {%- block footer -%}
89 {%- endblock footer -%}
@@ -1,1 +0,0 b''
1 To compare nbconvert html output to the notebook's native html see https://gist.github.com/9241376.git.
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,171 +0,0 b''
1 """Base test class for nbconvert"""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import io
7 import os
8 import glob
9 import shlex
10 import shutil
11 import sys
12 import unittest
13 from subprocess import Popen, PIPE
14
15 import nose.tools as nt
16
17 from IPython.nbformat import v4, write
18 from IPython.utils.tempdir import TemporaryWorkingDirectory
19
20 from IPython.utils.py3compat import string_types, bytes_to_str
21
22 class TestsBase(unittest.TestCase):
23 """Base tests class. Contains useful fuzzy comparison and nbconvert
24 functions."""
25
26
27 def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True,
28 fuzzy_spacing=True, ignore_spaces=False,
29 ignore_newlines=False, case_sensitive=False, leave_padding=False):
30 """
31 Performs a fuzzy comparison of two strings. A fuzzy comparison is a
32 comparison that ignores insignificant differences in the two comparands.
33 The significance of certain differences can be specified via the keyword
34 parameters of this method.
35 """
36
37 if not leave_padding:
38 a = a.strip()
39 b = b.strip()
40
41 if ignore_newlines:
42 a = a.replace('\n', '')
43 b = b.replace('\n', '')
44
45 if newlines_are_spaces:
46 a = a.replace('\n', ' ')
47 b = b.replace('\n', ' ')
48
49 if tabs_are_spaces:
50 a = a.replace('\t', ' ')
51 b = b.replace('\t', ' ')
52
53 if ignore_spaces:
54 a = a.replace(' ', '')
55 b = b.replace(' ', '')
56
57 if fuzzy_spacing:
58 a = self.recursive_replace(a, ' ', ' ')
59 b = self.recursive_replace(b, ' ', ' ')
60
61 if not case_sensitive:
62 a = a.lower()
63 b = b.lower()
64
65 self.assertEqual(a, b)
66
67
68 def recursive_replace(self, text, search, replacement):
69 """
70 Performs a recursive replacement operation. Replaces all instances
71 of a search string in a text string with a replacement string until
72 the search string no longer exists. Recursion is needed because the
73 replacement string may generate additional search strings.
74
75 For example:
76 Replace "ii" with "i" in the string "Hiiii" yields "Hii"
77 Another replacement cds "Hi" (the desired output)
78
79 Parameters
80 ----------
81 text : string
82 Text to replace in.
83 search : string
84 String to search for within "text"
85 replacement : string
86 String to replace "search" with
87 """
88 while search in text:
89 text = text.replace(search, replacement)
90 return text
91
92 def create_temp_cwd(self, copy_filenames=None):
93 temp_dir = TemporaryWorkingDirectory()
94
95 #Copy the files if requested.
96 if copy_filenames is not None:
97 self.copy_files_to(copy_filenames, dest=temp_dir.name)
98
99 #Return directory handler
100 return temp_dir
101
102 def create_empty_notebook(self, path):
103 nb = v4.new_notebook()
104 with io.open(path, 'w', encoding='utf-8') as f:
105 write(nb, f, 4)
106
107 def copy_files_to(self, copy_filenames, dest='.'):
108 "Copy test files into the destination directory"
109 if not os.path.isdir(dest):
110 os.makedirs(dest)
111 files_path = self._get_files_path()
112 for pattern in copy_filenames:
113 for match in glob.glob(os.path.join(files_path, pattern)):
114 shutil.copyfile(match, os.path.join(dest, os.path.basename(match)))
115
116
117 def _get_files_path(self):
118
119 #Get the relative path to this module in the IPython directory.
120 names = self.__module__.split('.')[1:-1]
121 names.append('files')
122
123 #Build a path using the nbconvert directory and the relative path we just
124 #found.
125 import jupyter_nbconvert
126 path = os.path.dirname(jupyter_nbconvert.__file__)
127 return os.path.join(path, *names)
128
129
130 def nbconvert(self, parameters, ignore_return_code=False):
131 """
132 Run nbconvert a, IPython shell command, listening for both Errors and non-zero
133 return codes.
134
135 Parameters
136 ----------
137 parameters : str, list(str)
138 List of parameters to pass to IPython.
139 ignore_return_code : optional bool (default False)
140 Throw an OSError if the return code
141 """
142 if isinstance(parameters, string_types):
143 parameters = shlex.split(parameters)
144 cmd = [sys.executable, '-m', 'jupyter_nbconvert'] + parameters
145 p = Popen(cmd, stdout=PIPE, stderr=PIPE)
146 stdout, stderr = p.communicate()
147 if not (p.returncode == 0 or ignore_return_code):
148 raise OSError(bytes_to_str(stderr))
149 return stdout.decode('utf8', 'replace'), stderr.decode('utf8', 'replace')
150
151
152 def assert_big_text_equal(a, b, chunk_size=80):
153 """assert that large strings are equal
154
155 Zooms in on first chunk that differs,
156 to give better info than vanilla assertEqual for large text blobs.
157 """
158 for i in range(0, len(a), chunk_size):
159 chunk_a = a[i:i + chunk_size]
160 chunk_b = b[i:i + chunk_size]
161 nt.assert_equal(chunk_a, chunk_b, "[offset: %i]\n%r != \n%r" % (
162 i, chunk_a, chunk_b))
163
164 if len(a) > len(b):
165 nt.fail("Length doesn't match (%i > %i). Extra text:\n%r" % (
166 len(a), len(b), a[len(b):]
167 ))
168 elif len(a) < len(b):
169 nt.fail("Length doesn't match (%i < %i). Extra text:\n%r" % (
170 len(a), len(b), b[len(a):]
171 ))
@@ -1,7 +0,0 b''
1 from jupyter_nbconvert.writers.base import WriterBase
2
3 class HelloWriter(WriterBase):
4
5 def write(self, output, resources, notebook_name=None, **kw):
6 with open('hello.txt', 'w') as outfile:
7 outfile.write('hello world')
@@ -1,6 +0,0 b''
1 c = get_config()
2
3 #Export all the notebooks in the current directory to the sphinx_howto format.
4 c.NbConvertApp.notebooks = ['notebook1.ipynb']
5 c.NbConvertApp.export_format = 'python'
6
@@ -1,189 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# A simple SymPy example"
8 ]
9 },
10 {
11 "cell_type": "markdown",
12 "metadata": {},
13 "source": [
14 "First we import SymPy and initialize printing:"
15 ]
16 },
17 {
18 "cell_type": "code",
19 "execution_count": 2,
20 "metadata": {
21 "collapsed": false
22 },
23 "outputs": [],
24 "source": [
25 "from sympy import init_printing\n",
26 "from sympy import *\n",
27 " init_printing()"
28 ]
29 },
30 {
31 "cell_type": "markdown",
32 "metadata": {},
33 "source": [
34 "Create a few symbols:"
35 ]
36 },
37 {
38 "cell_type": "code",
39 "execution_count": 4,
40 "metadata": {
41 "collapsed": false
42 },
43 "outputs": [],
44 "source": [
45 "x,y,z = symbols('x y z')"
46 ]
47 },
48 {
49 "cell_type": "markdown",
50 "metadata": {},
51 "source": [
52 "Here is a basic expression:"
53 ]
54 },
55 {
56 "cell_type": "code",
57 "execution_count": 6,
58 "metadata": {
59 "collapsed": false
60 },
61 "outputs": [
62 {
63 "data": {
64 "image/png": [
65 "iVBORw0KGgoAAAANSUhEUgAAAKMAAAAZBAMAAACvE4OgAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\n",
66 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEHarIkSJZt3NVLsy\n",
67 "me8Q6PJIAAACz0lEQVRIDa1UTWjUQBT+ZpvdzW7TGlrxItjYSg/C6vbiDwjmoCgUpHioPYhdqig9\n",
68 "FJYiPYmW4klB14NgFGnw4EHpj7UgUtTFXhSEBgVBxIOFggWVrrUqiMY3mZkkLNIK7oN575vvvfky\n",
69 "8yYJIGzgkSlRrULKrivVSkvq6LbxtcaSjV3aSo0lgWyl5pK69V+SRlEsPxNTGYhhDrV3M2Ue2etc\n",
70 "EDmuMmM+IjolrCuHXNoLoQDNSAXdzbjsfFVKTY1vCgFXFIxenG4cFSSzRewAPnN0FugXjPDr45MQ\n",
71 "JwoKtitgXL9zT+CsJeIHYG+Z4H1gwhRU4G/FcAQbbYU3KdDo+0sCK8lRU0guA72uKqMYk9RehHxP\n",
72 "iDIu0NS2v90KGShJYi7T7tgvkrQ2vIT2XtRISWNra6lzGc8/PW3ji4PL7Vmge095YIX0iB71NCaZ\n",
73 "5N3XyM0VCuNIyFNIyY3AMG/KDUvjn90DGmwq9wpIl5AyU5WsTYy0aJf6JFGB5An3Der5jExKHjNR\n",
74 "4JKPge/EXqDBoOXpkxkmkJHFfAFRVhDIveWA0S57N2Me6yw+DSX1n1uCq3sIfCF2IcjNkjeWyKli\n",
75 "ginHubboOB4vSNAjyaiXE26ygrkyTfod55Lj3CTE+n2P73ImJpnk6wJJKjYJSwt3OQbNJu4icM5s\n",
76 "KGGbzMuD70N6JSbJD44x7pLDyJrbkfiLpOEhYVMJSVEj83x5YFLyNrAzJsmvJ+uhLrieXvcJDshy\n",
77 "HtQuD54c2IWWEnSXfUTDZJJfAjcpOW5imp9aHvw4ZZ4NDV4FGjw0tzadKgbFwinJUd//AT0P1tdW\n",
78 "BtuRU39oKdk9ONQ163fM+nvu/s4D/FX30otdQIZGlSnJKpq6KUxKVqV1WxGHFIhishjhEO1Gi3r4\n",
79 "kZCMg+hH1henV8EjmFoly1PTMs/Uadaox+FceY2STpmvt9co/Pe0Jvt1GvgDK/Osw/4jQ4wAAAAA\n",
80 "SUVORK5CYII=\n"
81 ],
82 "text/latex": [
83 "$$x^{2} + 2.0 y + \\sin{\\left (z \\right )}$$"
84 ],
85 "text/plain": [
86 " 2 \n",
87 "x + 2.0\u22c5y + sin(z)"
88 ]
89 },
90 "execution_count": 6,
91 "metadata": {},
92 "output_type": "execute_result"
93 }
94 ],
95 "source": [
96 "e = x**2 + 2.0*y + sin(z); e"
97 ]
98 },
99 {
100 "cell_type": "code",
101 "execution_count": 7,
102 "metadata": {
103 "collapsed": false
104 },
105 "outputs": [
106 {
107 "data": {
108 "image/png": [
109 "iVBORw0KGgoAAAANSUhEUgAAABQAAAAOBAMAAADd6iHDAAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\n",
110 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIpm7MhCriUTv3c12\n",
111 "VGZoascqAAAAgElEQVQIHWNgVDJ2YICAMAb2H1BmKgPDTChzFgNDvgOEvT8AzgQKrA9gPZPYUwNk\n",
112 "cXxnCGd4dWA1kMllwFDKUB9wEchUZmAIYNgMZDDwJIDIPyDiEgOjAAPLFwZWBhYFBh6BqzwfGI4y\n",
113 "SJUXZXH8Zf7A+IBh////v1hzjh5/xwAAW80hUDE8HYkAAAAASUVORK5CYII=\n"
114 ],
115 "text/latex": [
116 "$$2 x$$"
117 ],
118 "text/plain": [
119 "2\u22c5x"
120 ]
121 },
122 "execution_count": 7,
123 "metadata": {},
124 "output_type": "execute_result"
125 }
126 ],
127 "source": [
128 "diff(e, x)"
129 ]
130 },
131 {
132 "cell_type": "code",
133 "execution_count": 8,
134 "metadata": {
135 "collapsed": false
136 },
137 "outputs": [
138 {
139 "data": {
140 "image/png": [
141 "iVBORw0KGgoAAAANSUhEUgAAALsAAAAZBAMAAACbakK8AAAAMFBMVEX///8AAAAAAAAAAAAAAAAA\n",
142 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEHarIkSJZt3NVLsy\n",
143 "me8Q6PJIAAADAklEQVRIDbVVS2gTURQ90/wmk0k6tCJCsR1SKShIsxE3CgNWBKUxq9qFmqFqShfF\n",
144 "UKQrkaDiF0pcCKYgBBcuBLV+wIWKARe6kQ4UhNKKWdiF4KIptmA/xPvmzZuMxdYUzIPcd+655568\n",
145 "vLlJAL6G32oOasQWNHz5Rvg6nrKh/mygfSzlX2ygPaBUGmov6//NXs1yq4sex2EPrsHemTd2snNg\n",
146 "tkb+Cx1zBL6SqwxZLvQAKYHzKZaPY4fh4TeHd0S5Nox9OClItm/jiU9DrEwwVEawpiVis9VkimqX\n",
147 "AOr4o2cCs/0BT2I5+FYJRhJbePQxgzcD7QLEqtV5gdnu2Icr3L45gcCyt74Z7neL4SLQ0nm4S+dM\n",
148 "YCz1gSPHnhKZDWyHhcCCNKwjqaF/TkwGl0L6nClie/wc1D1xdoNsSLhT0IJkhi7Lzr22xb8keE/N\n",
149 "Pm0Sc9yEuhRUyuiG9HzvFNeImCyq39SriOhtQI7IV/TiTqE8glqwohjE0NJwiANxOZTdZoxtfzSa\n",
150 "x2tI8DtHcKQoQFmV6f1XT2swibxFL+6k5EgenhBCqKLTPX3ULnaYdDlaTMcCSd8zuXTvBq2bJUJr\n",
151 "lE4WgSV5ZRdBzLFgO6nzhJp1ltvrlB2HCoWxQuG+jTvt2GxBWUZaU2mMApZNuSHA3vJpCliRhqqs\n",
152 "ZtvbTrb9ZIk+i70Ut1OcnpgeKskTCFUwjaYy8Jhr3eiefq0HIfa7yC6HOwVyULRuNDn21JngbcL+\n",
153 "E8A+MNnSxb+w59+Cj2tELJBbjEZr8SGwn0j2aLkTPdp08R2OcKV6fXB3ikPH3n8tM5WTfrETtZcw\n",
154 "g3QWH0dH7nKNiMkszqo/EDafaHhJ5Bm6ee4UtdAabxnMcmUUl0SnYx+uVqs5XAGN9QGgdeCrASv0\n",
155 "3TmCsJcOdhnozexD38goK9HXynEKr1OKDs9guhQD039kGySyIQpJAdbvJ9YTlPvyUl3/aLUf34G/\n",
156 "uGxIyXpE37DoLbAHwJaU53t9MRCfrU8o/k4iRn36Lar8Wd5wAfgN4R6xelyy/ssAAAAASUVORK5C\n",
157 "YII=\n"
158 ],
159 "text/latex": [
160 "$$x^{2} z + 2.0 y z - \\cos{\\left (z \\right )}$$"
161 ],
162 "text/plain": [
163 " 2 \n",
164 "x \u22c5z + 2.0\u22c5y\u22c5z - cos(z)"
165 ]
166 },
167 "execution_count": 8,
168 "metadata": {},
169 "output_type": "execute_result"
170 }
171 ],
172 "source": [
173 "integrate(e, z)"
174 ]
175 },
176 {
177 "cell_type": "code",
178 "execution_count": null,
179 "metadata": {
180 "collapsed": false
181 },
182 "outputs": [],
183 "source": []
184 }
185 ],
186 "metadata": {},
187 "nbformat": 4,
188 "nbformat_minor": 0
189 } No newline at end of file
This diff has been collapsed as it changes many lines, (1584 lines changed) Show them Hide them
@@ -1,1584 +0,0 b''
1 {
2 "cells": [
3 {
4 "cell_type": "markdown",
5 "metadata": {},
6 "source": [
7 "# NumPy and Matplotlib examples"
8 ]
9 },
10 {
11 "cell_type": "markdown",
12 "metadata": {},
13 "source": [
14 "First import NumPy and Matplotlib:"
15 ]
16 },
17 {
18 "cell_type": "code",
19 "execution_count": 1,
20 "metadata": {
21 "collapsed": false
22 },
23 "outputs": [
24 {
25 "name": "stdout",
26 "output_type": "stream",
27 "text": [
28 "module://IPython.kernel.zmq.pylab.backend_inline\n"
29 ]
30 }
31 ],
32 "source": [
33 "%matplotlib inline\n",
34 "import matplotlib\n",
35 "import matplotlib.pyplot as plt\n",
36 "print(matplotlib.backends.backend)"
37 ]
38 },
39 {
40 "cell_type": "code",
41 "execution_count": 2,
42 "metadata": {
43 "collapsed": false
44 },
45 "outputs": [],
46 "source": [
47 "from IPython.display import set_matplotlib_formats\n",
48 "set_matplotlib_formats('png', 'pdf')\n",
49 "matplotlib.rcParams['figure.figsize'] = (2,1)"
50 ]
51 },
52 {
53 "cell_type": "code",
54 "execution_count": 3,
55 "metadata": {
56 "collapsed": false
57 },
58 "outputs": [
59 {
60 "data": {
61 "text/plain": [
62 "{matplotlib.figure.Figure: <function IPython.core.pylabtools.<lambda>>}"
63 ]
64 },
65 "execution_count": 3,
66 "metadata": {},
67 "output_type": "execute_result"
68 }
69 ],
70 "source": [
71 "ip.display_formatter.formatters['application/pdf'].type_printers"
72 ]
73 },
74 {
75 "cell_type": "code",
76 "execution_count": 4,
77 "metadata": {
78 "collapsed": false
79 },
80 "outputs": [],
81 "source": [
82 "import numpy as np"
83 ]
84 },
85 {
86 "cell_type": "markdown",
87 "metadata": {},
88 "source": [
89 "Now we show some very basic examples of how they can be used."
90 ]
91 },
92 {
93 "cell_type": "code",
94 "execution_count": 5,
95 "metadata": {
96 "collapsed": false
97 },
98 "outputs": [],
99 "source": [
100 "a = np.random.uniform(size=(100,100))"
101 ]
102 },
103 {
104 "cell_type": "code",
105 "execution_count": 6,
106 "metadata": {
107 "collapsed": false
108 },
109 "outputs": [
110 {
111 "data": {
112 "text/plain": [
113 "(100, 100)"
114 ]
115 },
116 "execution_count": 6,
117 "metadata": {},
118 "output_type": "execute_result"
119 }
120 ],
121 "source": [
122 "a.shape"
123 ]
124 },
125 {
126 "cell_type": "code",
127 "execution_count": 7,
128 "metadata": {
129 "collapsed": false
130 },
131 "outputs": [],
132 "source": [
133 "evs = np.linalg.eigvals(a)"
134 ]
135 },
136 {
137 "cell_type": "code",
138 "execution_count": 8,
139 "metadata": {
140 "collapsed": false
141 },
142 "outputs": [
143 {
144 "data": {
145 "text/plain": [
146 "(100,)"
147 ]
148 },
149 "execution_count": 8,
150 "metadata": {},
151 "output_type": "execute_result"
152 }
153 ],
154 "source": [
155 "evs.shape"
156 ]
157 },
158 {
159 "cell_type": "markdown",
160 "metadata": {},
161 "source": [
162 "## Here is a very long heading that pandoc will wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap and wrap"
163 ]
164 },
165 {
166 "cell_type": "markdown",
167 "metadata": {},
168 "source": [
169 "Here is a cell that has both text and PNG output:"
170 ]
171 },
172 {
173 "cell_type": "code",
174 "execution_count": 9,
175 "metadata": {
176 "collapsed": false
177 },
178 "outputs": [
179 {
180 "data": {
181 "text/plain": [
182 "(array([97, 2, 0, 0, 0, 0, 0, 0, 0, 1]),\n",
183 " array([ -2.59479443, 2.67371141, 7.94221725, 13.21072308,\n",
184 " 18.47922892, 23.74773476, 29.0162406 , 34.28474644,\n",
185 " 39.55325228, 44.82175812, 50.09026395]),\n",
186 " <a list of 10 Patch objects>)"
187 ]
188 },
189 "execution_count": 9,
190 "metadata": {},
191 "output_type": "execute_result"
192 },
193 {
194 "data": {
195 "application/pdf": [
196 "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\n",
197 "CmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\n",
198 "IFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\n",
199 "L1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\n",
200 "PCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\n",
201 "IDIgMCBSCi9NZWRpYUJveCBbIDAgMCAxNTIuMzk4NDM3NSA4Ny4xOTIxODc1IF0gL1Jlc291cmNl\n",
202 "cyA4IDAgUiAvVHlwZSAvUGFnZQovQ29udGVudHMgOSAwIFIgPj4KZW5kb2JqCjkgMCBvYmoKPDwg\n",
203 "L0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCAxMSAwIFIgPj4Kc3RyZWFtCnicxZi/btwwDMYz\n",
204 "a+wTCJ3aRSEpiZLGHtAG6FbkgL5AmwTBXYCmQ16/dJycRcWq7SV3k81Pf76fzyZpo703l1/Q3v61\n",
205 "ZL9bsE8W7ZUBOTpajOR8ycGnKOcHdZ6Tw0KY5fAgojq9Mw+yKA2Lgiv+9WdvZeCVoewCR6ZoCVyk\n",
206 "jHIkewVw0IYPdTix8y/hao0qKvveiHOhcF5t6qJgqWDPRRXlkwmzm92vHp1g8rYzzf5on8xuby+/\n",
207 "oUWw+xsjO2L0w+gk06Ld/zKfPn64wAv4bPf39uu+XeGZwITgAuSQCQMVZbtRlHWt1fYbZRNCIAdA\n",
208 "5F/mnjAWEFiiEb0vlGNSCI2iELRWIzTKJoQYXSglJU7PcyeEpf9BDFAJWDhQZgXRKApCazVEo2yC\n",
209 "SOiQ0efhCnANQQsQhRz5BNHHhEFBNIqC0FoN0SibICR5QCjxde4E4RcgELLDVAqCTPQ6nzSSwmjE\n",
210 "mqOVNoEgkCuFwuvkiSQskVBwSDTejKhJGkmTaFGRNNI2Esyu5PLyp9QkcYlkLpHr/K4J5jK8Gr/R\n",
211 "uQ9Sc8bxlW1esL1YD6BjermIrTGdHI8VAXm47sDr8unkz6Pj/Mb1FG1c18Nnw6tcyzM/bIahMryU\n",
212 "eCZzUkOk+rSWp2hjuR4+G15pGUazvjgPle+lJ3RyGIPUvje+p2jjux4+G159qSPIZpXl9fc0RykT\n",
213 "byxP0cZyPXw2vNby8yy5p6hynVe77vRaXKeDFemDNxVUuc6JXKqfQWkIJs9/ZpMColBaaSmyffxt\n",
214 "f9qHsZ12BFKZMbIUZxkbEBOHBCw20unEPk49atUtXxlhoITscwhNv5cdJ5TWC1TVO2ghBUkqYQRX\n",
215 "S1WC9Mw788O+J9S896ON0gXIxBDZqwp4aBUxFQb3puE9CefA6rk/Dk+NzJQcSZLgFZdSzH+IK+Xd\n",
216 "wXr2pW/1LnNhOaeowZRiusjnBevZP9o8ZK4i60pTrp8vpZgu8nnBevalSQfHsiYDSJekTCrFdJHP\n",
217 "C9azL2BFsn2W/MaQGrBaMV3kM4N17A+vI0k8JOZEgM2nESWZLvR50boAwoaylaTvBEneMzSbkkwf\n",
218 "+8xwPYLx7YtYXAafC2s4JRkpW5B5jtvW0gg3mk4+UZSmm9SHrBX9z/WKNxc9fsvXuu7w+ebt2ph/\n",
219 "ACMXFgplbmRzdHJlYW0KZW5kb2JqCjExIDAgb2JqCjg3MAplbmRvYmoKMTYgMCBvYmoKPDwgL0Zp\n",
220 "bHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aDEgMTkgMCBSIC9MZW5ndGggMjAgMCBSID4+CnN0cmVh\n",
221 "bQp4nNS9eYAdVZ0vfurudavq3rr7vvftvdOdTtIJi6QTsnQATdhCgsYECRAWIVFAwAUGWQL6JjDj\n",
222 "AEEQRJYAvsnNnbZZxjfkzVMExhl7HImgeZBRCIn6BnUcRudB8vt8zqm66QScef/+DqnvreXUWb6f\n",
223 "73pO2QpNCBEH8Ynq8iVLlwleawdAhLl81cozz//y80lcm0LoZyw/8+zFIiXCQvvNBj5feebw6M3v\n",
224 "9H4RL+zA9YbzP3ne5v959xPrhTj9QSEC2fOvvrIaXKRVhTj3RDyvXrj5ok9etDjUI8Q5T+Od0y+6\n",
225 "7NoLR5ee8b+EWLdJaGdt2LTxk9fkfn3RLCFCWSFWbN10wXkbn8ze+XPUHcT7Y5twIzjoXYPrjbju\n",
226 "2vTJK68pvnny6UJ4QujPvvSCT12+7NTTbxHarheEqC+57Irzz1v629+uRv8fE8Ib/uR512z23hfG\n",
227 "2LWtHM/l533ygq985Ml/EdqPMD/jbzdf8ekr77zla3cJ7fVpjGHW5k9dsPmkX106T4i1eK4NKd6I\n",
228 "xZenf/fv66Mn/psoeCWjPtds3cDf7994/87Daw/t8x7wfhOXuvAIVfCe98ChPyM9vPbwWryliaOK\n",
229 "dhPvgG4UQXE2sFDPw5iZ0B8B0YTXE9XuEH7h89zuAQfEqepX+7gY1bKs5/d6+OPFUHauEtVT3LZP\n",
230 "W/GRlWJcVP+vB2P4a45BW4rbX5X9/sh7j6jiPw+Hqv3OGU0aDf3lBxxXiw2e3WJEHm+K1Z7TcX3s\n",
231 "8aawPINigzeMOj8UG7SQPJZrocNv4/gNzj3az0SEbaE/HhHvdbK+OhaLEW9LLJS/H3B4TlJ1ZF+D\n",
232 "YlQeJ6E93McYz3rfcf7h99Aexx7wnHT4t51jUGTkEURbziF+LU7gr/cs595u5/desQrHWu3bouKt\n",
233 "igF573wxoX0KeLwmTtd8wtR8h/8Vv4tw1MSvD78p7/9OrMBc0e7hn6tfjHNQfERep8XZOBahvRzu\n",
234 "ldFeL377OB/gPIdtoM+P4HoA7y3FcQ7ORz7gGIM8baEkEj/5zulixGn/bK0XfeZkvyPOr8DRLXYc\n",
235 "Xos+ycez0Nc7fA9jnIvjQ9oJ4gQcS1FvAs8mtQ+j/q95Lk7g2OX88A6Of0b9CTk29nsv5yYC4N/J\n",
236 "ePYbZ/wT+L0Jvyc74+Vvg2OceXjvlfwpy+tBsQkY9+AY1y4WY9rpoqL9iajgWa98Dt5D9kfA6zEc\n",
237 "Ie8i0e3OF3zIuWMhTzG+YRyDwOx+HOvdA+8tmHFs1E4TpxILjCGrPSFqPDCOk4gRecyxE2+pB4Pi\n",
238 "LNSPyHGAlxjnIMZZx5z3oP8JWRfXcu7HHMRIyv8PRQS/PLfdwzN4+BD6zfBgu5RPxecO33GI1ezH\n",
239 "weA3zvEmx43fFxxZIS83eL4movI4IIblwTHMEVWMYcLzMfDkTdGn/Rp8rYgLtP9z+Pe4l/N8TywH\n",
240 "j9fTHoCHZ+BY7vyeQZkhj4+yCa49mGkXaAM+wDbQJsw8aB+UjYA+hA6/C9twBo7EMfahc3RshGsn\n",
241 "XJswsx/XJhxtG44cH2QjcEgb8UfsAnV35iF1Venr+/Xx/GMOhbsJbF7B8VvgEqLezNQd58jDy53j\n",
242 "6Id7xGfqCGUURxJH2ZXRzgF5nHl8kOzJQ8md3ZGzFnj7U8jlh6UOSUzJC5QR+kld9/uFN+CUoJ8l\n",
243 "6A8GPSy+gN8fCgZDekgWf0g+VlX1gN8pHtwP4K4v6A94vfJFr9/n8Xn8Hq8X9/y4CPg9HlUbHQb9\n",
244 "Xq9XvYr7QZ8PV6iuuvSg75BHvqZKCC+GQvINtoIzHd37fPJ99hX04AJPvQH+C3k9ul+17vehbTxj\n",
245 "XVnT4xQvJhyUcw3iKYYu5+Rx2RB02CCLywd5TSYcKQ4jnL5QAoHOfdWjnJUzGE6albzu5P0cHSbi\n",
246 "DegIBcLEQfYY4CHHEQgFvbI6miMGDg6BkDNMVtTVKCQOuoTOBzhkL152DRQwM698BcwNeDzqBXQY\n",
247 "DKi2MXX8C3KEAY8aN36CIY+O+kFXNnRUCoV8Xh8v0KDXG0b3nanhDnAIeCkHpCGfJxzwOWOTDA2Q\n",
248 "QcfgQJaS/ayAriTPPYoNQZcNnHIw6PKBwiCZcKSounogEDgKGKc40/F04J2Bgyv1Ph9nHwQOhhEI\n",
249 "CK/sISj7JeoBPaRwgFiGdV3ngRLQg+74QsFwh1HAEwhBiPRAUOHgpWhCOL2UXdTzecl6VRsdSpTV\n",
250 "WDHPkMTBq3iKH8i+DviC7kzDeFnXMQFeoEGv1whSYp2peX06NYU4hAiF7vMaDg4BpcAB1vUeXcA+\n",
251 "8i9ITcZ8A5y8R7Eh5LKBU5aK6FV4Kia4KLmMCIU7Aul35VjWcabjTBW3fEqHleLI9wkuZh9CXGxa\n",
252 "xEH2EFK9YADBsK64iREaum6YhiyhMAcYUsMxJGK84cU5Xgz5wzhcHMAYL7jmM4Kogq5wrmZomgE5\n",
253 "uQD1z4P7IRqZoItDgDgYXsUJSkaIF1AiH+URrYS9XgtjVTOhdPkMWhlw1qdDJYNhv9cM+h0F1/1S\n",
254 "vQNKrGcU6LguK3AYEC925PEqHrhsCKPoussHKCY4ASY4KDlA6SFDckExNujKs6NIUhR9zkyU4Qr4\n",
255 "HJFSmhSCxOqGEJYVDAqfahH9KoRDR3AIGuGwYTk4yEE4Q7X0o3EAa4wjOODuDBwCXr2DAzrUQ+5Q\n",
256 "PBT+4NE4YOoGbuouDhZwMAyFAwA0vD6Jg+QzrBVxkIOAPhIHw++1HBwoUR+MAyYcDrP9MI2wrljq\n",
257 "IRvCsig2HIMDLhUOZEIHB90KdpAJhf4LHOSYj8IBbtanW0JEoh0cdLcXMDysHAlGCBzMiClLyJS+\n",
258 "Qo4UOLiS4w2asFI4NSF/jgnkXZpyn0nnAubSvUqwo5EgJ+eTPXl04gCtD3kdyxEkDhbqS5/ENyK4\n",
259 "ME1lFzAXy+uNuBKr3LBJa4/24Mrwzwx4IyHHdjpKSy5I7s/EgXMFDkGSkMIBXYcdiZNsQKH7hLvX\n",
260 "Hf0gE1Rx5BbF6ozGASZ0xKBRFNVUdQZENFzBI66Go4N59+kRIaJ2KCR8snPioPAImR0cQtAFK2rJ\n",
261 "4vBe4RB1OgXOIQvQhYFDSA9IHHyQfcQqIQQjlsTBBw66OERRFXOTI8E9X1ji4OvgEA57LV94Bg54\n",
262 "2bJg43kBHPx+G91L5hIHr9/y0SiiFyPEqgFf1MEByuHIphTGIwXWLSyZrVNdMV/JUq8ffFc4yKFS\n",
263 "9MLGERxwn0zosNrRnajigjvcGThQ8OkjjsaBouPgEFI4GFEh7FgHB4P9spi6lD9wBwpKDBwcwpZ0\n",
264 "2lI39KghRyJxiEgVClpQcxcHHSjoxIFOPugzdAcH3bZDUshCHC/4AZbDV+kuDiEHB91wZxrFRSQC\n",
265 "28ILhQP4pWYi9cECpjq0Ba4MUUUk4IvpAcWQoOVEe9LPzyh+TpYSTXUNozUcEgdDab6UNHVKHEKy\n",
266 "O4cJYSdqUUCZRlRxQQ23g4/UeZ9PxtvOPakHDAoCjsu3JBbAwRYiFtN14XdxUI4Agm+pWB/MAAaR\n",
267 "WESWcASj1cNyOEbMcIfjg26YcOahiN7BQXdw8Ec6OPiVHqFDafXCfOANGz7DwcFJLzAWfxT1OzjY\n",
268 "R+MQ8ftjEgelHuzij+FAJzYTB/9MHCxKSJjqGjalKTC8fgcGS7JBzVPioAaDKzBBGisZQToVYnqn\n",
269 "KAVxcJCRke4GWkfhEDiCgwlHbcSEiMeJg2It+pE4gOEKhzD6BwbRWFSWcJRO23BxcDXYp9uYsGmF\n",
270 "olBzmaJIHGBxwKQoJQ04hB0cwujQoLLLC68BHBhBhn0qd/KHXRxMsok9xPByNAqF5gUa9PvjkEJH\n",
271 "BNBDIAocwmgvaIUDqBr0xcPBDg66jLoJ4FE4kNl4YChiyJAQFs4yLcltxQYUJZBh2R0uwQSJg/TY\n",
272 "Lg6uHaPPCTvPpGNBR2EXB4MJQsBNQBRqHJ2pB/0WcEgkwmEHBxMdSXmIGNGIEk4oKDCw47Yshm26\n",
273 "44sYCUtqEHEO27BYFnAImw43wRVKNphkc4Yhv4VzBRw6NPkgTFvsxalJHAx/0NUHmIKY33RjNMOI\n",
274 "40Xbho1Hd3jR9vsTGKtKaqQTsyFmBvKSoGUETMMO+hOGxMxwgglG3ob/qBJQzA4bVFcjYkqWEgdL\n",
275 "ab4yOCiRiMsHGEhwwrb5xCmyqpUwHHNON+7ad9PpkSMMONWdgEolUcruyLDTbyWESCaBQ0CZPuAt\n",
276 "cYi6OIQdHBIKB1PiYKqRzsQhFo6ErYgOOGbgEHZwsI7GAR1GTEaBEgfofSSMTMj0d/QBU4/5I6Zl\n",
277 "gu0cTRygxGKYA2QYViLm9yeVmVaqThzAaIUD/sWC/qQRVFZep+0Od3AIzMQhGjWNsEl1RTgIAxCJ\n",
278 "EAc5t6jDhg4O4f8Eh8gMHCz1SAq14UwHnSlHYzoBFV2+41kgShE4auKQShmGCEizg6E5AzDtqGrF\n",
279 "ChvAIJaMyWLGaDxNVTkhe2PHfiNuRDEoPWZY7vKLQRxMZFExvGACB9PBwUSHUeIguezD/Sgj+Rk4\n",
280 "QAYS/qgbK5tmAhoSj4ckDrAScb8/BSlU2i9xiAEHE5MNRc2gZcZD/hQibDlR4MAuKajH4KCYbVg2\n",
281 "cLCACBnq84PvygLL1yl6UTIiEJaw45JMMB0f4jAiklBckDhIJTYVZ/5LHEyaeeIQTQqRTndwwBhs\n",
282 "qRe2GVM4GNBd4BBPxWWx4hYHoHBIKR1iRGEmAB3cR9yMhJxFLqIjcYiToTr46verztFh1GIUKHGA\n",
283 "I4pSYy1nDRFvYerAATGaqax1CiBKHCCtSP4TgWAaY1USKZPYOLTPxSFCHNKmim0MI2r8ERwo2hZx\n",
284 "MEgsaYN8QQUCH7FQ9KK2NCyyO+BAJsg5y5Gp2ilXHqEglrLrNFemMx0IiuKUJVNDnemjuiNxiIZD\n",
285 "gWhKiEzGNF0cgLfUtJgVt2Vegv7NRCwWTzs4JCISJhYrFZWWDN0GgIPt4KCrtS4/7wYsJKtxMM/S\n",
286 "A1EroHCw0KFNHCSXfQiEbIlDoIMDdDERsN1YGTjAiCQSiHnYHXAIBjMKB0xe4YBM18LUENqFYK5D\n",
287 "gYylcDBVMGFRUI9agnNwgEeMAYcIELFxTRzk3GKKDZyyHWPernAALLgjnbcqylqnrIiru+rEch08\n",
288 "tf5YHMIzQuAYcLARuEbTQmSzwCEoG4yiHzUAKxGT44WYm9CFZCYpSyQZIS+kjYpkbOWmMEUracUw\n",
289 "KLiMqLMKG3BxCCbI0DD4GnCcEDq0I65I+KLAgTlqxFnLxVu2HUgG7IgNky1nlA5ErGQS2QZsCXBI\n",
290 "BoNZjFVNXOKQcHGwESpYST2QtXTH28Ypp8xEj8WBoo0K0TjtbCwibZAvqCxPLK7YkECJxVw+0DjG\n",
291 "yQSFg5RXFjsj7zgexXL1JGI500HArfxIZAYOinVxgotkzs4IkctZlghKcafWScWIR1wcbNNKJRLJ\n",
292 "rItD9Ej32Rk4pGCxYraRJA5qsRF3zUAEF0kwLwIcIg4OEXQYkziQy75oFB7kaBww9XQg5uYskUgG\n",
293 "xjyVQphPmx4MpoLBHOyFsgxcOdKT8NERTFaPR0LRSEoP5CIKB9gzFf4ZVKSZOAQVs61owiQYEWmD\n",
294 "fGBDTGm+ZIPEIU5GmrZ0VOBEMimdtyrKa2aPaIjCIaIcfAeHkFNdRa9GB4cIpSRmhoLxnBD5/Ewc\n",
295 "EmoAkWRcpqsWeJRJJFK5lCzRNIcQVZVzMenGcCMQSUfiGJSZitjhIzhYEgfcIw4xDEt1jg5jUXco\n",
296 "Phs4UGMj7n6GFcDUOzhwNNlANJJOI06l1QgG08FgHmKgJFIu6qQcHMJxhGyRtB7Iz8DBkknRMTgE\n",
297 "gAPEKmrZCYiDHY92cJAlodhA0Ysn5NpkzMGBTOjgoBgRzykuKEMlH1C5nB4tFwe85uDgpCLS7iAq\n",
298 "RwJBHAqFSESEZIMx4C0NVDKaSjo4RCLZVCqdS8tiZ2zy4oNwSETiMTMdibk4RIhDFHlLmkmgEYhH\n",
299 "A8oJRdFhXOLAuMAPIxTnmk30CA5x4hCPxh2nGc3hxUwGDs5WOIRCBXQ/A4c0rGA0RP8U1WPRTDhQ\n",
300 "iIaVw5OGFOEQDEZALbw6MIDj5GjEhgoDjJj0Bf4QIZBSrww/SjKpcGBnuCQTOGvlSBRoM3CIxaLu\n",
301 "M9WjwsGZiLMSQhzUjSSsWQIpP3EoFomDNDuwfimpaSk7rXCAmEegC5l8RhY7A97HbDnWeF4ld2gu\n",
302 "GM1Gk9FE3ATPwwG5CAzZD0aCNvKWDF6wjWACHFRuDR3GY/C6UbLVj8QgTo21g86aZSQYTwRzwbjK\n",
303 "WTiafBA2GDjAT8bhNTOhUBH2QumKxCGDMNAO2XY4aeuoGg4W7bCtZDIlxZMhaPCoEqJoo0IsBXFA\n",
304 "WB6JJ4hDMknLk0wpNlD0FA6RuIMDmECbrEamGJHIKy4oQ2W7o3Z6pKSEnHszcHA8fEThkMwLUSpF\n",
305 "o+/HIZNycIhGgUGukEPJ5mLZOBtUlQszcMgRh6SVicYNtZsIU9LBAfVM4hBQnaPDhA0c5IU/Hg8m\n",
306 "HByUqEYCiUQgh/oJV+IKACWbRb4A2w0As6FQCWLg4gDf5+JgJO0wqoaDJQeHaCRp/VEcKNnROM0m\n",
307 "wnLpC/yKDR0cKHqplMsHKmUGbKAtcHitaheO4KAeyVFD0WkaaJ10555aNzedVIR2BzgkI8ChIES5\n",
308 "TByk+U+kUypATcdcHGAoC+i9mJMllotTJhUOpQRNGQUgaOftlJ1MWVk70cEB6ARj4FI2hpjDDCYh\n",
309 "ycqtocNEnDjEMBd/wsEhFgy7+pBIBvPBhModOZpiMB7L5ZD2wgbgxVwoVEb3ygpzoSCcRawUC8Vi\n",
310 "RioWRlUjWI4ZsqtoNK3CcIv5eDAYOoJDMknJjsbTUYIBHJLEQVkeFMkGiUPa5cMMHJyRKUakSooL\n",
311 "0rHKRzEVaHX0QXfqy0RPrQQoVqRhzFKRcChVFKJSsW2hSxyS6XRGDSCWld2HIOZ2MZvNl/KywBax\n",
312 "QQVaKTkThzSsaSQHHJwdKdwlDrqeUzikOjigw2QcqikviAMiEAzMxSEaTBKHZCzl4lACDvm8wgFe\n",
313 "M6/rFXSvrLDcNssRB13hkIjljWDFwcFGYIHyfhxCIZoYWpYM3FcinZC+wK87OGQUG7Io6bTDBwYM\n",
314 "4ASY0MFBMcLFgYXsPxqH6H+KA8KrVDSsp0pCVKvEQQoBRCQrLV42nss4OMCe53KFckGWeCEh1UVW\n",
315 "LieVc49BFAuxTCyVjuRjSXe7CiyKhuIhXc/HUc8KpSDJKrxAh+kEcWCM6E8m4MmBQzzk7ChEQ5h6\n",
316 "IZRWOTxHUw4l4oUCsm84UOBQ0PUqZAbsZddcwc8jIInrcfinuAF7aYaqcVPFEtGMCsNhMEJHl1Qq\n",
317 "m0WFRJb+LpOwYQrSfl1iAC4oNtAEZDIuH2wbl2ACfaNTlO6UFRekoVE8kfYi7kwHguLMxFmRkmuX\n",
318 "St5hzNLAIV0WolaLxYQu3TBERCUK2Xg+q/ZsUnYMulCsFGVJFJNsUFZOVlJyRBKHInBIp6MSB7UZ\n",
319 "FYPBnolDuoMDOswkEYXKiwD8YAYe9ggOdghTL4YyKofnaMqhZLxYNA2LF7oOHGoQA2Wh5XJqB4cM\n",
320 "cSiaoZqDA5McmuYPwCGdBg4wflm4r2QmIX1yQLGBOEg20ARksw4fUHAJJiQVswmUql1J/Cc42C4O\n",
321 "uPU+HJiCZeywnqkIUa8fwSGbzckB5BL5nIMD7Dl6ryocksUkgzpVuYqYLillIxQvxbOwptFCPGXN\n",
322 "xCGBi0ICeEVCGUiyCi/QocIhgbkEUhIHw0iEjBk4lFA/oyLIZLISSiYcHFJ4sajrdXSvvKHEoQAc\n",
323 "EnoiYWUSRioBHOoJU3YVs3PSWjA1DoU6n2HxjKYeFVI5qGUqm5Q+WeJAY5TLdXDI5Vw+IHBzcXBH\n",
324 "pnCoKi6oSFf2K+124ggOTv0ZOChW5CQOhp6pCtFoxOMinJW2MJfLS4uXTxQUDrF0LF4pFEq1kizJ\n",
325 "EpPrpKycqqWP4FCO54CDXTyCAyKbGHAIh4vH4oAOsymYSHkRQDyShWU/gkMslM2GyqGswoGjqYbg\n",
326 "jEoWMnsUXS+Fww3goCy03J0sIkBPoD0rmzBR1Qo1EpaKrWM5aa6ZGh+Fgw6O5/OJZDyVjxGMZDwL\n",
327 "AAJhiQG4oNhAU6xwAB9QcAkmpBSzpd2Qpaa4IAPN9+FAy2k495yldCclJA6IJLIxI5ytCdHVRRxk\n",
328 "OAQRKagBJIt5uZ4OcxOHLpTrZVlS5RSDOlk5Xc/INAfN6YlKIpfIZu1SIq1wQGoCx6kn9XC4lARe\n",
329 "ET0LSVZhHjokDkaCsXogndIlDknd2dOK6TAFFdTPqggylarpqWS5bJkROlFdL4fDXZAZ5Q0lDiWk\n",
330 "RclwMmnlkib8lqV3JS0V08XyMrxkaqwfXehyUSFdgNlM51PSJwcUG+gFJBtoAvJ5hw8ouCQTOGs1\n",
331 "MlW7rrigMg7Zr0o8nOlAYZ36M3BQrMgDhxxwyNWFaDYTCReHfL4gPU8hVSqoPUwIJXSh0qjIkqqk\n",
332 "O91nGhkVNxGHaiKfyGXtciITUV/9wLXqcT0FHMop1IvqOUiyCi/QYS4NHGBkUqlAJq0jEjTNlG4q\n",
333 "BsV1iGAV9eVaCkdT19OpSgU4wInixUo43ET3ykLLTbAyAvRUmPFaysykKpbeTFlqbEhyGNbQYBwN\n",
334 "AyZcLDJSVzikpU+WONAYFRQbaAIKBZcPCShlCUzAg5RTFA4NxQUV6cr7KvFwpgMcnJk4WxrEQb3P\n",
335 "FCwXN8O5hhDd3cDBkGFptlAoSotXTJUdHBA4QBeqXVVZ0tUMG5SVM11ZOSL6zmQ1WUgivSgnj8XB\n",
336 "MN6HAzrMZbgvp3DI/Kc4cDQNHc6oGrEYv2fC4aphdEscKFFy80XigMlG8ikLVSN6dyry/4hDhmYz\n",
337 "U8goHAyJAbig2EAT4OAgAyhcggkZxWwCpaL5LsWF/wIH3HJWyuVafgeHfNw08l1C9PQkk8KQYSn0\n",
338 "sSQHUEqXixKHBBxWo1yuNWuypGsZqS4s2aZadJI41IBDPherJLMuDkloiZ4GDpU08LL1PCyKCvPQ\n",
339 "YT7DfTmGisFsRs8nEqaZdnFI6Pm8XkP9fNqJIrv0TLpWkzhkFQ49kBlloSUOFQToaSOdjhTSVjZd\n",
340 "i+g96YgaW6JI/qVpMI7BIZ8vlVAhWwIO2WJW+uSgYgO9QAeHYtHlAwI3cKJWw4O0U1TtpuKCDPiz\n",
341 "8r5KPJzpwHA6M3G2loiDer8IY1ZImEahKURv7xEcYP+k5ymnKyW1p4/+uyqVWrfCIVPLskGFQ3dO\n",
342 "jgiwhlP1VDFVKMarqWxUfeQGHMKJcDpsGFWJQ7gAi6I6R4f57BEcsmHggIGFI2qLNwEWhevhfLrg\n",
343 "zqgZzioceBEO1wyjF90rbyhxqIYVDlEHh3BvB4dSB4fwzKKHC4VyOZ1JZstwXxKHgoNDUXoByQaa\n",
344 "4lLJ5QMCN3CiVssqZhMohUO34sL7cHCmA8Pp3HsfDiXgUExEjEK3EH19qZQwZFgKEXFwyFTLak8/\n",
345 "n0zBJtV76rJk61kGdrJyrgexdVYqYjjVSJWIQy2Vi6qvEUMpOM5wBjjUMsALOECSVZiHDgvEAcY+\n",
346 "kwnmsuECPKyVCUcVi5LhQj7cQP1Cxokiu8PZTL0ejdgMZgyjbhh9kBnlKeVmZA04ZAzEzcVMJJep\n",
347 "R8N9maiKrZFsMrzkUtEH4IAKOeKQK+VkbBQkG+gUHBxoistlhw8ouCQTOGs1MhXN9yguyIA/J/tV\n",
348 "CaAzHeDg1Hd2LOSeilK4JHGIGsUeIfr70ylhyrA0Xy5XpOepZGouDvCrtVqjtyFLtpFjg6pyr8IB\n",
349 "sIbTXelyulhK1NN5W1cfrDg4mGadi7WxcLGDQ39/qpCDq5IXwXzu/TgUw13AoejOqCeMoKABHOBE\n",
350 "gUPDNPshMyoqkTjUkShl0J5dykTymUY03H8MDjTcR+EQBscrlUw2laukCEYuXSgCB1NiAC4oNtAE\n",
351 "uDjIwA2caDRyitnEQUXzvYoLKuOQ/Ur/eQQHy5mJs9U6E4d4vJSMmqVeIQYG0mlhyrAUIlKVnqea\n",
352 "rVUkDqlCKg2b1NXXJUuuK0+ZlJXzfVyElYoYTjeBQ+koHNLQknCWOGTxTixcgkVR4TY6LOa5T82Q\n",
353 "PQgjBH8ZiWRdHFJhmORmuJgtZdV6Tr43nM92ddkR5lF5w+gyzQGIgfKUHRyyJuLmcjaCqnZ4IGur\n",
354 "hChVIf+yXCqS3O/AYJRKtDDpfBU45Cs5GRsFFRvojSUbiEOl4vBB4QAmyCRb5Rmqdp/igky85KOs\n",
355 "SsSd6QAH594MHBQrKql4vAwcyn1CDA5mXBwgIjU1gGy9KvdbU0X41Xq92d+UJdc8gkOhvyhxAKxG\n",
356 "ppmpZJDmNTIF2/m0J40AxsgaptnIFrLZuFGCKVKdDw4qHORFsJA3FA7q0wpM2SiWjKYxA4c+I59t\n",
357 "Nu0ocEBto2mag4gnVVTCN6INJEoODlHED7Yx2MGhKnGg4TaOLhIHqEEN7qtQyWfKUASJQ0V6AckG\n",
358 "muJq1eUDAmhwotl8Hw79igsq85P9Sv+ZdaZjGC4Ozlars2RIwwenUk4Bh34hhoYyGWHJ9KBYrdak\n",
359 "56nlGgqHdDGdgU3q7u+WJd9dYICtKvcXZdovcejOVBFdJLsyxZjzMVsGjtPIGZbVxUXzuFGGRVHh\n",
360 "NjqsFPi9QA5zCRULiKjSkUjOcBBMGxDBbqMCY6HW1Qp9RiHX3Q0c4EQLptm0rCHIjPKUcnO+Czjk\n",
361 "LMTNlVy0mOu2jaGcrXKcdJX8y3HJ7hgcyuV6HRUUDtW8jI1CZAOdQk2xgaZY4ZCWOOASTJBJtsoz\n",
362 "VFbVr7ggAyC1QSD9Z86ZDhTWmckMHBQrqulEopKyrQpwmDUrCxxkelCCH5IDqOe7agqHUjoDm9Q9\n",
363 "0MFBmi2W4oBaDAesRrYnW81Wyslm9mgc8sChmQdecaMCSVbh9qxZEocIjH0+38EhPwOHqtGD+pW8\n",
364 "E833G4V8d3fMjjOYMc1uy5oFMVBRicShiYQ1b+XzsWo+Wsx3x4xZ+ZjKcdI1GebTcB+DQ6VSr6NC\n",
365 "sY4wolgryNgopNhAbyzZQFNcqzl8QMGlwiHvFFV7QHFB4SDvq0T8CA7OTJwtb+Kg3ufSUDVtW9UB\n",
366 "IYaHs1kHB0THDRkBNPLNusQhg8ABNqlnsEeWQk+RDSrQBstyRBKH3mwNM0l1Z0suDlloicShm5sX\n",
367 "iRk4oMNqsYNDqWggM8LAXBwyRrVq9BpVhQNHM2AU8z09wAHBDHDosaxhxJPKU8rP7rqP4GCX8j0x\n",
368 "Y9jBAXGWdJvvx8GsVBoNVCg2EEYQhyoUQeJQk95YsoGmuF53+YAAGpzo6SkqZhMohcOg4oJMvJRs\n",
369 "yjgm70zHwQGvyQVZtfetWFHPODgMCjEykgMOMj2AqnbJAXQVmg35HQj7H2g2e4d6ZSn2FimTsnJp\n",
370 "CDlOUeqomevL1XNV4JArxdWX68DBzJgFEzgUSgXkKlVYFBVuj4woHGDsCwXgYEocCurTFEzZrNbM\n",
371 "PtSvFpxoftAsFnp7FQ4l0+y1rBGIgYqlFA5mMlmwCoV4rWCXCr0xc6QQUzlOpiHDfDwuyFG5n2oa\n",
372 "ZrXa1YUKpS6EEaV6KUeGhsgGOoWurg4OjYbLB4kDmcBZq5GprGpIcUHh4OSBPHGmY5oRp/4MHBQr\n",
373 "GsChlrGt2pAQs2fnciIi0wOISJeMxLoK3QqHLAK4we7uvll9shT7SmxQVi7PqhzBoT/XyNWq6Z5c\n",
374 "Oe58ZJuD4wQOkUgPN5GSZq2DAzqslSKRqMKhXDIRtxAH58PRrAlT0I/6NXdGQ2ap0NcXjyUQVJYs\n",
375 "qy8SmQ2ZUZ5SfqzSY8JDYrLxesEuF/ri5uxCXCWm2YZ0m3Sg5tGFoU+hmCt3IYwoN8oyRg2RDXQK\n",
376 "XYoNNMUKh6wMZHEJJpQUs4mDyqpmKS7IxEttmKkFEWc6MJzOTJxPQGbgkE2l6plYpD5LiNHRvItD\n",
377 "tdFoygigWezpUjhU4Vd7evqH+2Up9Zcpkwq04Sqaljpq5gfyjTxw6M1XEjNxKAKHXm4iAQdYFJX2\n",
378 "jI7m6mXgAKdbLIYqZUS2WdsuHsEBpmDArBdrKrMtl2eZ5WJ/P3BAMFO2rP5IZBTxpIql5McqvcCh\n",
379 "GCkWE/ViDPFD3BwtxlWume2S6RaXTo+GwWLogwrlZq4AMMr5o3BoKjbQFHd1uXxAIgNO9PfLxQ6V\n",
380 "7ykchhUXVAYu+5VxTPEIDs5M5MK4+gZBsaKLOGSBw7AQc+bk8yIi0zSoarccQHextylxyCGQhk0a\n",
381 "GBmQpTQgcZCVKyNH4dCVrzcyfUdwyENLJA59Cod6Bwd0eAQHnTjkcjNwyLk41F0choHDwEA8lmRQ\n",
382 "KXGYAzFQEYvEoc+EhyQODeIwEDfnODjkc00ZvtCBvg+H7u5iKV/pRjhX6arIGFWPSF2gN5ZsoClu\n",
383 "Nl0+IJEBJwYGZuCgstsRxQWZAL8Ph9zRONCZH8GBS3QN4NAYEWLu3AJwkGlaDX5IRmI9pd5u+cFZ\n",
384 "DoH0LPQ+W+FQHqgw4ZSVq7ORa5aljpqFwUITUV6mv1BNyC0nB4cScOgvAa+U2YBlV+nn3Ln5RgU4\n",
385 "wOmWSnq1YjaIQ+kIDo26OYj6jZJaZ66MmJXSwEAinkRQiRcHIpG5kBkV08rPMfqBQymCPLKrFKuW\n",
386 "BhLm3FJC5fy5bnKnxCXsY3BgCIoKlR6Ec5VmpVBvEAfMqym9sWQDcejudvng4iAXnVTerbLb2YoL\n",
387 "MhCtyn5lHFPq4GA7M5mBg2JFN3DoysUiXbOFmDevUBDRY3HoUzjka/nCcF/f4OigLOXBGTiMKhwA\n",
388 "q1UcKjaLja5sf7GaVP9rJoSaVt4qWdGowsFqwLKrztFhoxKN2i4OFuIWDMyKq09E82CRNWTNwGG2\n",
389 "VSkNDiocqpHIYDQ6DzioWEp+NNRvwUNGkUd2leKI4xLWPAcHxLsyfKEDtY4uXV29vaVyodqDcK7a\n",
390 "XZG5gh49Gge6RIVDXuKASzDhfTiMKi6oQHYGDs504MCcmTif4shvUBQO+UymKxePdo0KMTZWBA4y\n",
391 "XYaq9spIrLfc36NwQCA90t8/NGdIlspQlbZBVq7NqaNpqaNWcVaxu9jVlR0o1o7CoQwcBsrAK211\n",
392 "wbKr9HNsrNBVBQ4lprB6rWp1EYfyERy6GtYs1O9SKwzV6qhVLQ8NJeMpBJXAYSgaHYPMzMBhADiU\n",
393 "o8gjm+V4rTyUtMbKSZXz53vInTKXsD8AB1So9SKcq3VXIUXEAfOic+5VbKBL7Olx+YBEBpwYGpKL\n",
394 "fyrvVqsMcxQX1EqI7FctTB3BwZnJDBwUK3qAQzMfjzbnCDF/frEoojJNa/T09MlIrK8y0Ku+RW0U\n",
395 "irBJs+bOkqU6q0aZlJXrc5FrVqVsWKXhUk+p2cwOluouDkUEklYFOAxWgFfaasKyq/QTHXbVgAOc\n",
396 "bqWi12sW4sdYrOLiUACLrGGrC8ZCrTPX5li1yqxZyUQKQWUtEpkVjc6HzKhYSuIwCBwq0Uol2V2J\n",
397 "1yuzktb8SlLl/IVe8q+Cx5VjcGg2+/pQodaHcK7WU5Uxqk420Dn3KTbQFPf2OnxAwSWYIBedVN6t\n",
398 "stu5igsyAa7LfmUcU3GmAwfmzGQGDooVvYVMphs4dM8VYsGCUlHYLg79cgD9lUEXB8Q3g4PD84Zl\n",
399 "qQ7PwGHeDBxGJA65oVI9JT/+tywHB9seOhaHBQuKzZptxzo4NBFxxmfg0OyyRlC/g8Nc4DA8nEyk\n",
400 "GdxHo8O2vaCDg/yIbshCpGIzj6wkEMclrQXH4MBA5mgYIgxBK9Vivb9YLtZ7a6VuKIJuOzj0KzbQ\n",
401 "FLs4yEQGnBgefh8O8/5fcZAbFOrbKBeHbLanELe758m/w+R1jqL6q4C+j+BKk9c+HyyXWCPGhV9k\n",
402 "xRe0AW2+tkL7gvZnnoLne54XPf/b+xXv495ve3dXk9V8tVytV7urI9Xjq0uq36wlIL3dtVl1Tz1Q\n",
403 "j9bj9VQdcVJ9oD5R31C/oPnSvj0/t35/+P96Dh/mX0oUD2qztOO009By1vM8Wn6l03KiiryPk0bL\n",
404 "x31AyzG0nOu0vFG2LNCyJlt2yiH5dxQPNYV47xPvrXzvQ+8dL8S+h3lv34p9N+47Zd+Cfce9fuD1\n",
405 "1uv/+Po/vPbua2+/9q9CvPY7HK+/9qPX/ua1R177xk+Pq94sRMgv/9riGi3p6fec6PmYEJ6/8XwH\n",
406 "9DtuT57neXheEn+keKbUcdS9J3D8rUThSvG0+Kq4UOwUS8Vz4r+LvxQrxF+JdeJW0RIvijfEN8Q/\n",
407 "iX8QnxXXiBfE98TlYrv4mHhe3CE+JW4QU+IU7Uahi7AwhSUSIilSIi0KwLEkKuBxXfSLATEohsSw\n",
408 "mC3GxHyxQBwnThSniw+LM8Ry8RNxvThJnCZWiw3iYnG1+Ly4WWwV/038qdgm/lzcI+4TT4pvid3i\n",
409 "f4nvi5fFT8Ve8b/Fa+JnYqX4iFglJrQ/EVeJc8XfifXin8VZ4rtio/i4eEz8ibhTu0H8T/EVcb6Y\n",
410 "FD8S02KRuEt8U+wSa8WjYoe4UTwiHhY/EE+JgHhJ+EQIshbUvigMERMRERW2yIsMpC8n4qImekSX\n",
411 "aIo+0S3uFr1inhgVc8RccbwYEV8QS8RCSOqpYrFYJk6G1H5SXCIuFZeJL4vbxO3iS+LT4l7xkLhf\n",
412 "fE08IR4QF4jHxatij/ixeEW8Lv5e7NMMbYlmaks1S1umRbTlWlSb0GLaKZoNmY9rp2oJyGdK+4iW\n",
413 "1lZqGW2VltVO15Lah7WcdoaW187UCtpZWlE7Wytpq7Wydo5W0dZoVW2tVtfO1WpiE/Tmeq2hfUzr\n",
414 "0tZpTe3jWo+2QevW1mu92nmiLP5M69M+AQ3bqPVr52sXaIPahdqQdhH0YpNoQD+GtYu12dol2oh2\n",
415 "qTaqXabN0T6pzdUuF7PEd6CVW7QxbTM06NPa8dqV2gnaVdqJ2tXah7TPaCdp12gLtWu1ce06bZH2\n",
416 "WXGCtlj7nHay9nnxIfFzbZ52hbZA+5T4qDhHnCkuEn8rvi7+UdwitojN4lnx1+IZcZ74hDhb08Rf\n",
417 "aGEYhf3iLXFAHBS/FL8S/0e8LX4tfiN+K34h/lX8TnxGXCsC2ktSn/f9/1uWMQdIIWQwApnrhoQt\n",
418 "hHSNQ7JOhWytgVx9UkrWbZAtSta9kKqHIFcPQLL2QKooU+dB3qkN3xVnQ9q/AA34uPghZH+j5od0\n",
419 "94r3xKQW1ELQlbvEIU3TPOI/xGHoyw7x75Dex6EPV0FzhLhOC4h/gxbdKK6AhgWgH32Uhw5C3xb/\n",
420 "Q1ygecHxE8TnxJvii+ImicQnoGF/A/za0KkoNMuGPik9ylOHNB90idozT2wC+v8I/VT4rwX6Xxfn\n",
421 "tMTgqS191Zpdmvana5/WDt/cWlLapXvXf3yopQ1Wq0svXtLSNgy1PIMtrb821PIOVpe1vM1lZ6xp\n",
422 "rK3eXr19xcbbq8uqm87b2PI15S8eXHD72uFqS5y55mLQs9bUWuNrC53TC9auPX6o5WMzPtnM7WvR\n",
423 "wCVOA5fIBvD+e0Mt/+Cp1Za3e9Wa09e0blhSaI0vWVuo1apLW7tXrWntXlKorV071Ap0xojfz1+c\n",
424 "VaMNDrYC/UOtkGrhTLyP19fefru6atRau2+/vXA7ZuBcP62JY2+Mz7yBGS99WrthlXxyQ6NW4I1G\n",
425 "rVHDiNYuGWrpg6eeuWYphlRbOwSRakFk25rHM6C1vV7QKe/yRfOa2dDAlO/Dzon/LHUipjTnbMrz\n",
426 "sWVj8lY74A8OtISaT3tDSPt0+/owyAMkz5G8TnKYpBLWrmwvJFlPso1kJ8kPSN4miYa1q9rDJCtJ\n",
427 "riDZaeLdt0kqJqoMk6wn2UbyAMlzJD8gOUwSNdkKyUKSlSRXkLztVPk0q2BovLQjOBsnWUWyk+Rt\n",
428 "kuEIhxvBa4d5eQUu6RhT0LgToZET+BUifrgoTO1HIg5vG/f8DpZBQLvVf1+Gb3kFVnuWp9/7qP+l\n",
429 "wNbADwO/DWaDZwWvCV0e+qb+2/Bp4S+EHwq/ZAij23jUfNictiYin4rmo2P2JbGJ2ObY12J/EzuQ\n",
430 "/I9UOvX99O8ze3KX5LbmXshfXjilcGHh9sJkYbq4oXRLRVS+VvmbyhvVrdUdtQOIQOr1c+vXdd3e\n",
431 "9WhPqOfcnlbvpr5Ng/cOTg1tHTowy5z1w+EHh58f/tXIZSMPjbw02jV65ZzpudV5l8z79lh17KwF\n",
432 "Xz7u9uM3H986IXLCwyf8/sSNJ3lOGj3pEwu/sPDBhd9euH9cLJpYNL3oXxaHFy9Y8u2l6aVXLn13\n",
433 "2e7lkxNLVixbsXvFj05dctrVp019OPThlz5yw0cOrFy18oerxlatXrV71U9W/fr09OmDp0+ecd8Z\n",
434 "3z+zfOaSM58/69dnB86unv3s6jWrD63pXjO+dvTckXMnzr3w3C987NmPHVqXXHf1+lkbzt2w47w1\n",
435 "5x3aGN7YfUHgglUXvHHhZZs8myY23XjJpksevuS3lz592QuXhy5fdvm9l//HFR+/4r4r3tic3Lxg\n",
436 "c+tTOz5911Weq+KfyX7mK9f4ru2/9t5rv3Pdjs+e9Lmxz09d/+ANX/uTxTce/8W5N+Vv+sub/vam\n",
437 "vTcdutm+uf/m3bc8sXXktk/dduNtk7d/4kuXfelzX/7Uf3vov/3sT/N/etmffvtPX9n2uW3T2/Zv\n",
438 "e/eO+p32nVfe+fCdu+985c5Df9b1Zz/88xu+kv/K1r84/i+uu2vwbnH3GXdfdvef3f303b+455R7\n",
439 "7tpe3X7a9s9tv2P7S9v3bP/ZvcvuPePej997yb1X33vjV6/56k1fveOr9311x32R+/L3dd83et9J\n",
440 "951y30P3/eV9z973/P3x+8v3998/dv/i+z9y/7n3X3j/p+7/wv2333/X/Q/d/5f3P3v/8/f/8P7X\n",
441 "vrb7a9//2itfe+Nrv35g9IGTHjjlgdUPfOKByx+MPJh/sPvB0QdPevCUB1d/fcnXV339Y1/f9PUr\n",
442 "v37DQ2se2vjQ5oc+99DWb4x848RvTHzjrG9s+MZl3/jdw+Jh8+GtD08/vPfhAw//7hHxiPlI9pGu\n",
443 "R0YeOfGRiUfOemTDI5c9cs0jNz1yxyP3PbLj0Tseve/RHY9OPrr7sfHHTntszWMbH9v82Od29O6Y\n",
444 "u2N8x2k71uzYuGPzjjt23PH4xidGGLbLSFJ4/gGetwHbPiBGW4PDraHh1qDd6p5udQ/vSvvebQ3Z\n",
445 "rebeXUXfu+KvvFqXb+CvmloO1KdpvoGR2fPnzUn19MydPzY2/yTvvLndjXog2DM2Nmc0nUryLwIG\n",
446 "UplYLabheG3BPI8VTMfsZNg3VKkMBUaDp4yNLct1NwOB5w5t1P7hkLjq5JOvii3IWaVYNJOI6V2z\n",
447 "B+eEJhYtP7E6r1FLJOc+7bn4vbs99703iiELoaJ1z196P+3phucXWhBe6XXEDh9qX2Fo6yYXGisN\n",
448 "zxbajS2TO6PPRT3rpnZHp6P7ot51grZmHe3UOhqhdbQruETNkdlH2r240+5G2e6YbLe90NC2jFsP\n",
449 "GDuN54wfGK8bbxuBde0rSnxSkk9KO0vPlX5Qer30dimwbmT2B4zzetneQPsKC29xgKJ9mKdvcxgL\n",
450 "3bF0RoVGZs73nk47fyvbWdleFUPtK2KofQPIlIjZsWrMu2Vqd2w6ti/mxZ2aXavWvKhUY481Dc9q\n",
451 "07V9NS9ewS3RXp9kX8Vj+/pop69/lH012wvz6Atk3dQD+Z355/Jo4Yq8bKGCFg73qha8sLDCczzs\n",
452 "bhgxxID22XZzwDvQHhnAyzZIa8DeJXzvtu9o4qWRJu+CtJr2roD33ZawW8Y0Llrl6VZ5uL2qrK3b\n",
453 "FfO+264ZzVj8uPbmQfTXEkvXtHLDhV0586S18qIfF/2Bk9YiAHm3beT6UbVlDO8Ke95t5exdaY3v\n",
454 "h/n+wRoHqU3u8D7t9axrT3jR/R+8GIgewtm9CQjPNcmtSTw6QK5cTHIvyYEUL0nGiqh5C2Y8eWH1\n",
455 "6ipqrq7ixltVPHqzAbKH5EddvASZWt11YdfVXQBidc+FPVf3gGcv95JnZ7Hrb7HrpTx7lGfvkAR4\n",
456 "GeZw9kdxuYm93wMyeW3yNg7sIG9sSrlj2s+ON5G83HD6bP+Y5BV0M3/O6EkeqmZjnjqb5Wk0euaM\n",
457 "lj1U0VQamhrBnR239ywZLZ17zp/fmZ/Tl9crJ865feKfBs8Y71504qlnx8YuPPuVxXZttLFsyYlW\n",
458 "ebhu9PaWFsf7l4wef2bEE1j3kdjiRSMy0x05/C+exzx7RI/nlnY87B1oxe2WmG6J4fa4wHSmhbau\n",
459 "FbZ3lQDnql6qXh8Frw9KurBvZR+mdn2fi24UgEZddP248APddiLqJ7KJ4VbU3pXV3m357V11gNvj\n",
460 "j/J+z3B7ugdNbuiRILff1HBxWxBkbYhnJG9S59eS3Ebysk2wqD5XkXyX5FaSt0im43wAMnlbYnsC\n",
461 "A3wGAtJ+ieQXJE9SXp5JvkhYniQsv+xgs5ZkO8mLJM+S/ILkSfkgDfIMyRMkvyJJ58CjN/KUMJK7\n",
462 "SPaQvAMyGcin8zBpy+XzAm48WpgqoNv9Bb5awKvLebacZ29SOMcqyyp4flfVlZE0xXQ5zw5SPFZ0\n",
463 "4XIHdXAtyXaSHLVxBcmzvHy8G+082/1SN9r5aTdvkLu/6qH4HiRvD5CFK2i+9pCPL4Nnk1fHbolx\n",
464 "XOTfleTfGyQvk3yPPJN69aLLp8lnUi+mUH1H+iiuHCS5hnM9QHIKiZzpAVoaOQmpcPs5kwuaZEdz\n",
465 "qol2pjjMPSQHMMxmxNuoz4LYn+SBV8oEZ+EyAtEve6gN8z2PxectWTm48tbzFyw4/9aVi28aXmh0\n",
466 "z15QXHLZqb29p162pDh/3nByc2GkkVxw/tbTT996/oK5Jw7H6nl79KwrPvShK84aDWf7KlLue6Tc\n",
467 "r/B+rj3YBVsX7BqkPAYhj5C+VmRvexvt+esgraDdSu5t/5oMKEeCqDZufLX8ZPmvy39X/mnZD7GE\n",
468 "xWv3gbS67F3zYRHhkRdPtxYPT44vXrUYIjC9GM/KdmvF3vaqU6hFp9LjnbryVCrQqa4C9UFn+lwF\n",
469 "WoGLFVCglrm3PQLMWrG9rRU0se2hvhUcKRx/n71rFBq1wt51IjRq0Yo+3l803N6wiIqwSGnU3Vnq\n",
470 "Rw4dXly6toQOl9Op7KhTikjWkPPLwfnJH/e/1Y/nPxogSiS3knyP5J8GiTDI1L1DTww9OwST+HdD\n",
471 "FCySF2bh5SdmPTsLL/9yFqVkmD2QvECylmQ7yTMk15H8gmT/XLw4f+7yuXD2n5l769y756Ldb82j\n",
472 "JsxbNg+tPTqPtUhuJfkxydhxHC/JrSS3HM8qJMtJ7ia5ZyGaWLvw4oU0vQupwCTf5t0Xx18dp2qQ\n",
473 "Q78iufpkvk9yN8ktSyinJHuWcvJLqTiPgIWT382+nPWsm7wlexd+2reAoe0pcvXu3GM5j6P73yO5\n",
474 "Dm65fTEjjM+SHMPuZ0jOIc9vo2aeQsbv6d9Pxr9BTr9MckuH8W+S8XtIXiCrd5DVz856iaz+RYfV\n",
475 "B0iu7XD5RZJzhwnK8LPDqLlgLplCcoBkBdl+7dzbwPb2VrL0aZIVJK+SvLWAsBy3/DiPw+M3XfZO\n",
476 "3nr83cfj7pvk510kU2TqOQsvIqsf442Xxzl0krfI3mvI1AMk20m2krMHlxCIpa8u9azzZ5zgEy6t\n",
477 "3jM/PWd0TDo8hqXzu3v+uB3I0Ez0aJd6QjGjPJyq9SXnDtn13nSvL5yMRtLh+Nyh/pP/MxtxgrQj\n",
478 "hnGi5vX1dGXqqXC2K57M+SKWHvDHlgdixT9uP/ppXzQZjq8G+RbiJlPktMF2IgdLspOicT0I4xhG\n",
479 "TbthQ1sJGSu119MiPkAiaPZ3F1zlj0DfI67yZ3GRdWKjVsTeZWjvUpWfZqxxHMnjJK/KIIihx708\n",
480 "e9pHFEEmt/se9wGPp+k8V4R4I/R4CDde5Q0ZNT2l42yCZAfJcSTbSV4l0XVWoXtYTZcg/cKt9Aa3\n",
481 "0gSuliEMyRRN/kSaKiKjomUkMipaJsfCtp4g+WuSFWzwGZJl6U6YMyO4YVTztS+f/pmV3d0rP3P6\n",
482 "lyd+ufjmSxcvvvTmxb9cPPv0i+bPv+j02YsH1968Zu1Nawdl7MKYtQHeG+LClne4bYMT5HfLa7e0\n",
483 "va3AdCswzNg0NN3S7FZ4b3snvN7k9dY2y+PwXAYpLs89uPC4PEeQEoBJ1f0emlQdYSkRmF9L1WI4\n",
484 "+N8O7bOHPqQ9dehO7ZxDjy9e7PnO4t8sRhwux8TcQVgyDl8kdiEOb3DhZZ2YfNs8bHqcJAbpzBZ5\n",
485 "WyY2bhx/7Psfle/Pbm8D36aG7YX2StuLBMl+zvYwiKcf57TaCxl3ro+iybejsrVOWxd32too21o3\n",
486 "rg+bC82V5nrTt2Vc32Y+YO40nzN966ZeNzk+mOAoh7YBo5p6Pft29nCWt7JIlvTh7MLsyuz6rG/L\n",
487 "5APZnbSDG+hdttH/PVc+ut8jc7he9jugHOqGKMVFZk0yf5JjXs/RHybZGXV4Ad2yHN2yRU27vV2o\n",
488 "UbdoTK8HadUc3YICtQqdPMSaJo3sxeNWXNLkdHs9g+wHSEQDyZtEOw200y70VVxUXejTUt3aVrpK\n",
489 "6K3hXTYykth0y2Jb1MIc5GzyOO8Kr8dRvJ+SfJNkAcX+HpJnSHI+1FwQmoDuTd4T2kEVfIYqmDta\n",
490 "BaXi/ZTkmyRPZ6hkWSYTtCTdjDHP4dmt9C6r6VP2k3Qjf23fyrPVZbZHEHY3yN3JjjLOl8kKx3IX\n",
491 "yQL2vp3kFJInSBawz1NIniV5hr2fxd5XEFrZ8RSbXk7yUfQ0Q3OpCMxTYh+owZrn0KGJFSs+QI9/\n",
492 "MzamzXmfLhvAWhdntzTosuboMjTXu5eYQp2h18G97ZWGazK9gM3rYihwIRgvee1dPuAX9AoVz+0K\n",
493 "UXXnNDqKO6E9eeh+7ZRDU1JnnRzovyMWbHpK7WQJOVDJ3hWCrR5OgguHafJaIK2kvSuGESXtVhPZ\n",
494 "7nB7hE681eOOpo4B1I814G1Rz3IYYrhVt3d5IV5Ze5eF4SXU/cRwex+8w664MvAvIt2a/Kp4UjBE\n",
495 "wXn72yQXMW5fQ3INyNRt2nbtcQ06+SJv/YHkpyTfJnncA/J3JHf5Qd4hCfghhvP9y/0Qw7HAsgAa\n",
496 "fyfA+wHMbxnJVJgeP7w8TC8e5stcOtlD8g5JwEALy4zVhgcNGcsNtkDLtZqG4i2KZR/XGQ7Qr/XR\n",
497 "r/VVQNaSrGHM38c8Zi2JTLffYArwsky3mQfc1XyUecDzzF+ealKA7+a0d5C8Kty57yB5gQy4WLtW\n",
498 "u40MeIa3fiIfcsYvgkwe51+BebaXcRbzScY6U1lOspajPSjTFI52dSfXeqOThf+MA/kuyaMke9xx\n",
499 "ad3dR2KQsfnzKPiBwMxsxXNp18bFbpgx/4Lex39z4rZFbq5y9mdHPIu7B91AopD5P4sPPdJounnK\n",
500 "8IirB5+SPu3mlgE9AOPbq0hGQHaFIX+e6ZYhFWE98xTvNLKTXQHfu5PCsi1YpG10ctPWPji59iqL\n",
501 "dtxyJVSDUGquhIZxEaaEejSussD9Udd808j2W8HplsfepVMmE3NitdicGLQn1tgwod04MXHoCxOe\n",
502 "7xz6e23OeydqKw/tUmMWOzBmrzgNfUizvI9hyCrfBoQhk9f7twGRqYp/2L/QD+e12z9NhITftcVH\n",
503 "6bEcJMYlVXbOjgl0Rp+yHMwJSJ+SdvyqCZ8ya/IB/86ZjcPF+g4z9llIc7feRxfrnMm1vcNv4+3c\n",
504 "jHY+KtuZO3l9cFsQrz0HiziuV0LDoYWhlSHfFngqatBOkvUkb3NpApzn0iPGdfg3aCUjfWza8bGm\n",
505 "XOO7Hh2ORx/w7fQ95/uB73UfhxVcN25EfRXfsG+hb6XPv6W90sb4rk/Lmumd6efSP0i/nn47fTiN\n",
506 "mno0XUkPpxemfVvc2ID/l2r/c8bYr5d9DbtjFxhVezMImBA4TC1fSC1fTwXf6Zw5vlUTkcP/on0Z\n",
507 "rE2Iv2mFhuW8J18PvQ0X1UrslZY3BD/IJT/av20pV4ak2LhY2biwpZWzw8rKyQWj9g1cNbKlvaNV\n",
508 "6wXS7YvJvetINnEsB0CmQoFsoDfg3dK+hSHMLQwH7kGYOfVM/MX4q3Eo+BNxWoML+daFfGsr693m\n",
509 "1ms/DTI/nZb+CEIqk4junnPCYyM9swvhicTwacet+IR559DcyuyFNe2N9w51nfqh3lNXuHp2HeYf\n",
510 "0f5HyxymOp1MZP+K5DDJn5NsJhkHS6lnCDHPhDud/Ib3r7gO+T261rWMvu/xUmhS3qZ3nnepF7HR\n",
511 "P3l/zhpfZI1fkwhUa/n2Tp7v+zQ1IuVr+qCqf6BkjlFGl5J4QcajN/ju8D3oa/l2+6Z9+yAyLVPi\n",
512 "wDWIwN72z8i28wOfDnwxAPb8L/LkX0m8AHnqjsCDgRbvT/OW3whw9XQZjX+vf4EfpvtW/93UvEfJ\n",
513 "z2+B0JBEptsVimHL/sBM5CjdNHBhBJyLIC6CEnyv4bg4fW97KVMHv9DZdQ9xf4qdcRDtFEkiRNXR\n",
514 "2j+hwf4Vyd+TfIdc+g758Sbrf48kxPovMkTZG2Lw/LLnTQ9G/12/W4vpTGLOHG2OpjW0RiNGe6Hp\n",
515 "2ocvOvRV7dpLDj1saBMT2p3anEPPHfq89slDf64+4pHYa7/FhV8cd2ze4NlL4xcc/oD8QHKCQaLo\n",
516 "pALo7pRDl08w+pc65bRrib9GE60omqbowD770LqYbvnYQdtGxNuK2k6CAlz1vaTGtIDxg4LJ3iz0\n",
517 "ZpnHsnobfV1FY5QP1zZurA9fEb4+vC38QNgPSQurtVrY7bbQiMDU82KP2C+862Dad3lwO6RrBMYr\n",
518 "QjI2UpGSIa8mbzHugl+HxZ+fCjJOmhecNx8zfOUVzvGMMya0S55d9uzPFu9ftmyZdo/LR2+eOuTJ\n",
519 "t4MhROcrGdeupBkSoaDqAdFbex/BvYFkFUkLRHJE29teyAmtJ5G+/FUQGB6ueT3H+ELu+2xzcySp\n",
520 "B5G97T00AFMkZ5KMkEQ7aQTzHynN7etJHiCZJhn/YAkP4SIk5ThCPrQ/RQv2TyRnMxobE8sQjU2e\n",
521 "LM4UUNm/4v19JLtp4yLINKc5YN902x+K8PXvQzInv+y/j4r2WUrpkyR7qZG67GDyy/p9Olr8vr5X\n",
522 "Zx0G3U/qat7GdHuNrZbtnmInF5Mp2zWuuWovalzN4o0nSG5Ci5M/CrwBOz95QeAq/Ew9EvhW4LvU\n",
523 "/7uCNEhTweeDe4L7gz5EkLRjj5Fsoj7tcNOAcf2Z0IuhV0MHQ6j0uM5lGf1VjGrqEv06/Xbd62Tu\n",
524 "vyR5hGy+kOQukudJ9pOcE6GRfpDjvZPkRyRTJPtBmglGDw1qKBVU+x9vXz7hOSy64c4mLr/JM/7e\n",
525 "iZ6N790nj+84dvkJxj9aue3VIVNVWthVTLlu8N5BqzrtyhAjfQ8kwj8NRR2PrfSv91/hZ7DBmOA5\n",
526 "f2hLS0ccjwoGIqbh8cSIMW6sMjYYm40bjDuMB42WoW9hKr6F30JsmVxlbWDMdD1czBTjp19bmH6r\n",
527 "EzxJ2/e+3Q3hp+2bukBcJW6GnrX/gBmPW7rIiT5xnFgh1orAlvZXeNN4EO3sFtNin/BLw+uZRljN\n",
528 "vZGpHwReD7wN3MatSwLXBW4P3Bt4IvBsILCu/W8BtuYPpALNwLzA0sDZgcCWlp8rGiOzm3MYlimm\n",
529 "ejZ4Js49dC7IZZ41YOjH33tI2jonF3+C+4KiqvYFNQsxQ7l9PfRpknk/pjxuyg1B7uwc7pMhgoc5\n",
530 "kTeOnCgherTftMowSnvbgjtCmwnsuJDr2bvCMuvelUSyNN4LHrb6dnNPaCGb2tfHvc0+u6/a53UC\n",
531 "vQbY1nB5KDcD6Uwa9i6/Jjf9oipemKBHANnSPo5n20kOMrbXPTkPlHABJeAAyQqS7Z21MGbm7f+Q\n",
532 "Z3SoaUY+1IUpqsE7QeCTDjIVCi5nvDRGLXiUZD+jn0AoHeJuDW88RbKc1mwZjc+jJPtJ0hSXp3i2\n",
533 "nDIzZi2jzNxFmdlj7bfegcxMBqw0A/F3qBtpbgzn6F8XcBFtBcl2bvq+GjsY+0MMtfVYLobaE4xn\n",
534 "QDBnnh0kyfFyNdfYbiVZzcz8VpK1zFy2cpl5LclWpi9rJeHyyGrmK7eSrGaGems30SVPJxd4J6BB\n",
535 "kwuCE5j/5Hxzuckfa7nFn9jyGH/iy+OedZpcg52x3CpDKzfPKXs832GC4yY6/P0IMxw30+Gv9gkm\n",
536 "OW6yw18mOW6yg1+1xrMQPuRG+hDR0FbBMLcKeyd3Fp7jNtnbmKVc14nYuxJQ4+g07W1yr9r83paU\n",
537 "eyLt62MyNW/Vp5GBj+sLmyub65tXNGHPtjVd3a1B1Gqu3KVwkaLc1eRGJP1yCiLMhdbptl1L0W/Z\n",
538 "w7tiShb3UJqWM+y7yPsZMm++bznzi7tl7Ea7KDPNu0lkfvkYV03WSMKlmR1yC4BLJ0+XicM1bO8V\n",
539 "kt+ThCixUoov7qwfbSc5hWQZ25+vu+0vZfty/+6AlAJ28jjJQRK5JrTf7am9AkRzMPTNmZNwli5d\n",
540 "EHHqCR239OrVs8O5gaUbFi2f0PKH9mujhxZd+ufr+k7+5JeWa9869BPPjc0Vn1yeOmHhwtkVbeXi\n",
541 "Q/+6eMmmLxy39uY1A1zrlDZC5iN1lZNpfcyl2pt7wa71vVf00rb0chdZ7p7v5P7xepqJt3sP89l6\n",
542 "3ljofILwAe19VLY33r6C5mQVv0XYPICW7YHqgGfL1O6B6YF9A9Dp8UF+kaE2pllpIfdN3h5Ql0e3\n",
543 "fXGn7Y2y7S6Ob93keO+qXuggx90e5+bI+NxVc3nj+D86tuvl+wva4+hx8sGB1gCcphjg0JDOTA/I\n",
544 "+TpDwHwHDg941HDk6GQS5u3YWENkxBz/1nahjzGUnGwfQsQ+Z6GpNbq3PTLKmG+U4yMRvNwsz5qj\n",
545 "jCleEj/hmtFlNM7XkjxDC92n1rEMWaf9Y4rPfpKrQPi9Rtfe1qjdmrO3bXbNYY2rXDs3+V3zZXqG\n",
546 "T/DGPm5dby7cQJ1s0fKMcIVnFQgXXmn7M+r1VyiVnyWRS5j7SbLq0XXcQZvKPs8l43+mtDbU/a1c\n",
547 "DjpAspGkW430Rdqtq0hmqxuXzGZ7s+lQ5tnzqvPA44XcJmzN281twn3zXE2fBeWe5Wr6KC5Gj13j\n",
548 "lRdduOjixSy1KFeVvgeZDL9JmHxavEBmXkI+XkPyBokR9XIoL5OBt5BcSfIzElM9+h65tdV0lfRq\n",
549 "ko0kGdlu+1Uy5DqSZ47wZxaXmSefyn6PrPm5ZE11Fmt/iQw5SHKBZI26+8IR1sg3FWt+PlsFjQs4\n",
550 "0BUMW7eLxzmHAwwVT2EA2a8dr0Gk5zGpkkuDexioOquCQX8G+WH7akapexhYzg8s5wLCvDBqd4NM\n",
551 "PhZ+iouDTS5FPcU5L+XE/oJkzFkJXDf5qDlFqemmk1xAMs864iSXcTHqMSbwb5EEeXm86xknD8R+\n",
552 "z08Qsvw0SnrJV0mO4yWz/PbvSbJxrrzHV8Q9joc8TjrMBMhWesjHSf5A0p/m0mPGtcdvkfyeJMSV\n",
553 "7WVcUv8FV7abXEOXS+pyIb3JhfRz6hjPssbqBnr5PVnfz88u3uFKZaCZboJPY/zcYjlJoBvkGcLx\n",
554 "JMkabulme/iBEs/WUOG3khwg6ad1WsO93P5BJv0jnPwIxYkYZudws2DOxByuDMzBDR032v1zaNxu\n",
555 "Jq5yUXSC5DgivECbYEbwOME9qP2B57rGJvwTzD10Ap1n8r8gMEEsZ8I4RQR7ieXZBE8GORK1+YTx\n",
556 "bvMxwng2YVpKBB+1pojgft4I8IaKGdoX8UaaGP2YaP07yV8Ql38jSREtFU+0byMoa4mHnwA8SnPw\n",
557 "VvbfKfMSjK3k/lb6rbVlcr++uo5H87lX/pbcMCcOEoztIJOhZpY4/IFBzg4yPtTB4fdk/FqSHHE4\n",
558 "p/Mdw1skq8n9/SS3cjt9WQeCU0Amb579F7M9R5Z50/yjMs7XWD3znQ+v6t093Jrudpd852c867o+\n",
559 "fjxjoEat0TkbnTXKSGjpNcOnNU9zzj8zclrTc3q1wWDouE19Tefsov6x2Td+mFHRQPfp9TOc8/6e\n",
560 "0+sdv/PRjt/5R+l3CuOGvbS6dGTp+NJVS/0QkPX8WOHw0iN7Z4z7M3JfOqPV2rEMPIudgcXO2PIr\n",
561 "UTHdXsjAKaZ2pZ/jhwwLcyv5IQN3rj8gTZYbZkx5UpE0Q6TUcPt17gHfAMIlkRnb1Ecim16SFzuh\n",
562 "+SWd3bJNDG96GaRfy7OD7m6Zyk97GXkfZFB+QP8909GQntV7dVj9axkMvUhyK1P6W+T6YDfb/rFX\n",
563 "GlqcXc3GLiK5lo31sbFLeHYN3+vTIZU/0X/B3LvAxapbbK4izdyM5rewXE7aceXIyb3xeO/JI1dO\n",
564 "/MNln//8ZbdMaF9K1obyuaF6YvHH169ff+gp8noEznwAfjwl+rTX2nYAvJYrr6uYfxzmOIdp5xIB\n",
565 "W8aWdiu1txUADghtbXtX1fvuZGtgNwMEMeAuiR+VbbpL4rsKYHOCy/+7morTa+UaJKe6lROUn8xt\n",
566 "5SzXkqymet5Kspq5yEEujDxPHf2Wq57tR3nWzTO5v7+C5FF+ITeWXUbl3E+bmabKnuMYTmQ7OWY7\n",
567 "uf25d3LMdnLpnGfL5PLcOfhpp/Pg7qvFg0W8+2Pq9Aska2hlV/Bse4nWqvQHfoek4+7kRHlNGa8f\n",
568 "V15Rhh96tXwQP+013DiaqPMl2uKD9T/QGuTkjY4NeLVxEBZ6Um/kGug4RxudphVYRt2/q4dj7Nnf\n",
569 "804Px9iT7kGdc2gQljHI20+SZii6vPcchH6i/T3yRXqa/UypfkzyFY74RyRvkjwPUqvNyILk95hz\n",
570 "NCdHmufkTN6BQ5d++IsbxsY2fPHDp+F35Tl73juze2LT4kWbJrrxu2gxfsfOu3nlypvPG+Pvhu2z\n",
571 "PFrfCZeeMXv2GZee4Py6Ony81OG8diG0kf/zii27LLWWGJHrwc9RzihsuxKQpoDdyk63ssPtP9C+\n",
572 "hrLZrGdLK7e3naeJ/SZ1fGVuPXRc/Wxpv0s4TT48nqQPREpl1m5l9rZvgLkej41nVmU2ZDZnbsjc\n",
573 "kXkw08qEtrRX8mvaneTQwiK/qChuK7pfVMgdAVdu5Rqm2h6wnBViWxoJrhnkudUud9Wzclc9T9U9\n",
574 "wG2ji0PXcqf8dgpznhoql5+66WbGKKkX8MPaq5O38AvO5SkqPHdQLDW83ZnpzL5MAAbAzZZF+0DI\n",
575 "tQWyzUtJDrDNiwj6VjQ31Z86PnVKyrtlhiHgwor6LD7R8DZ23ODaghsmfnLZ59et+f6av73miDV4\n",
576 "7wue73x8/SkXhA61NLm/MHr4X7T/gE0Y8TzQjvR6B1q9dmtkb3snfc1hkitIXifZNkIL6n8XVXYF\n",
577 "YYz5HTnhTe9t/wAz25XxS+NawaOVDPmvINk26lrpIXB5yGV5AhcJyfKhhMPyIbX0G1Y3wsPtTGKI\n",
578 "Z5lhfpNEGMJ2q7F33NjZeK7xg8brjbcbfhlMbu0kE9vlAtaT4q/F34mfil8K/7r2e7y/yV2elOuS\n",
579 "k89qLzEKeZWB5TJ9NS2sTF5Xd9ZQHqExesPmd9j21bbH+QZ1D2G4h87k8RTXJJ9NvZT6SeoXKd+6\n",
580 "qQuzV2dvyXJp7NEs04c92f3Zd7KA10eBZYY9uaA2UfNwJbP2Yu3V2sGab93kpu5r+P3rq4wHXqE5\n",
581 "+AmTqq39FK7+a/mp3cF+eiKSixkWHJRf3vGzuX8HmXpk5Fsj3x1BavnmCOXndwy3psTzDKi5pKk4\n",
582 "w53pqae072k/5lb0L8mFPXKvQ3dnew7JDhnxcsqb7Gsw5XFjR+rp1AupV1IHUn7nc+Pf0cpenSWT\n",
583 "j0wTDy+Sn26SBHNunLqgRhY9XXuh9krtACbbXsE1n2s41YtJftKZ9B5O+mXO8UKSt+QZJ/pjd6Lt\n",
584 "x0a4q+2uErjxjbulNndWwI1ytJ3D5xbHBvJjq9avGus7+cz+RVf1LcqcsaAwNlCszFm0dNGcSs+i\n",
585 "MwZO/ES/Z+XSaGV2bWRevTB0yvjIh+cWZy8Y7hmO1UYqzdm1dLo4sGj2nNNGs90jMq+WeiLz6iEZ\n",
586 "35zz/zH2JvBtXdeZ+FuwcwMJYuUCkCAAghQJkCABQqJIiBJJUCtta7cZsrUtWf05lZjEizLJSP80\n",
587 "sSVPMtK0iSylnUj/NNqcTgU+w9DSzkitLWpJfyMktTYbrdjakiU5E6mNrcWVybnfeXggKSnTOtHB\n",
588 "e49vue++e88963e4nzD5poqUW6ZCQzC+BdKJQT8ItZcRknLI3yIEGX/Ucs+8rVUJqvqEQNEisqvs\n",
589 "HL7DIEgnmMju7O6wtBlbRr2y1KrYlFE9EkWikhVDLeNNVYwVtFaZ3fzc+P8Rqv+P8J2urodlrAru\n",
590 "TqKC8We2oiH1Bvy5Asu81InP62RMSglQKkpLuxEPvQnkOIK+O51LnMLjJK5ytlOOuVxWDs9Coiyg\n",
591 "WMYoiDBQBrcVm9lFheX4c1FA2sZW+JF8WTS4kbUnDUvrFAkr+YLuVXBW4odyPJ8pO8A46RrOfznn\n",
592 "kST56YUc47wJMlOnyAl03VbbQ1F85skoIDMTnso7mquqmjvKvxGP75mxMOJyRRbO2BO/pbE319c3\n",
593 "2TX/+GfWQG8w2Bu0/g/2LZdO/EZYzfqygh9E3MMSJe5hJB8GfGOiPEPpLtK57LIzLN3CFq1Cg9jF\n",
594 "UjRSoXqQ3FC5GaLEbuchxNJ3UpoLyDmQfkgWLqfy7fNZF+c/bNQnW2A+eyTWpeQ+IQWvY0QxQqf2\n",
595 "iSlxVGRSRUTsnbSmpg5qj2rPwMRMxuSDuqPo6R3sgySvFd1BNpOmyFLkLWIy7PIiJne8ZtwB/ncV\n",
596 "rG8HFGBLsRd2YAtWuFomqUu7sIDdALFjdwvYwC6s63abn63ryRv2+2wpT+ntdrvfzm67yg5N0Qs/\n",
597 "GMnGtGBSSoQH139izX5qXrHlwmNeqWIfUMU2hdXmmc8v6X9upjleWuX3ewsLgBpSGud1M55dGoks\n",
598 "fXYG/9fjC0N9zRVGtdpY0dwX4pOYv/TdaP42ZeMykHdUySVvVU5AlOuETjcItfpQdkvOsXr4OjkX\n",
599 "rCF5qPI4LluCKzZU5xKVboEcAukEuxusUnK/5Pusy91Hzv2aGSvaXYlbnau8UomWaJVbohFL6rBV\n",
600 "R2EXwUPB48FzwSvBW8GJoPbxbduUfSfpkCv7bGpF8lbVRJVAB8CQ+IkvGT9YQ/zo7tsoIl8vcWoV\n",
601 "pqaK3KAxWJET4gk4scgbGoTIk4sPGBFExJ2CdXVCcSgCWQL5bhvIOQh5EA+CmIUxzEcXuFkRyDaw\n",
602 "tD0gG+DEG9Pf1isshXzHyhAnXkfigQr+2eRT3LNY1JbBsdML8jJWtu9ivftj7qccllXFaaWiNAiB\n",
603 "ZDXSOJar8XWu4oLlIMjc8YRMId7Nh/hG4fri8V/Hx3/bL3ukyD8Oo2eCbRYJ+ZLI5GTpCibVcUbA\n",
604 "uAsyUhFsC3KArnSOoloLwNDYS3MF+TB23aNoMJDXQUbJEYsOhIs5uV3cw/oWbnxdBt00kNyg24xp\n",
605 "eIJtj+jZbVR6cvGeZu1PtaniqpUqNmG34G3ugmjB+XyMwBerZUsIPKa9WtkNIRkEWPlSKw0vGF41\n",
606 "iAMQXQszUhyq1QlGRorYOXsw8wYx85Zg5lGS3zaQEyBjxY8NXSQuRF8ln+yI31NsPNJ7IP8MopL/\n",
607 "9F00cxYImilHTPyzinyhiCdgXEuflgwiddZN+Ax+QSFwjKTMBo+h1SAO49Qi+ox3cWMrPjtZleIQ\n",
608 "YXQILriD76KBA+4TdO79XJx5BA8lJ0UbRJ17uTANCvEhh9o9WlwwFGeB3MPzdTAj3sUHjYNEQWxF\n",
609 "YFd4eoQNGvxPdNP/Ql8I0nJJOND/y6WSIC39Zf8a8md+ZYpfk40lDZtrG+AnFo6Qnzh5SH8cAudx\n",
610 "TIdbmASb9Ntw4E204r9heJwQ05h6nB49KQd7yGEob4HsBAmyd07wmVjRNn43f4g/zp/jr/C3eO1A\n",
611 "zNTJL+EH+fX8Jl75m569E7pMy/PUqaqM1I+uuYTQrwJOZVS5VEFVTNWv0gxL2/GR1JlY8aSD+pz6\n",
612 "ivqWWjcQMyN27WH3tWFY0sgt1WM8x/KUoLRBnZpJM+jlQZCLOiQoZWKmoDam7dcOaTdoN2u3a/do\n",
613 "E1o9womy2ye0ae2YVjuAuxkysj+pE5/lArb2InQkj7Vu0jd+Ii+dN5bHWmc15rnyHvWd5w3Lgefw\n",
614 "l0tLEHR4q2ACE9cJw24aR4OPd55PBg7lgQlJpRiB58Fz1nAvgx3tx2i8A6LBn1pBvpezw8ObDomA\n",
615 "T0saLbzvUh/jlMkPNZ/CyvlzWK+Pac5i2w8OuoLCozhNNhxFnZb0tIMJ0IvB3oOBfXj6OF+Bca5H\n",
616 "9HavegUs42RN1cB5HNeu1LIDGnDhVSB3MMA0GHZtIEcp1QFb5G+J52GYezjEz3LLEUJiQ6ueZoRn\n",
617 "Q553i6KbF0N8++jq27xq8NLl1bx46/f4g3zZeGL8+/yc8eP8N/h+GvMT/8rG/EI25nV8YUIISOfA\n",
618 "ONm6sg2xECqMABpsQ6oNKiWITP+4gDKBoiIktSAHATFFH4GkGnaDTs0SzaBmvWaTZptmt+aQ5rgG\n",
619 "N1C25TAFtpLuxpAZBDmX3RoGHgVblUA2G5Sv/ljJWlKrEJgtdaNHl6mxCH9P/SP1XvU76pPq8+qr\n",
620 "avaApWqEy4Gj4St9gkmFeEGOqUfqlHpUfUF9Ta2W45qlN9ktmITOh0xs6WEi+vjd1X//96vH7/JN\n",
621 "/J+MS/zi8a9SnCb1Ha3p0aycsp/yMvAaTFjRT4BXdOZ0hEOK8pCNvcxevy53/XN0fTDLdlJX9LgF\n",
622 "EwqL9E49E84OmY+bcdh8yzxhxmGz0yzIgZw8Z2X3MiPWnbcwCYGtg+vBRwN4myXYWoLXVyOJhX1T\n",
623 "Psb380P8Bn4zv53fwyd4+qbZ7RN8mh9j7AmahZBGDC8i5f/DXxIPoXA3aQM+ZD9IEGQMC8Z2wx5D\n",
624 "gi100hUM5AkQJ8RySqufjMKn+KmHg+QQPaol57qkzQkXPhDMa4rcQZZNWl447CBxECwm7JvziD/j\n",
625 "q1qrhKLxZ/k/Hxf4n4y/wP+rsOXLY13tQk+XHNtC/UjftH2K7uiltkkb8kh4xIjszI1XRM0BJkWJ\n",
626 "cfmM/1/8GGfkWvh/kSoDYn0iYBxRs7kxATHRyQRGBLmUqB8kjGn2p4Q1nbAGpFtMkkaatDstBZEu\n",
627 "dyWM7glPS3I3PJTkPhn+ginQIme7twSS6ZaxFmFghBMeJOqMSu57qfBAssinWNjjLIyjBS0xC3w4\n",
628 "dS0Q2z70fuoVyEbzEha2i+InUETe0Z5EWMsdCC3Eqi4WfAKGvAXK2veQuPuO+SQblckd5n3I36UU\n",
629 "rosgv4V35im4zE7ClJansVgsXkvY0mNRs7tYPsGj4dxN7ijbB/1zH7SuN8lOCkPqZbhSboLUBvnh\n",
630 "1NbgruBBWE/s8K7YmnCoaVfTwSZ2yM/2kkeaTzezyeFvjjb3NYvD2aCI67kwHnqDD7CCfApC7f8c\n",
631 "7YSNKAnDCRJpcGCFBeZmyw008IJVaRSy6KUbcOxfbrjRIGT9a1Y8OtU8yh4tWZr5Yc+U+JbZYou7\n",
632 "WusLkwILx4/b6211T4nt55+0L+huMrl8pTWtNcWvPjm7tuu71Z2N5WoxJopCxZKoc2ZD2axVz9fd\n",
633 "UJtq3dYqs97mjzirw/kbI4F5pf6O+l+WzTIV15oC/mJ3qDo6x6Uj3w4bf8J7bPx2ZHnS99nAtklc\n",
634 "mPVbMAxtIXwizJq7PTwlDmH6NU/TNW6Ji+IaJGv2Y+tEFPJwdE8UWWK3WyfjvmcJLdwXFKu/FGtI\n",
635 "ERN4kseFc0zFBbvRK1KOajglizpMzuUysl2FsR0RIjZUmLQ4JmoHuG8xtm5jclSySHAKFDzqjoRe\n",
636 "nvXc00LLdm5Ke4/l2vsctbdG2gb3/ZXWW3Df0ywKIlt0Wy+O9t7qFSZjJD4Ta9gcNXBl3FKxTXoq\n",
637 "zPhl7Ck2A58ywmgqDWL2tYefwmxpD4wY2GQNG0eMqgeJdmOijNIZytPs5ERtOlEbSPgyUmM7TpZW\n",
638 "NbKbhI2J7nSiOxAr7u8e6t7Qvbl7e/ee7kT3iW7dQGJeJrlnXmIea+GC7CULMAhB9iOBe9vy3cux\n",
639 "aiyHLrac9frYcoUJLGZTfbHCBOJsJ67sNLGdJoUj1LOdeuwsZnyHzfr2xU3yeyQ725e0s6nqbA+0\n",
640 "C8MJQzrRZBwxC3ipkTL2w16p3jhSzS7xLa7P4ig01i9GI3+NtOAP8XJx40gXO2NenG46L5AMzovR\n",
641 "29Al0s/wIssYSb234P0FHy9g0/OPF8hxBCshDK+FeHkS5p4UyDHYHg47T8GqsgaK8CjIVgIdANkI\n",
642 "w+MukKRfYQpkabyEnONPQW5E2MPeiPw48laEPexSG3jN1rZdbQfbjradaWMr+gEM4NMgx0BOImWY\n",
643 "ErTXgrwOchIZxDtAXge5BMfnpR7IsEisPwxyeiHYCchlkAv9uAHIJ/3glk988gRmBb3jOiJ40STe\n",
644 "cRQkCUYyCnISNpfDICmYHk4RwVvvxQu/BvIjvPArIEf8kwznBt77Q2RgX2q5juz21yI7Ivvw0p+w\n",
645 "LpB+xt5ceh/kHaRav9a2ow35TziQxHt/D2Qv9QDIVuRVv8BePrll3k72AZPnu692s58LPdd62HXv\n",
646 "4J3fw5tepdddiIzy/mv9MC89gQOM5AL6tFO4XmtraDKfGszO65vC8kKtSLnOogNRmjZ4o/DPpd7W\n",
647 "qsqQ1/ILc6PXThxxpt/SZXKHXJUN1Y68Fu/aSOuQw/3sfLDEuq4nfOv5cm9twVOz/NWD0fDSYutA\n",
648 "qGVJuIwvrIrUWqy1EVdYZ3LaiGXWzXTr9a6Z9Y58c3mRv6mxJdreBH4ZiDoNFZ5AmaEt6Kpp8dYF\n",
649 "azqXN1U+lh9uIv5SnnS1BduYsB1En3JtSI5o29OWaBOnxF4JCeECV8Q5uW7x39hMTIQyieqMdALh\n",
650 "BlyoGjPkc+gbH0FgYZNNzdT7Ivn4n8KTehNkKyOJkDExOyNtmM0PEN8JkYtdOuBgf6o2JqoysYKv\n",
651 "V/1R1Z9U/XnV21XvVmmYOgIT0hcwZH0E8iuQIZAySxXu/yrsuztB1oK46Ghy1HUB0DVuuQ2RHG5N\n",
652 "UD7wFnxJoyBd8l1OdmFpB5krH7iE+bMT5A6IZi6Tb2YzBpihyAGpn5GReewtO3sVNtbG+FObItt5\n",
653 "2Y5X4VyU7UhKnLcNjUOwMzAJ0GNkV4DKk/AakTgtaSGFuelEKYomXwaZ2+bFgffRls9B1KxB0kvY\n",
654 "+iHI34IUuefipDfR2VfR2W3GERO75V5k8JXJd3gOnfQyyA9B3kW82q/K/hmSimuumyKvMGlfRw8H\n",
655 "uTIc6CojJeQueof6aR7dijFJsL/XoNYfJr8WwmbXaF+GYNUKNvG5DvhAujW6l3VsNpMW2Kuo4VNi\n",
656 "v85QKBikl1UgFL30Y5A7iF19E7LLXZAtIF641ntBTsIhexiEhsANkJsQaXqRl3gdfPUF8NWDIGcU\n",
657 "sSv5QuOrAIQ4CM5/BuQGyLFJKA4ssEdBDgPJYe8sjBSQwyDaTsjmRGJoCIhvDiM350KE3pLLzvgE\n",
658 "zPIlCGcX8LZ3QLTogdFcfPTrIO9QNhfIfQrdgr92q3kXpLYvcu/bA3IKr/ox3vIlkI/wquTh78P7\n",
659 "3iA5Di+9F6+6BmQU5BO89JrGl9lLp/Y1phpHG2F3x+uuIa8W3nTfLCxXs07NQqQBXs5PBC/XB+LH\n",
660 "G37E3tBUKOa4oEiIaNi1dogmq3sKP8yF/MguDq01Ehp3N1UW2mpbKioC/ppiX9TfMLvYateXNvrs\n",
661 "m3aveW7Gc/EZT8yucTTMdLlCZcGY190RKCtvaCv78997gn+m1O2bUVbZ7C41lnst/O66UFuwxFdd\n",
662 "oc23u+rGt/zsheicspYFQV8sVFtU/VRTbUe9xVw7y+eONLgLDxyYKlvdyPG+vyXe94bEzYIsiE+7\n",
663 "CSSI3RPoju2z9qA7NkHU2oNVI7hAJsMSB3ICu9uBRyO5OnCPDrAFtpUc67jdAdsZtrd37GHbybGe\n",
664 "21h9uB54akBcPfhjzx4cDfbINnGunzcJ85m8qeFek3iOaVg87G5JlxCEyClmpN9C4ldxPHmrobwm\n",
665 "A5pOjQBjmfQA2jAMudykCQHcSJ1JiGl2EbInYvq/Vv2dKqP6tUo1IH1GWZdTTW9DKi3lm93F2L2n\n",
666 "YSthyEQ2l9bg1Y7jxzuE98aX8OvG34RsvIr7VJjDf53zcF8yZpcwZSD6mgAkIMfJILQNbfRkpB8r\n",
667 "Yg/2fRkuoQ4kCjLQp0vSiRK2bRyxCQQj4RIonoIieVlDYvp3hJMCUtlUAzH9YfGUCO2NNX0nLA47\n",
668 "DeTczbqHccYRy2nLJct1CzsD0W6xAoPH4anzzPTM96z2aIa5mP6ocEa4zEYBzj4qnhEvizdwP4AK\n",
669 "JHcaDhhgxE+ZR80XzNfoju9YTlrOW67ijvdwxzwE09V62jxxj3oYwFLDvAzB5JPj4LS+DhGjPhsL\n",
670 "FxHm5JVV+W1Gi8VRYg+XF1c6TNq6Rw/xcWNVWTGvyTcUVhVZ7Yba6bvobyc/xP93ysEchem7nqwY\n",
671 "mVRQiAn9gjic3CBshuvtNtCP8mG2TCLXjc35TsMSw6BBHJZEA/A5krPEBQBjQAgY7qHKSFdkc6vU\n",
672 "DKPCv2IY1WBrN7b+AWQudp8EKQHhyL6XT4vCZQ3l0cHoqu/XDengRGCd1a9DLl9GqkN+2wNwwdlQ\n",
673 "sou0TtgDF+Lo0yC/wp+2g+ipddI/5DAeWmBauk1IHY/momkzSiLvElz8JghHaFNs4CfhgoGOlkaO\n",
674 "oJCRzLDOU2bMN0Ei2P0cWypsQY3OWjt76c3oPtKPYQv9TyB4R2mZhr0RU+0MBJCSR9AZ+WRyO0wW\n",
675 "cZhSj2hOayAtU4L9aZBjlJODPFRkKZ3ViAOpg4ajhjMGccAUsWqtWsRH+iLW1tCD75t/sDr4zDPB\n",
676 "1T8wf79daG1oa9hY861v1WxkG9s4gatnMtjnTAZbyH1FvU5qqWMjoM6YmJuRtmHln5iLr5mRbisJ\n",
677 "R9J2SGI8Ywu8/J3bM9LediazqJkaGGhhr7mHKRmJFuNIgZrMKQicaTEmXOmEKyBthwgwxMiIk52+\n",
678 "kGtHhyxqJ5CIucaRFezgAB1MLhkaHGJfYfeQ8okC7BMFFCmIiaEjHkhBAWMinpHScdwW5HYcrQJ0\n",
679 "HkLrY5lEND2iY5M/QAzkNvKauRJjiatEBHAiHNoTbLlLFZU7ywPlbCw7PQG0xRmQhqBntMfiaOGC\n",
680 "eAxHmSr3JLtXzDiyWpDzUmDJuk8E1q7TcDQfLDpahLAXDLD7IKvgDF6NLQO2PsUW8gslHcVdg9zH\n",
681 "7o9BzoKU4ZgVAdWfQ1DZh6X7ldLXSxEjXmotZQOdsA1PYhknk8wamGT2mVNY3DUIxgqDvKKYlpIn\n",
682 "7efhpVbbzXYPvNRrEIW2z55CpOkrWP3fBDkJae5zkDUg+xxgg4DP8zrCDtVw8nXHmw5EFOKPZmQf\n",
683 "7IO40IOtNrh1v4C97h1I7oCQk/oAqtVWG6+Fe35GfAY6BTG/KyE8XAfpAyEVdSZIaTObyWuaX4Zt\n",
684 "6HVEmphb2V3fh2lhB8h+kPNQ3faDLO9At3S8jiXxNBbTPpDLIFEIk2dAbnYBjaK7rxtiDxOtkwd6\n",
685 "jmBptGGZjPb0YfsLKK5tvbgDSLgPEg7IfkZS5+dfnf/5fCbajGKt7gXZD3JsCZq8DF6TZWghyCiI\n",
686 "dSU79tkqtpUCWf4MlMtndjyDvn4Gr/4MlvYPMGpWYixcBzkKosf4oOFyFruUsRYFWZ0bHwbs7sLX\n",
687 "95cyfeoPSr9Z+kYpa5wDKCkzQfJBCEnxMkgUI+Gb2PpTkHzs/ghf+3OQl0HWKvJuSmu32n0YID/K\n",
688 "DYVuxJK+7HgNX55AFTXAGAmDrKWTMAa6MQZaMQa8IEcwBrq96GFfnw8KCYZCtLYPQyEyoxdD4SKG\n",
689 "wnmIkOGGHmjr1zAEVoC8jG8P46C0Fls0FKwYCltgjftx+C1Y4z7AYDiIcfAByCoISRtB3uhQhsJZ\n",
690 "EMKYO92lDIobIL1QtLrx1d8B2QdyB8QCCSrSg0b19vSyp/wMw6AV5Cq+eQ/IPpALIHdAjmIc3FwK\n",
691 "Vo2vb8OIMGMI3MXX/whffAvIRpBdIKufgQAkapiIa5kas6pAmoSmgi9mY3mqvT6yhOYi3kNaXAWp\n",
692 "me4hBNuWqtT5eY5wfXlwyfMtc762rLl52dfmLNjq77TNe3KgadGWNbNmrdmyqPtbA+FAd391ZY1K\n",
693 "sM6cEVtc1bG81TPbyO5lqTDWdDTYW/1VbXU2wTt+raAsT5fvmb24LvqVed7WlV/v6Pj6ytZY1D+n\n",
694 "wRZ9fsvixVuejzY8OTx3zgvzfeVOm/upuS3P9zfVNC42e8qKBH/nAndduD42Pycj/0VORv4lyciV\n",
695 "EoevGoOicAKWyO2te1qxzAX7sr6B+MRnwizhM87ENfIVUlUjW5tkxCmkDDWwhYUtmg3GhDktJaBy\n",
696 "UCBnJ8hgUAkuokTDwqnBXIoNkEI2NQ+r1eVkA4TOXAQHQDnpthdg/YfIBmsOzPT1XkR7JY/Vn0XE\n",
697 "+E3E812ulwFydwkHmbwkQ1MNJHeJB/GzQ7sPyZ47dPuAQrUjfx9yPncU7EPOZ7S4Dzmfu4oPIvdm\n",
698 "FcIWkH2a3FVyEEkbgH1KRip7EaCdco462akp9yiCriM1vTWImkYmruehXFE+VBySJUZzNtLI5za7\n",
699 "+d/aG+f4/fOay8ub5/n9cxrt48u6BOOMYMgaebrL4+l6OmINBWcYha6bwLWtaJ7ny/4KTeN/bKu2\n",
700 "GDxdq1tbV3d5DJZq22KyZasnfsN/lckPIvfThIgMZQgHE4hELeKdvDCc9fFPQGCBoZuwXB4DhaM4\n",
701 "rZQMquQqbh2MGVsp7PUgd5Q7w13mbiDs9U3owW0CjvcJq4R1wkZhq6BmS69wlHV9zI6+XyWuEzeK\n",
702 "W0V8AEUgz2eyEa9VR/nATOFvS7+sN6H9T0z8hvsBG2Mi15hQBRC5mG0tk1ynNFMZQgpAHYHyuJ9o\n",
703 "bxc+e/AF7pM/8RxfLGS4AJ+XmBFIDs3YMEMgZKAZlOKXh42RCjZmS+hQgMm12wK7A4cCxwNMrrUF\n",
704 "KjDQOpswbg0BIFtxBk8WzmUwi/+bJ1DQdoANTBtHcorHOFJDokhMr+ftvJ+P8iq2EBMkFfpHj2Rt\n",
705 "vxAV2NF1kDa/aMBRQ4Ojoa5hZgOg5/SN9kZ/Y7QR1zViZUI4RUyv5a28j4/wOEUjWASvEMZNSIMj\n",
706 "FJh1MAncpdvpG+wN/oYou510r5EO5O5pag63yoZMMw1P0trNlaKZBioOMkYHnOX86khJpc8caysx\n",
707 "6wVzRaVeX1lhFvTmkraY2VdZEqnmO2a2Su5gRUF7ka2y8C9qmioKeIEvqGiq+YvCSltRe0FF0C21\n",
708 "ziQf/W8nnuPu0bdwsHGVHBTXK+FebHzG9Ju57RyAAFQUsWPIwBNawkRPK1eCTq0gf0UNQZ3NSE/7\n",
709 "JgEPQewE2DcJ8LLHUP4u7ANy0z6I9PlD3SjVCNmgniT6EwlsOLAWfblmsi+1DdYGX0OEPo260dzo\n",
710 "aWzFp7mDTzPtI9/DnXSCDXfy404zQQjWZ60fd1I3mBs8Da34Krg13YLdv9Ha6GuM4NNUa8xynKgM\n",
711 "cU32ldZGsVWOJG1V3HChe//upxH+o5+GzZM57Nt8xL6NlvNBXweuXBoquqB+wAGwRQU0FupZRP+i\n",
712 "L03uYjZQikMfDQ399KfCvgefhcVX5XtVsXu9S/fyJzQBKYboPF5NKRhaWCc4ultg2t2sbNq2sn9V\n",
713 "uNsaMT/8YAuNmatCjM8j3JgzEqdBLBN3HJgjJzRpGELkWwLcMMN9iw0qG7RQYBRldc8UfgJaMTuk\n",
714 "UB+EqRUGpyGAaC8tQBFpmqb4Uf4Cf41nc34/RkjefuGwcEq4KHzCOFhMf0R1WnVJdV2lQoi6+oj6\n",
715 "tPqS+rpaDd2PzgaLky0N08+WDqrIaJG9AAcYm+Vlf0IIRoNwhM9TPdHR8YRqhnam1ztTK7zX2d3d\n",
716 "iYpoFEc9yQe1XE9CBzQmREFOaGSFSksgKxrg5EwJnlO4oobtaGTcP6wA7DR1Rv5wIuvqH7TjP/bi\n",
717 "jeO1479i362PG+F/LpjYul4gGTixnpOK1GI9u2CayNMo9JUHYx5PLFiu/PK/P3WP/XJZ/PTf8n/P\n",
718 "/xNXJXRLVUB/XW9nSrVdDrFZDzt/Ech2GbIyUZxOrXdvcm9zM8H5Fgydg25Em2BrCcimHEBlJXuv\n",
719 "SkVgKGU7pWRtryyVOXPKxQW5GKB9Kml0AZ2wgDEDY2mlDGCQBFSoHCRwDMrzv4H8GmQ9wjAITe8Y\n",
720 "yM0cgOBNzOuwugfpo/thJNmHKY3YMKkVSmYPyD6QA1ASjuW8IF8gveFD46eIaF4PNeFdRDRfKL4G\n",
721 "6aK3eAUCm9+FBW0popuvYes6ZJljIF+AGBB8MB/e/LPWD6zsNn0Q8+/Dkn+s7Cws+QYI+kdhIL4M\n",
722 "ch/EgMDv+SCE50+uuXdh5V+BPv8AW0Xo3/XoVUqJly4p2Soyig6GqnQAr0ngDfvwNgThj4wNKY53\n",
723 "6StGwmDxTYhI+RCRKLxzJd7kJoSlG5b7EM7oXQ5DJblLuiladTiXSnYXiVInXedztQeeQgtPooVX\n",
724 "QdTYvVglYwx6ZWEqwiaOVaPRamSB3GqxWPn/Xjzbx4Qnm40JU77ZxWH3ymD0mTnV1XOeiQZXuvk1\n",
725 "jhq+vLm7tra7uZyvcfj9Pp5nolVrKxOxeN7nl+PIPhJa+AKyyW6SOJ6N2U0E2garCllnpVu0gA8K\n",
726 "64VNwjZBNZADcVLxXM5OK40BnUbfrxnSbNBs1qjI3nYLEta3mNxiI0EMF04gRKVIdGId3IDgOhVP\n",
727 "YY3qNKapj8l/oT39X+166qkuoWX7iy/K2Ow0p7r4L2Rs9hPQ2LYzAvGlIy1pazpkbE8Fpn0KQjsy\n",
728 "pyoyWZx26U9hGHgLcuzRyjOVAgG0tzIhvtKY6GKthQd5cJ4y5Qh/XZlyXWyn6yH89a4s/nqXjL+e\n",
729 "DDbEmP4ImIUgm4FdxpGZbAbO7iIY9tlsBs5eMptmYBLpOuz1oZ0mz1RfRjbjEfiMzzKSOuI77buE\n",
730 "IhPIS05+2PApu2fyQOORHMb3LwD6HW7ugXViPzLDW6F39uTMEfvg5OwFOdKOMQ1yE+QXtDUb8xvk\n",
731 "r0GuQkm92AFxi5Txk1MMMkcxFM+CTG0p4fOfAklRWhHIKZCPJ7HJ0czraObBxqONsLo0x9HaA1Cg\n",
732 "D4SUhvagjfvJ742WXQXZBzIK8gmadxnN+5QR638EGRxzQvvojHE/+J2w4JFKR2NuvoQfnU26x+OB\n",
733 "L1AZTFPmkf/ReUaYij7un9kMc3KdkraQaYy/Y1QCTsmZmcLm5WGWKMrAzF3Mlq//58uH1v/Ot+vw\n",
734 "P775S2mdXTxxhP8XoZyr5PyCSVIVAU+Z8bqUHC/KBiBQO6UTIPoilQx8nUzrx4BWFtTH8LNdv4f9\n",
735 "JHQkOumNCX86UUp2Yyuh2znSqPJRo3ogv5yVvZzV8FDYL4lEMjDciayZWpchGHJsMrXaCqBlUEsG\n",
736 "tCwjnQPIs9U4UsmudNLj/GSmpqULgdvJ08IlqL6yGpb8QLwJbrMSgIr6I/mn8y/lX8+HB4V8kojE\n",
737 "14OpXyq5ztTcJNAm2c8R02mUC7mHaDM9LKB3YYUs0DqsDp8j4uh1rHBohqVdWJI+LPu0DFeUn0ae\n",
738 "80Ew+BvllEQF5RPuHWEgtUNA6hBCPrJJ2my9QNc+gLiUl68qV81QtasWAgcUGZPSDeBtH8s/m/8B\n",
739 "ILiPUlMJKIM1NXWy5HzJVSBiUijOSbRRjTamsHUX5O9hEvstNVl0mBxuR8gx1/EUmoz6JMlLZdex\n",
740 "iv4Ya9MBNHhyKT0LAi+zJyxPH7MbsjjJ5CGzPMN8WtlLauX7a9qKwq6lDcGmxeGKivDipmDDUle4\n",
741 "qK0m6ArVmEw1IVeT4Lb5vbXC7E61f87SYHDpHL+6c7ZQ6/Xb3IKgcQU73O6OoEvz0Fr0HUmDWNhN\n",
742 "kPo0kOUIZ48tMNwQt4HbDJWJqfe38Mk3o78ENcV0q8nfc4tk0EHVetUm1TbV5IolC8y0BkGIFCEd\n",
743 "JovUTog4E7jLBrhHBFEtR4S7fVp3JMQXYDX6ar/Q8uKL29m8WTbxBfc3/GXC6fkWSehSP1ZMeCaS\n",
744 "HGfkhOFYnqzXIVdGPZCSA28h42lkV0U+CbAlaekW2O16+yaw2wS2Y/Z+u5KrQxYjw8OhtPpMwmxk\n",
745 "zCHYFCmV7XDgDcVTtv+m0marnPovaK6qMrN//FeyG1n95xvceW6QydmLCO43IwMr3wOmso638bW8\n",
746 "OJys5dt4Nnrl2GJRTkwWmIiJuBAFCpejSOMMYbWxi62sz747d+4T3/+UUnw4+8RvRK2MHcctEH8i\n",
747 "VZaK9alNpdtKd8Ne7CxlU+9c6RX4FJaUDiKLe0yG18Y3nyBvD0y5Y1i6E5Vy4RSm1hC8ZSmyqJND\n",
748 "wQ1BBHcE2Z1OBNPYjrHtxMyM1I8qFRtmbp7JuFRtOjHTmJjFLoXzm5tlnCUMJ4LkYSLn0ixjYkFa\n",
749 "GkLQVBBBU0sWDS5C5uCiQ4sQ1rdIkQumla1Sgngh7WAEpTCaAmoRQj/7SOTeS3FFxiJXETvmNibq\n",
750 "mYgCK91EPVWESLRmkmOttxH3OKuVQvdmBRKtTKxhl3bg0g5jh6tDRMkt+Jcm4nhE3BkPxMVhaUF9\n",
751 "K65YAE/yJIO5AMtIL8jnkLUARAsdn22ndohIV8Q5uTJVADOT4kDF26VF0iL742X4Gr+ARunQ1jGN\n",
752 "MotZn0LZiKOIc6HCEV8g9MWgc+jqdKwpUbCrXfkH84+CXV1G3Md8pbRQalfBwYKjwE+8DA72BQ4Z\n",
753 "ChwFdQXsQhXE58+hIJiLPUwzSO0o3lecKhazeeAREDWk6zBcZjtK9pWkwPgugPH1gqzMJUYuB+ci\n",
754 "vAaC8V4OyeUayA0C44GJ/3TDJZj4VzLZJHWp8XrjPYSKUIzMq5BNVoFcBjkLchNkJeSVLSFcHLoU\n",
755 "wpKAAxtBboCsQCjja5BnXmtD8kBY6IGbWoXOJdD9HiUCW4qgTyO6Xphe2wriiMYmHEBdDuaIcP90\n",
756 "eN2Z2CKMvxUE5UdlnvAKZxou4xUowHpVLsTnPgiJhyvQ6FcYSZ5qvgip63shxCiF1oReDsF5hDbf\n",
757 "wetcDH2C11mWa//rrP2mh+ArtA8pwp6pCOdsAXBPB0Ff1rT8a11dX1vepPy2t6/Zsmjh1jXsd+vC\n",
758 "RVvWtAtzip/vDj0501UZfTJUE2uuVrPR1eJt91us9e2elh4dPzT368vY9S/Nm/uNZcGmZS919299\n",
759 "Lhp99vUl2V99fKl79lNNTUvbq03eqLeurayxo8bd2VQxq57kmkpunVAoPM34TYTvl6xAUUNVMmkI\n",
760 "JOaXgdAYH0sCw4J1QBqdnAAZAolZZenCoH7ASa5m5CWyDwBMMITkJpohITVvbt7ezJTtZjLOQ6SP\n",
761 "lPaCg8muz2TE3IufsL0HjH2f4taSredZcTrq7oPtvM0bBzgBwIoUJ9Vb5K+sj8OifxS84gA0gbZA\n",
762 "PACZJnAUNXxScFNEWnvhplAeHjb3wO96GO61I3hcFkblrcpjylOlg3h0mzs+5dGkehzAMyP1vXjm\n",
763 "fjwuEujFc/ZNPkc63Pro+PBYLFqLBm5+2cJDYEgRbxgufzlUNGL9vfLmLq+nq6m8vKnL4+1iMvIr\n",
764 "jnKeL3e0zmitWlRbu6iKbTxyhP99X3eosjLU7cv+DlctqquTzy0rk8+cto9vXzvxmVCW9dPEpdKq\n",
765 "ST9NqXHELPtp2OrZkJaCOT8NXDTS8aDiCyAHzDTXzDSnjeKnyeFGPs5PE9Mfs5y1fGC5ibAa2UUT\n",
766 "079Tf7L+fP3VehXpgD8S9kI2/ZG4F26ZsNhDThrGggWlPk8S7BSnFO+F4SRc3IOfH5XshTMGaDmS\n",
767 "vpLPYuUMJ486zyAUW4+MdiBjJY+6zwCyTA+LRxQkDkyco4ikuw+ix24UBHE/kt4DpHhwaoUrzcQj\n",
768 "Tjv5gchD35x3t7qnewatoeLQBnh0oAFBE4JHh//5f8yjM35r8cMOHf4PmXzin/iOIFLtgyffFtUa\n",
769 "VT3Z9NJZN85tgc/aQsn4SQZB2cw6NcNQ4vJUsoWMrGIa0hb00BZgyAWSQ6g1xEf+7u+62P/5e+1f\n",
770 "jgoz2/9OtuU1T3yH/4Iw8f8ze37h456vlquQEPyOgShb8lG4BhJeIex7HAyYOSgWapFJN9kiSaUj\n",
771 "HBZVYEQr0OhUUdUaEUjsaGux0lb2jwniZDCW2/wu+6+LiKBqH0+1nzjRzs9vPyFjUYT4ffyAkCaZ\n",
772 "KyWVVkJGZYJWVqpaIqcyQYwifMnJoo05SF51BsKKPZPFBiJ5k6ewnyTsvuAMWNZGQQgelyBOTiLx\n",
773 "MwsPdxRj6CBWsTOA5coqY3IxkgO47DQICuAkDxecwhWHccVeKjNYwv+7oLN8g7HMYzZ7yozKb9BS\n",
774 "C1iJWovyK8ya+mf8Tv0r+0VfTVwVlvJ5wjGS5weA/g+7cSZmkg1ZMoo+bO9jGj0TGzVGDeuOfETx\n",
775 "JBHAw4R901DJhpLNJdtL9pQkSk6UpEvGSvRQNcwBG5R4kVgOBp2pJVtaF5xyyvbecqu1HP9OKBvC\n",
776 "66VOZ+mUf0yOXsytEBYKWmpnGbdZ1jygFCWhEwmK7pGE2sH24FtinXoF1kzYzuWiD5se0kCwbSM7\n",
777 "uZ0p4ECUGQLhMPe3V0CJtTsYE7UTkgpTPRwEV4bR4Pkd2oe1qrWK/6OHVZAz4wI//gNFDwlkN863\n",
778 "s/eqn/gL/r5o4xq4MDdH+LZUDr1vDKhB6fIxaNQxiHSbQYZA3GoCOHEHpH7G5xgvT8xJY+aw8Vqd\n",
779 "STSmYXxgU6g8G3w5YlITkIIvnfAFRmrZDuPYIRVFY7Yrpolp+PqEDwzz+pwCBMqjhOLEnKzH7jh3\n",
780 "jrvC3YL6WUBzvgDw9KAmUBSqTcwhvKw6K1PUB63rrZusItMirIeYrJE1Zyf7rKusbBRVUYuryMXH\n",
781 "aG0mubl2e61A1awa2Y0ayO4RxmPD58JXwrfC7LEWYyICppCS3criQGqddqN2KwT3F3I1UrWI3dHA\n",
782 "Xr0flcJSxaPFFyBTixAtyWhAZve7sFifNX1gYm36uemvYPDYSYFekFgoGhuxV9LH0L1+BPI5bKcv\n",
783 "V74GseJl52tYcQhw8TmAKb1WtwNgSheALPQKDhyuO4UDVyHDrGwCE0CbEX6EqU8JRRo0dC+s69Ra\n",
784 "qt5Kgj8xg9+ikQRPdxVEi9ZTCdLLILty9Vr3o6n7qYoPWvkqIuZQ+lQ6yZqRerkOLYO1BC2j5q0F\n",
785 "oaKWK5AM+A5SakYZMU1aOrCsab1ebXGlKPuK3a1ery9SKYYiWAvDXp+YNYKMV3dH3FXhbk+wpm2G\n",
786 "u7DNHK/xxGfWOCPz64M96yvbjbW1PmPQ1Ogr4xdEg2UzXCWmqhl2Pm5wNnY11vc0V4g98wptTmPQ\n",
787 "XcWPf15Q1dTdVNfdXCnO61J11tebXZY8Pr+yyROaW8KvEMzVDQ6Ht8KipzWqW/gK93NaI5slDcf0\n",
788 "6t0cvIVsUMjcS1Q4VkrmYCL4kp7xJTEznR115zjPf1M4Du6/gtFd/PtslvYwJT+JSFxheERUP5A2\n",
789 "w3gVU6Jok0PqDTCijKmnQVooYpSS7S1X8dnV1cVuSesU4nEe8GOcjvPwp6QaB2Y+hJMTIBwTTmCh\n",
790 "RwWhfqTPOGQAf32aoLbZn+QZLg2ycQHwbyrB1Q+yHgbpbSBjICdyZbmcrCVOw8MynJOcZkx4Mstm\n",
791 "Tuk24nM5PT9MMZtm40gh+3Ox2Yk/Fwek7cVyYhyVTqGQ2v1grqug5Mmw3yCEDt8Dsh+Low9bvYBD\n",
792 "IOjF1cD9WWl8wcim0hbjTjjLVmIKbMRkiFiRGGs9DWYRsfUC4Odo+ZlyWBkrTgMtMQoGTcot3EQS\n",
793 "ByzDJVTW9wChjuH5kVxLsDgnw/k9+ew+1nwf+5Hxdz9BQ1ZgCu4g5DWq8WiEmXSFca3xFePrRlW2\n",
794 "LUetZ6ArUZoG+bEAfygdBtGiKRGgN16oulYFtHhZJdSyqSJb4KcFkZn5ZH/c1d5QJojlje3u1kWl\n",
795 "obrnZ7asinlqYsubW5dGK/nCuU/Z68IVYXdHg6PJVdfaqMiG3s5lwUol1+EB5Xmty+bK/oSNJx8+\n",
796 "/rC0HiNgCUgAuzQqOAQBbvBu9gq52ooP3+NpukclXZ4MeDu9rJe2g0+M1aFfb/uzWEXydcdy1z1H\n",
797 "17XRc2L6Q97j3nPeK17WcRtywzEInRwYZuzvbcfbzrVdaUMIedu0PN6pbdlE93RI27M663ByzH/b\n",
798 "jzXeb/QTcoDIhdk1d7Iy3iL+r6XYfDZ79qDUahEyWjZjawgkxghihaEGzTdS1bAYFpFEJDBSSsew\n",
799 "0jQEpD0N/MBIJZtt7fNjlDIGP8wiefvsImUKTcPR7mY73Vgr3c3d8qpM2lA3IWhDP7bzD6RaNaVd\n",
800 "tbuzdlVJi1D5FflrgSsMmOzkioK1kACBAp1cWfwCnKuwyUtnYRhaWfICVB6IkdILYOjrAhsDWwNY\n",
801 "8KC/rW1hh9a0vtz6Wis7tBYpTadms8vOd1xFYsqKjrUIzD0FT9L5yfK0yfNdV7vY8ZcRh3keEeYf\n",
802 "IOZ2Y5yd8UH8ZpydsXLBC6jI/AGSe1cufGEh2gDD4AcLby5EdCBhg+gx50/m8P2AhyydgplrBRYw\n",
803 "WOvlNNIVIGuU9kqj8G6Nok0nFz4aNCc+tK+Vl6VctpFS9p3mVTjC/6XFF612t/ksFl+buzrqszhM\n",
804 "1Y1lZY3VJuX3A6uv3OgKx2tr42GXsdxnbY97Zj/R0PDEbE+8/ZSzFZe2OrO//LqyxiqTqQqX0u+3\n",
805 "dc665rK67qDDEeyuK2uuc+oE43M9jfNby8tb5zf2PGdk43F44gvxFW4Nyadu7qdwa5VAkobcZFXM\n",
806 "9pN28THuNpenCK0AUMjHaflD+RvyN+dvz9+Tn8g/kZ/OH8u/nY/T8o2Ma0FpseE025Btg22zbbtt\n",
807 "jy1hO2FL28Zst204zWZkvFIazNV6KGPjswwsvigNQbwMCZgJc5rE8akSrPp3bIuvKBLs+NuPbimG\n",
808 "9Yf/cTK+1TnxOl/MesaJ+CKmmaqN2bJPfJqTBLjaxwSwAA8TmcXrD2zi9XNdnHIt/xldW04XBqZc\n",
809 "yAvTLuQ/G8/nP6MLBaYjjAoL+Z0UO9MC1VNAFCT0VIEQoXg5bEarhBeSFisDJN6mcnC8uarVw/4J\n",
810 "CyGws39Ce/uO9vbsWi1Ui3mcn5utegKJCeoisT65ybmNSYFsBU34MxLn9FOUKpSS+dxq4Nu8hu23\n",
811 "uXehi3ydEKaK1FQYCba2X4P8HORDEJd8+acweD6NsIgPsFXhojwc4Acn91WkKuSnudPQABAvkwRG\n",
812 "Kbu7Tz6PfNGvMQLfY50s57cwnrYEKWwBkEFIe50gm0A4ZAKOdWLE1AQACuAMTEbZKKJCrj6irxZC\n",
813 "gPQynvIeyB+BVDhrcTSD9fAmGvpWxTEs05yPoikJnsxaipA96T16U/n4dbzfJibrIJQSJqqoHLL3\n",
814 "PM6PIDBnK9Tlb0Pt7hGXQ3TeAZMyme+1YD+ElbEV5CbIUkhlpJQTasZbIK061kejuguAPqMkzR6q\n",
815 "N4stNTKQWkEAW5SM5vXlAUcdjEyPgjbR/D7ICmdy3sczYGo5l6mMkEx8mVI79ZDP78D8eAfhLyhL\n",
816 "kvym7Q0gR6+0s9tttG+FPfQgpPU/gIFyl+Mgwvmp/iZCfJJtFfEK9sCVkOJ3onPeAtkFEecuAqK0\n",
817 "MGT5yJoFkoSY+DxVDgXpqUF9AW8PrJphLP1hiEURfKBaFB5ZhQzSd7GkvjljMt7/TcoAgRqwC+St\n",
818 "JvREc18zLHDNB/HTFo4j0v8AIv13gRwFOQCb+S4KZEBeZQRepTdn7Z/FLnizfX87Voi1GPyvCltg\n",
819 "+CBHC8GSrwShD0c1uI7hSxyjNGF0MWlnyxEAdZWcGkBrfBVgC6/at9izPSnFEQ91Jle7NF422Xe7\n",
820 "siWAWetdBxFgdAC992MQB/rs39CP9dhaANIO8gxIIUgvDIJhyCzUgb205QNyv68Xtuk69OPT6MfT\n",
821 "6Mc+JppIBpB9CPzYj67cj15shcSzn+I90FfRXK/Nz3XdAfRaFOQAkzP4SlE7zcJjsUYaRdmeDAha\n",
822 "KxNDH7ZDDjXGmx28LToUD8smxvCMnhqh1OP1W/+w5kVHwNLuCFrX1I6P2BvmUJA5BZ3PabALP2z8\n",
823 "yrMvzmr4yuImRbQsrxQ80WBdabSmzVZb5DH7za3ucddDpkriseT/JZ2riPvm2/mqAlU99H+q3xfT\n",
824 "K0BLquH/yLqXvFJ8C8KOEwEI64s3Ybs/BwtYxJhO0SNYSvoMWyqne399TKvKeX1L4nFlXfpPgorL\n",
825 "trmc+xv+GrX5/3u7QJXP2pxvlPPTkku4QSzBGjRX86jV67YmDwB2TI10aYKamKZfo/l32j1N96OX\n",
826 "0MkRmdmmT1U8EQW7bErT+YTS9i8fZGuTMtIrcpydO/E2r1ap6pNAwEImKNzVHEDbTmSD1WDbJFc8\n",
827 "2CAHwDa56CxFsWD9VGdAtXJZ8HSikH2w/sKhwg2FmwtVdAdbWupEaGGwbBpYneICoELOhoci8FHE\n",
828 "mUdgbxqpvVpC5C+RGXlcQd/npOV6VGDK2pxlS5k26zwzh/jq9V3PPru8t7CiMD/fUVBWXaJZz+8c\n",
829 "f4Hf2b55YIlKbBdVJVUz7K/Cn47++CXrD3xLP58HDKrb4BQcCjoUZlAAcVgpdw8Mv4dGn459TCMn\n",
830 "x4tidGqGASdepH4ApxfMY8WPxNxUZpInKtPwIQXhgK+ltd6F8iXkykYZJipyJCXqp8ldSq/Vsp1a\n",
831 "pddK2E4Jeq0M4yF1Tg+wNHEgltepX6If1K/Xb9KrEbABkbAgjYcVgo4UY4WkfSvkOKDdwI8St69E\n",
832 "wITUaweW7RTBjU0J7e/s7l9WlpRU4l9RV9eeR7te2GIuKzOzf18+y7/f/rjPQHGJn/E3GR/w8F+X\n",
833 "DCViPRpck2YyxAjPpI6arIiCmoTSEIJmgYQHTDyghVEFM4NxpIx+shXEEzmplbJK86dOIHSYx0gA\n",
834 "z2pPEUW6BCRBTYWEPoKMYCKxSqkgDtkHpkhknLNL3HQiaw3G5HksOstz1nsqBnkY5B3Y4gFmwT70\n",
835 "KIHgYFFCSZjkaP6FXA2YNSCjBMUFQeBrMMWdx6L/CQiViZ8JcgDLvB6r1UEsSVGs6fNBrhOQ7ztw\n",
836 "hi/XrkGKM61+W3G3V1Ft4qL5Ezgy1VkgjAFpL26lwa3ewq1QA4av0mZBaB6BKafAOFMV/8vxf1RZ\n",
837 "g7bmJ2dV1cRWhOa+WNFbGg9Uz6y3OxpjXu+Cai2/TvjOeb2uevZTTaFls6tjHc66JnvdzCpPR4PN\n",
838 "XMKvJ96J+fa3ImZeBfceqiPfRt9wOsIGlYJUml5NBZLV7EeVAVqsPiPX7wQtYSfBzgrPgEAge+Vp\n",
839 "aQNMlNtAEiDAoJbSTuX7E2cpnPr9H5s4lgt259OKG1JHhu88CryzZHmQgjvCJXsLVjA1uwrR8L9z\n",
840 "avzt42fEZ+M/+x3zgJt4SdAIaa6O/w4bfkifyAIl2DLSEL4ex74jOAvTXGppjJLnqdRky+4wdcyM\n",
841 "OgS0zzioMyON5TrFT9dwCT/yJ+itK9hbV2By+GW2qyXrHJg3Yw9+Yg8VxhE3vXwqwvfyK3hxCoht\n",
842 "8hXhdXherYJPEIZTO40HjEeM4oBky+U/67F1D5YHXbENweorEVt3D4KWDkJqraPNgRojbDt1pOx0\n",
843 "2aUydvlBAmcBISCotSBvgkRQGGqFB+Ch3hVeYZhL7TDuM6bwSAsedBeP1LKtpKbYgqdR3SSKNtQr\n",
844 "0YaqYekd3HoU5BrIfpCLBAyEh6wDAfgW7xbhms1Nh4iJfeQIEvCUb6zVhvj9r8xVl7ojtZb6Ylde\n",
845 "eYG10pQndr74SpmmtKbF21JfXVBRZHeVGkTLi/xXx/eUhWeU5RUENRpTpdfEPxne7myb4agI6vS2\n",
846 "mlrjt2mOeBnREI5cIfc/UVViCfhcfkbajZm9HqQTJXsxOBi/E5HYNKJV0ZpJ6ieOMm5fEJDEAiXQ\n",
847 "6vF1ebWFMlBpIAuHIPmziJIDKF+MW8txo6KCXnAeX/4aSA8Sk1ZQJVHYYslW0wZih92pr2BVgTDM\n",
848 "OnCWQL7WqlY+xK8UPrsTX7MmPv6/+cpnhG+N/2HXgQNP8mcRq7hqYoxfInzM3llPpZpFxl3dvJXf\n",
849 "z78bGu8QPnZ+WZa1cRsFKz/Gmbh2ISK1eFHVzyujIcGyvaSFbbcYR8rl6AQ2e5vT7G+J9nSinSm4\n",
850 "UFivwE7UCXIcBGAs3CRgnMINyC5neMiHRTtRthPVyTUuwSTq5ViF0igCzpInS88j6i4FR8rHyPDf\n",
851 "XrqHHUhEjSNWdlZFVb2i2ib/quIX0Go/BRMO1sM5lkoG3wu+HxQppgEhaOzPrRT1BELK6n5Eoe3U\n",
852 "HgCj34klZmf+AcQ17Cw4AJtfK4b7PpBekDcx7xDmJWTju17DqkIwAmuxFceiEMdS0EaaDxShI1D+\n",
853 "zoCchmYC6DUpDqUkCpJCsvaK8FqocKewfT5yNcKefzhyiv2kzrRfbr/RLiKMRkbwf1PcD0WbdLMd\n",
854 "VBoZwzdO7myQH4N8A215H+R5kKsgrWgkmpsEwApeDS3sATmNxh0DSaFxp0BWQBO6BE3oDMgxkKNQ\n",
855 "hy7B7HoG5AbIsfbJEAyfUlUou9hNQ6WkQIzWXOH7V8sCnZ6aOc1lvK2xy+/pDJTlVwxEm3vqTYLr\n",
856 "mVBoVZe3pnNFizkQaCwVukyR31/S84cNtz1zmiocAXY6+61omjP+A1+gonmud2mwtqZzZSi0ssuj\n",
857 "K3WXLR4PepfHg41Bjmo1fCZUsPWxhb8olcKodUiWxgmPEbGc0olsQGd+Gu71Usac2bj3cjAKJ7wB\n",
858 "qdBbStZmQKdXyEcrAih0PwP1G1o3I/ZoSVgZ8xQ4XviQY2laCWHJp7XLIIgjXjaAi3yE5WWXwXe0\n",
859 "lLaK0bpOtRGqwavwl6wDATZ48k3DfpTEewmLJvlDoiDkl+yGsiOnMUlhmD96cobdHghB78PoQZYP\n",
860 "DdT3s9haicoA66o2It8DqRTJldUvVCvBWN8EOQuyEjUI5oNshAp9LYh6VU3Xmu4AJdUCzNQLzdea\n",
861 "7zSjelWzpZmtIsm1qlfQ/OfR8lcoPQu6xsYCpcko7SWX8R1G4UTWfII0RKNGs0lRA8lk9XtozUto\n",
862 "wxqqrIf4sO66ZXVCtilvMBJyF+esz5Qzmx1hrRY5FcHrbpXL4pEMsaPL3PREe21PqPIbM+bUlVZ3\n",
863 "rmgtrCzMt+X3D744UBn2WeOh2nBVoeCa8USHx9bQVfdSnaCqifb6Wld0VInqqCg8s/Tppe0FFYHq\n",
864 "9q7KxjYH47V3hBbuHVpfngOiCjDZHwd6LGZieZOIpOoBqUjkh2MFQTEm9otD4gZxs6hhmoZLVI6o\n",
865 "hxOCkkbJZ+REccbKxJDVbXj6uVnCe9tlHXQxVycsZG3QcN+eNJ6qRQD6xIr+i/pP1T9X/5X6F+oP\n",
866 "1Z+qtewBZrVH3aruVi9Tq4elz9Q5QH4ByQ2yBVdWV7MlalQZaQIqq5oXJhOqZINs8hR3EeEcp8VL\n",
867 "jCuZ1GZ1q8ezmEyz/2P8KaHlN42/aT9zButMC+fk9/J/w6m5PH7R2xqVXlX/NqcSmb5MCv5Acok4\n",
868 "mC2IkA1WhtyoZ9JihuCcmeZKyO2cpDOgZh2shLfA/4AuD0FWSKeMBpchaBCHUycMacMYyh4YUO0e\n",
869 "kpZc4ZwN1+XQyO9T0rGcI9yHLGEDHaVMMjkRvA9Z3AYsxvcpWt+u8quiqj4VjiI74r6ajqr96qi6\n",
870 "T42jajYN/Jqopg+h9Mvhd7lPle3tWr82qu3T4hw6SqXs7Tq/Lqrr0+EoXuU+gWnZDX5D1NBnwFHA\n",
871 "EK4EhDUwc9if8vx5sIDiTwTT/jQcu0+zTY9V64tY1UT55q8Hvv/9wPhF+rmdqPrlL6sSRPENZrNv\n",
872 "8JfZb9D6tl6lYd9AVHGqemkIdok9RLAoDskV66FBwIwBaCYq3uYEHLwTFtnjcHHrKcDtNgLc8tIc\n",
873 "exGxPnVCl9aN6cSBlFHn0gV14rD8bWT8foK0BiJ77sNIdyhfV8NbeC8f5nt4NiRXKmUdpqXU36Hv\n",
874 "oFFZVF5VGN/hjpquVFvUXjUSQdmVMCuzQ1qL1qsNa3u0uBn6/A71OYqme3Vh9Pkd6m6NwWLwGsLo\n",
875 "7jt5dGWeJc+bF87ryUOdytVoxzLqZtxkGetrBI5qfR6iCepj3v+YrgZ2Mefk7lBf/+XbaqXeU3Ym\n",
876 "AWl8UIuxzIsYy3gO5YrsRnaDzB7QgyJYgUiQcPcpvcTOyeMYg4DLjuOUPIxFZRAjkt4u+sWoiEO5\n",
877 "AgGPHcYpefgy8UIuq7KaHYtgHGnv4KW+HqOXkmM52Njh6H0OvS1QvZiJbC2ULOwV+55ylor8ZiKP\n",
878 "wUDcD6/Cu/gg2rgbw6sTrbolylEKd+jNLExID3M9eDPCYFfTGMDryQODXarGVXfwehbRK4bxemq8\n",
879 "mTww5GHRw96MTQ3cAZUupOXsBAB9+SLd9EL8HvmNeC7OXuqy8Bln445I+TbIBUwZhK0MQFxsvG6S\n",
880 "gdwAzyWloeAjAUaacEwD5SicKv4rwi0lkmGhF3RWSA4k3JOY/y7I25hbBdC9YTRCDyzHhDpFxecw\n",
881 "SbYU4X02GrcadxkPGlVM9DusPwXEf/xB2gjwrF1FB4sYu82Cl1jMTFvOLm9md7xLyKuuC1hXL+8K\n",
882 "96kbQ7VdTDv+kcllLRhcOX6RFxc/pauJx24jtjAptPDttG5puZ8CGWCTUqExCex9xo2FTHJMuC0D\n",
883 "budAtqcib/8/ALfl9PaUXCeErsrWDWFXqTJydOyjNT/YcqfCckcORQ1b9DROakhaxutWs39HZj33\n",
884 "9Pjbs54HcPf27exberlzvI/8kW74I3nCQlRnsl7MTsysTnT9FLekb3yC589la6OxscAdEI6QzXIX\n",
885 "U+ySscL+QuHfMVMWTzVT4u86xVQpbUaK+VDxBohiu5VaOlKsGEKiPjBpNlFGjFJTJwljo5At7UBV\n",
886 "HdZn2SwFRD1kPzwwxUo4zSRIMRuz2Dt9QTEbL7CRruHmUMTGblRWQwqlINdwSMbU/Wq51sPExMRH\n",
887 "7MyCKdc8za4pTR5SHcfp/SqsOrfVcpzJxFV2Rh7FmcjnPsfObYkV7Vbh9HOqK6pbqgmVdiBZpHKq\n",
888 "hGH2B8shy3HLOcsVyy3LhAV/sDgteDK71x127TtTnruJ7ZekOK1R69KKrI3afm22HoUw8U8Txuy3\n",
889 "cnJ/kbCwb2Xpt0z9VnmT30U9/Lgvl7DQJJc2u/CVqjZA+N0NmTOGvPaxKszw7FealhNKlh2mp9KX\n",
890 "UT7V+mzNvuxXgm3HKAvwPWXLy4QBLhUvW1n2Qpk4MO3zKbWai7P6kC/3Mf+XqDPpbBWFqi7BGmkp\n",
891 "t+W+7IMUL6hKKqqLBe+X5wxNzV4D8WXwsY8YHzPwf87YUPKQ7rhOGBjRqqmuH1u/RbDBFkyBHhCC\n",
892 "FLDRwgbyR9h9F+RrWOeZ2FjCZJ6UWwgJcwXGYJdBAgpj7swD+SlqygHpcruACZ0QTghpYQxJ9zoS\n",
893 "294C/8cikPxAfRMRd3+MA7+vppov0tcgRH5BGaWiyqRyq0KqucgoHSIg1IdLv0gih+D4JArYCXJi\n",
894 "anKt+Aq2qXLyXqwkP8RRVPlRshLJE66wZeLRyudTKuY9VNaHh2E6eZH7BCEAq7FwWECACM36joIB\n",
895 "1uJJlBi7EYRKRB/Bg7O6OJV0NoNo5Auu51ArCa3BA6mpVINiIaZISKt2+xAx/8Y/PHuDF9b8tquL\n",
896 "5//+wvidO+wjKjGNhC8SZ+2XtiFJF1VVBLLjUkxjEmWXhN8V1fiw8pmLapTvP6krfItgZMArJZ7K\n",
897 "3MT0dfxMfj6/GhLxv+HBwNHB5P0u/0P+Z3ySf49/n/8Y2oxAPipoC2oV0xaoElwO/5KfUkhOQYli\n",
898 "qoKsIyRPaS4yhs6r1WZPq0dYOP4U0xQEfpy/d+ZMO1MX5DZ+h+JE1FwDJvWUYBBFNdBmuCynl8vV\n",
899 "3SZhwgOzWJWwsH28gx//zgft2dpb3E326nnceXavJByEcoxoLlkii1lDKRrSZlhTYrC67YauOoaU\n",
900 "gaGCDQUYX3xASZeYNsqUOnWxoun1b5iqpYfUg2OsQ1EAK4mKWEjAPa47p7uiu6Wb0KkHUkU6lMti\n",
901 "assm3TbdbiY7ZwvSsMFJGfi8XBRXowXucLY8VK4wlCli1rLlX9saYR/5iSe62P/5s0v7nhr/z/zs\n",
902 "p/qe5NezPpjLcaLAj3Ez+PcTMwLS8Rn8wEi9msybMxByRFUBpW0gt0FcjBGOuFDJlyK/LewEKObb\n",
903 "QG6DuCzsBDMbjojJkzYgsa+zkfXZOWwNgmwDKcKxTmy5sDXWqAxUPesyvTIxi9lOsWFqZyo7SsUJ\n",
904 "Sa2XbYHq8xjwaojk/wTOUlhM1j91IZsU7xd+XIjg9DQqNRcbRxzCA8aTRzyyjEXpHCl83Esw5MRz\n",
905 "iJKXc4iScdglKL6BylceRFTDLvtBRDXEYcq+BBIFiSPEVFc+WT38OkyOB5HXtKvmYA0iWWohA49O\n",
906 "ZlRK5/HYHghvF4quAfmUguDDeGYvyBt45k7ImK1ZuNAB6QLIVTzsAuGqg2iB1XINz/svCJXYWcMP\n",
907 "mFq8qGcqO5yyYAxTJcIpsqEo9Aq2ZXWm+lp3fumKAJMRm+d5mp2F7EdT3+jp4l90tDh6/XU6s7ey\n",
908 "oYUExuLehRXB2VX3sZGVHGFf/hdhJTch/FfGp4yEy5Itr0KCCpuEE+P/yhcKK8OyfYIvZvN5EbKt\n",
909 "p8tnFCwGDZN9Ipq5xAmK27GuTZTz/8hkmXLuH6R8DvI5R7khAK7KCed55BCWLpbIDnZHWkqjZxIg\n",
910 "VBZpe+U0ed0w1VGumTr+lB3yDOtkr7la9tvkpaUSG029DAYHcHQkh40Y/bdhPf2vIH/moKrTjr9y\n",
911 "/MLxoeNTB1WlTh7VndFRFWX7Eftp+yX7dbsahcHesh+zn7V/YL/JdpkQn4W3hG3UYs1mr/kgyEfi\n",
912 "lS1eSxc+Gon03f4u/v3xL5cvsDXOrb89/ieOkGNhictWWPG5bAf6Lve8YOHvM+1eQ3UG5fJgV3Jl\n",
913 "hQkWpx8LlVxXULok17cCE2Ta22QJP0MmoUtTSTxpiGwuiN5PQqQShlOIDXFxTC7LwjxzsNGgwt3E\n",
914 "lOp1Mk9FATsNlw2rnQmB42mQXkgVVMQyDgVuFqnYIGQ2uQurTi+MIndhLlhO1o4VWI/bFCuNtBB3\n",
915 "mIeLI7huFVbYz3Bdt2JMkeYzXYqfgvHML/pJ/e7d9T/ZXbd7dx2/enfdnt3Y372njvpuLvRBxiMr\n",
916 "uNtSAbCxDtkpBX7ERksFlQ5ECk0h9EEl218u1rvd+Vi+RgvwwyNOUunhSExeUF2DUH0SnZCESaAQ\n",
917 "xi4lMOM0mFs3lMGUQVELT2GrGwYh9IjkA9mZNQGzLWgYG0HeAHkL5LQZn+4U7jWKi7fgbArgJ9f4\n",
918 "LpBRdo7JYjE/RpFkW77XBf5hbZKtJO+bPKZHFEr+q6aZjmzeBOvLBxT7PYP/O8lXwXpzM8LcYiB7\n",
919 "EPzok71LnWyiQmRG0LfPmKjLSPY6trKUig+kg6V0GhAJBhG8sZuRkRliNiOKKnrkP7RMJKrZnGUL\n",
920 "pa2+mny1TBq2HbcxabiIHTTbcDCJYu3CZNkgCnZbgbVhBUYPBUmvKFB6cSWm+laQI3AUIIIgqbVY\n",
921 "mboh3QOnvo+ZfwZM+gzGwWkoFDdc9xHWdj8XFHgBfpWT8IBeALkKH9AoyH4Qqkl2EtV49vlTfnbh\n",
922 "NThfLoKcnsErlX9WaZV2vYZ2LSfPEzEjeHYc8Oxcxrp8H8QO8z5hlFEjLzumtXQULT2PuMU7IARD\n",
923 "9gntosWfocUX0eJRNPYayAEUJzvgP+IXHsl61PoeSp8o1WhFN5+01s10u2fWWZXfuFActTUumVlV\n",
924 "3bG0uXlpR7XbcXwZ/3l1W63VWttWXd3mt1j8bX8u5OdXzewPNvXPdLlm9jfNWlk/fga6LM1NwsXd\n",
925 "mcXFRf6BFdAbWfyN/llgEsFmpXaYwLkZ0ZNtw8l/F/HAKKmd7HcOISvsNrY5p9GJoO0MLRWI2s3P\n",
926 "SBuwshSwQ+hsrrKAUM4J1+cWem83wH2M7DTMIr7MCCYqGKlKy0Z8qBdAxALA2kkqZ372aia1avMp\n",
927 "MFcn/1CZcuTDMZETCT158uFC+cIiumHCCHglaYJ9cAQjOTJkfJJKih00uDOIJygNSGbalyyOYvzY\n",
928 "5Z9yuWUV1P7H5BAqQE4SR08EeGonJHe5AYlCtlsoA6LdzpYpqGCbFWTkw56WRGcdZRHnUZahkbZL\n",
929 "6LiZzrFQWXl7GlHxZbDehCJuLdz9+BfS0j+zm/658Zf//T3L955e84eWF1+qmF3xPfZv9bOWwbWV\n",
930 "syu/VzmbL/npP7b/tP199h/7uXDhQi4/S6gi37WPf13OI3bJecTEXVzZmogGbMPXugSE0BYGQTpB\n",
931 "xkA4v+K/oxRjw0Muu4RbFgbsOUAFGb1YioN9RKEKTgcwjmh7H8UxDhf0FEzCGcs4xsm2kjjwnGQQ\n",
932 "YxkjYTiZsowCpS/nrEumrKPIb7qDQDoNJTyVnQFCEjAHJT3Ca+X8KxlpUA/JNFrRV8FuFXX2OZGe\n",
933 "5TpDXAkTnSkl7EDVmSqFTemr8AjPqAePwIzXIB4k5R1FpPIdxNhqkJ8U9vX44NprE+OTpeSTkYJe\n",
934 "+MnDCuLJw8kijyRGX1bCXJWw1ziy75UQWWTjP5yC70MErBIJy36VnCShimxGf5bNsRphY8IkDYJb\n",
935 "7a49VAuTlZ8fnpJPNe38p+l8F50vLanlh1Mn6tP1Y/XigGSsJ0tX/dT8J3btsdy1z9G1FukQrnUh\n",
936 "5vgQ8npcM3k59wl1AP+A6gBWcgvFvdKCWcDpQL2aACrXUCGbBCOJBbIbOm/WAky7vIB0Ow81H1QU\n",
937 "azHLOGJmWwvYGphGyS+2OjblEZ84jRjmuXkI2E/GFvUDAOjKYkUGibFBG1NGcA/b6VF2wmwnrAi6\n",
938 "jWynETs9MnSIs6cxW9EBzFFiXHOYSnzGyKCFMoVQqBpJoZLq5JPrAtIhpKA1hZGElbzSdKuJNWVx\n",
939 "EzwJ1MRYGM1divyluXPZEErPHZs7ZfWVC9phDq3BAncKxAcRcA3442mwYAqAIXyxA1Cg+kDOgBwD\n",
940 "oUo3vfBu78PU2A8dqg9z4ihIH3AsD5YfxcT4BSbGAegFbcgFPFpxBqEiJ3Oe5RQ8y5HqXvib12AR\n",
941 "7IU2t7F2ay2CMGov196oZSNjJ5gFFXk6C/IhyK/RA/8AMgo5ZS8izVMgd0FsAbjxQM4gsUrbhoAQ\n",
942 "gAreo4KCR6Kno5ei16P3ouqB5JHZp2cDwQfJV/rZ7MTTiKc5CnIfRI9om/tICrkDtP6VqNNwMf5J\n",
943 "PFcgEEpuEv5GNuOPFJzGvDyYrWE+TF2XOlh4tPBMoZiF8jkAEkf3HQDZiz7sAdmLjiR1cz/IKZCT\n",
944 "6DwkUlJfSRGQk0pPST/CtDtfexXTjqSbH6JvroKM5iSaS+ilX9Tjq8w4iuoGX1ChC2Cd3Ef9QXvA\n",
945 "H2Cy1Sp01yl0132qWRBB76HP7Oi9Y9j6AsSA3XsoOniUkdTZ6AfRm1H2bnfQgZrZ4GEdo8iuu4Pe\n",
946 "06D37uZ6bzmKG0S6ETMRvxafItpoH2ZgD5cdnAouMllrUKxVag3GLXUdtTWzZ9hsM2bX1HbUWeLT\n",
947 "6g1Gf6+8tKmlxRJe0VFdE1vRHH2xquqpzulVBms880KVCgesDM0tnVZoMFxRa89X+GFTWygsVxjk\n",
948 "ucoJH/crTsNZuVlvF6t1qvpYGaL2vMVAZ1levKb45eLXimUEq9HiAva9iq8Ww7AlBhDaZhULSFOb\n",
949 "khIbCWWrL4QjvyoO2ktc9iKjw1UU9NRWlhaWGd4pNuVbnSazz+3M90QqzGV5eY/ltZuIXxopADvF\n",
950 "1RvrXfWiUl8aFv9nCFPv/4e98xBB5vEADVeR9q3KSAHoeeeYkpSSEfNEUvbVaW4yzDR/qsWXfG8a\n",
951 "2VhGPxT8xlNJuOT74sciqky9qdqvOqw6pVKxyQMsYdLCku+rPmZqWVKlKlWxgfg5Du1Q7YOmNqqi\n",
952 "0t2AtOSfiW9qSMaEP9gQ/iFhyPkmxsQy4WPG7T2cX/gEUUNOF2P5Vpg3gE+b3GNNsAUc0erZ0Ak4\n",
953 "zYrSiSKgwmK7Qg5lZ9JSgJTKhMuYcGdiBYNuGYJ5t/uQWzOQvOWecAv0x5q0VKTkDyMgz5eRzkG9\n",
954 "upVTtIagaNVm8Ed/RtpU/9jw7VyIUlYMThVVOisDleIwfKAISJWWo/2jwgWUDNDDF98jLBdUwwpE\n",
955 "0MfCZ4JsBCjJIFYDK1iKyzPmufLEYamwhJMFSlQRcmakGIJmKXK2ykNLWTX9MH0OJxAIhoyYmfDT\n",
956 "J7uBxaEPFosD0JR3gXwKYkPaGCG/DUu1sG18Con8KtQ0NSq79GBrBchdEKr8c818x4yX0JgtZq85\n",
957 "bFYNSyuoNhDkLC0UpjYIO69SgVSQdci13uU96MUa4L3sveFl3GUVen0+SBt6eQvIEZB1AKna5Tvo\n",
958 "w9m+y74bgMldhRyv5WCIr9XCrZuqHa29UHutVjWAo8NSL/70Sk4dvAc2qqu11bLX6vYj1T3lH/Vf\n",
959 "8F/z4wJkWvf6VyDT+hX/637w/ecxdK+il3rRS/up/DzIVaj9UVhDHCDzQerQUVcReXW19HNEVU72\n",
960 "khadRslxFjOyn81rESJIMfNaqJc+kKu5EDL0VlVVayQ8CfU6Ge+u1YY88kwReSsvlo1/+PNSb6G5\n",
961 "vKAqoGszLAqXN3utRkd18Xc++vJw+5MVL4WfpJjU6M9KAxX5lmJ9lVXf1FJYVldmq6txGV/6lP/q\n",
962 "XO+qL8NKzKqKi7H5JlBsayFn5uz8Fyg9rkVYUJERBsVsgAlT55YgknZJvuzagh8iheLPAYGNbznQ\n",
963 "V2t8TJAv4owIbZbQkqRDRih9wFBJ3jJNmNgQKhg0rTdtMm0z7TYdMmnoj6VpaT16ZjNIP+seQKFY\n",
964 "2aTEenprOn4bU94sBGmzKZfHQ2APyqQkMxImZSF7g0L2BgEQrlCPGTMXippWX5gFlc6GlKTgZw2o\n",
965 "2HtNDzGW0TglF4zNMZBiM2VllNAPqv+Zs6XiYfdj2pqd5l0bKrm8atkCNeQI3mgdDuyyHLRgcFtQ\n",
966 "xRyDm+YMXutVkCMg65BWuct60IoTrZetN6w4EWmCyyFUvGajWWAbtV2wXbNhUOfSKF6xKSLcPZje\n",
967 "dTYbkqVfQyZmyj4KM/w12DOWI7oW+TTSRSTVuLXZgGh3qymknhx2whvCljeAp3/i7b5xz5Rhxn/1\n",
968 "cvgrX+ngC7Y8NK54LsxXcf8knGVr0atw9mQRPuVVKAl/tjDZz2wMZAFc4fLWZJekFAKRlqsZ5+vM\n",
969 "VYKcXKAyKA3H+B+IQHZRyQUWK9I2rVIm+Q3+iRrMV1ETSdd18gd4j5DmCrgm7n2p1iTWJzEI4btG\n",
970 "Ro0pFzYnpWvlLCgHY8YOOdbElC0sB4CkhrS0CSiLh0KPwGqx4WZzF8q2M9balBzbICKuIaHLpOC8\n",
971 "Wq+TgULL2V/L+8uHqBicfI0zgPNkrIbGQgTKJj9ovAlgcMA/Qmu+WPkJ0rR2IJMoeb3yHnY+gA0H\n",
972 "qQgmkrlkU7h2sq5zy1TmQtXuUeHpYkFdbYXH4nAa1c+UeitKSmrnNltiZTNKXI7ZLk9TRZ4ohEW+\n",
973 "sJlNdX1pSWlJscNZ8LrB7DRbPY5CXdRY6LEbTWWu/K3FVQU1pZZs//4+698izs2NSUZgvfTDsHoC\n",
974 "60p/lgMoHs7dsMSsl0FfAAg9AX3lEFTnTbksKcJykcHKUoiyGALsqpMAqvJYX+YN5q3Po9iu5AHh\n",
975 "CIwJZwh7LOdhHoU1nYBb3sllQ1HU9yjs+e/AoLsPBKbd5NGCM5D2oSNlyx8ezd2NfNAH6XK6qFBB\n",
976 "L1MKaz2ionuLyryWhra2Bou3rKjdVj+rxj2r/v+y9ybgbVVn/vA9V6styZKszZYX2ZYsyUss2Yol\n",
977 "WzKxvMXOQhYSHCclk/wLZGEZyAwkAdqGYUqWzrSkLc3CAGHakm06g3yjOEthyMyQhbRT3CkJCbhN\n",
978 "uiQkYWhoSymlwf6f33uvZDsLMDPf9z3P9zxTmp+vjq7OOfe9Z3vPed/fW8D/en38r5hw+Iotieqq\n",
979 "uKXIZy9rBFdZ4xjOMpUQHPmVWMXeE4r4eiisekxSWVU1KasyuqJdLoJdfCuHpDnsTrpnuRe773c/\n",
980 "6t7o1i3EVtt/QHs7y2HguaJU0aEi1UKZyEoSirClJkeGeBOgRVcyGLFflv6W4XkDl8E6LEBihm7D\n",
981 "PAP4rEEwsxJwwgCLYsMruCfPRJtmr0OH/Dmg0G0iBv7CUU/mJgwxxfKND0MBegZAeuRBwIZi8OzL\n",
982 "1uKV8m3kUbO9EtxglWexm+KXa/ak/7vYSlmJNcXjWFNI/n/lCekf+3/uJ5PX/jqeSZhuln4KFo5f\n",
983 "AyhI9hYK1gVX5TWARYCzAKEhs2fl5C3NmVHys54oghOeKNJpiOnCqKz0TjrpbzL0GPoMywx8BL4A\n",
984 "6ayHdAYMR7h0ZEN4KY/ulM5BPD8hGckZzoNcKDKiTCCKqcw9mHKHYFcD0nO9pb9KvCIVlxJdwlNQ\n",
985 "wlcXry8e5SCvpG/S36p8HjL6JYQ2CPBX0fbnWkjoDf/bEBkFq9+OhL3+w0igEPZhOYOfht8Fm/JW\n",
986 "SGhnWB5iGoUu8DpQVO8BjIZHsyRIH6AfTNZidaNdquU/jOG6z74M7KT77cewIKIwgB9g+omVdZfB\n",
987 "3aJsBzbOTsAcfVP5duyZEa/RFuj6u6DKKjEbt0CV3QXH/dO1F3lCemK4M4ywY10Q+wcZyoQ0Qs/w\n",
988 "2ykA0TFAD86u/oirZlz1YP+jGQCXl/Q8+1LU6yjWaORmgrlRairLOtCnN9fsAC3qZJQfIzd3wAVA\n",
989 "F7hDYxxYhpFFoUDN+rC7dApBritjkTQxwN4u8mBLLjyztKOsvbgU23KhWWXtZRsndGLfrqLU2VSB\n",
990 "jbsK9lXPnHpyTy/o9HSWzQnjuqiw0zM3AOW1s64i346LtnF7cN/L6oU/Jr2wSGqFmr+Iw4AlVhYL\n",
991 "x1TYy28Z3cvvGT4rJmift441fXp8u1Y8NsW3G2VQLaNIdxNC17opjuMx/+T4diewEjoP2Av4VwAF\n",
992 "tTsIqJWD3R2vfbNW/G+FuJOJTcG0nIly14QNmilXR7mTw9tJkz3Y4aAYd8QtIe3H9sp+6HkU606K\n",
993 "0clVJvHa0HeOa0LfWf8Hoe+Y9Rqi1OFvZOIOPSYyruObhT+DY/AsdMmNZOE/lH6CbYO3/ExS+YkL\n",
994 "sV8tUyIa+JeGbWTZpfCmZl3uiGsG1pbgRdPmkbmRlq+eNOQ3apWJhyIRkbV/ob3u5pjn4bve/ZLK\n",
995 "eOV9dhAV/jzitkRHFgtXxLOCVbiA8w64pafDeUmYkOQOkY26bLLeiivYreMQuFlgZOSpkR0FDUPE\n",
996 "oWoNpQy0aj4HW3bzSraWbWLbmRzCSqe4HDxPihpgE/GlcCVaJAruFaDg5t9jCQGHrvSA/giaxmR9\n",
997 "L5Tb53PAEZizNmcT3NBzBnKO5JzMOZ+j5jfk9ObwG87T/G981Qh1cBW2T7qR33msErqh8L2OJziX\n",
998 "mw0eD1dL8DJdKauvsFrLwp7GjqlTesR/jiy+/a5Jk5Yt/rOJwT+78PADlz5P707P5fQjktN/ZORE\n",
999 "h0PSWcCjeXLc4ykY5MICxQ4h6QhQQaQpXILEEztE7knwEuCi4gKDS8YGtpXtYqqF6VfZaTSB+RDT\n",
1000 "aJQnihc9H8vj3coR6AppK4Q0H6rsbrLofyhnQ87WnF1cGgOv5pzOuZijIj4Dng2e/iIkM2A8At/w\n",
1001 "XhDGDFiOWCClt5H/BX6La5IK+ivcUXF0qR8nkS9dRyAawT/yc1WR+Eu+ynEJNUKrMEdsk7nNCipA\n",
1002 "5Y1QpzMBjwKSGKzvB7Cp5D+sWPRJScD9TBYeSIikXkgQc4US1uhRPHQKMAhYLNJ5XLpAFQRf/lS0\n",
1003 "m17AWhWZrUMPBK9EqsKCZfwIvRyZWS1Vy79CPKKpYOuURuDYNwuBWM/cmlmrzuQda2ZG+yQ7Vzom\n",
1004 "oPjQM+G+gRgKJbTJdH9mfymVM0REhEi38WyhhfB763lqvXzZxRVc7LLO7EL8An5LQrb4P4LnPa/M\n",
1005 "iHyKE5bC9nIzEt4AyL4OOYLs7aBeIT1E7YF8dg4wtJaLiAuHmFjpPnEZ1s50+LqVXEZGQ8zLJqJH\n",
1006 "AOdpPMxy3MBJgpegkv0k1CvS67Vb+IogvdawiY836XWWzeA9XGfdjCO6Dc6tTnwX2RTBn4mbJuK7\n",
1007 "5s3N+BTfFMctk7ZOAtX5Bu1WZLPBsPXabNY6NyGbr9Q9hZhDa5s30e8nbeI/dAWYy/Zp52af8v3p\n",
1008 "iVy77bR5qgsKqj22zN+WIjkGXFHm73DoU2/xFIlvF338VmG1x2r1VBdm/lYmQ0VFIdxCf9n8T7mB\n",
1009 "jx3ERUOca4v+65FIpMuwvbzPtAanpSnTIfxJmmaZxLHGrjLjzHi6mX+5mv+MxrFbmVr4F3Y/r0vP\n",
1010 "aF2SOZny1aOlp89oL+MtnjFdRpnjaiDNInMoGFeNN8jPFsrimVJ1QiEfK16jsQJaZUjoEGYKt4t7\n",
1011 "pFkLePnhOAfSM7fh8JAtiCsDBLkDnUGTNzMMn0PpoNCERe08SG+tkI18Njo6PCqPDtK0zIggPQG1\n",
1012 "tRVwH2CjosAqo8SAoLaoy9Rcd4cSC02M/0JRZ68JyhhGYFbpPR9+5rP4ynw8LU7GOiOgOzRXe6pD\n",
1013 "1TyrjbN4BrMsqU5+cydu7rR0lnXymxdYUlP5zVNx81TP1NBUlHsnyr0zMwAt4i9zUWYAauQfGkcH\n",
1014 "oEWZAajRkmodkja2wjCIlxFAGQFLoCyAyJGD+HoCL2YCipngmRCawJNNlOwYTLVaEIyJZ9XNf9mN\n",
1015 "X3Zbusu6+S087VY+4fOxMHUz//nN+PnNnptDN8uOV0sg9PEj1lVDlZSDoXs1Xtjy6w5UU/BCKYIf\n",
1016 "TunSiMMrXme0moK57pOHLENmyJqi0qwY2K09qD3OG+zA8/q9+sPwuXveuNd42MgvducdzDuehwv/\n",
1017 "Qf9xP74K7g0eDuKidm/t4Vp8VXew7ngdLiYfnHx8Mr7q2dtzuAcX0/dOPzwdX804OOP4DBWNUMSc\n",
1018 "mjkOumr00XzCd5/0uy9i1GILmqurm/EvWlDVVFbWVFWQ+Tt8z42/+u4Nv5JHsCPV8Xg1/pU1YaRr\n",
1019 "KvM0YbBq8twgnW24wReKj21YnC7W8fFjuqTC+DGi+Ehe14y8lYYJAd597yn3qYcUN1vi+JetJmX2\n",
1020 "fJk5vzHC7v75z1v4/9nNwJ8LCmciyo3QGLJEMiBSGxH5YzlKfrEGMtek5TCYFA2wy5FareQpa+Dl\n",
1021 "kw/USHbRkRRld1kNsb/o5AMb/Mo4BMwb5INpuaPcyuvjUOpG/rxUs5/f08KWPv10y+bNVLcg18uK\n",
1022 "FL1M8+nxLJI41yWVDPEsKAqSopc5QjcIbpH5kAlu8ZmCWRB19oAc0GIs9UMmjgXiDN0onIUcYiIT\n",
1023 "zgJnpWKW8GEKAlookSyaoXwpQSwQtSLd7JviE1dcG4zCek0wisb/fjCKj19jf3698OL8XYRGPmID\n",
1024 "4iBvnxPYc/IM99zoRCuHJzPI5G9PaLdpNTLt/sDL2te0Z/gYorDuG0MDZ4yXjSN8DEmbjR6juKLf\n",
1025 "pKbVvJ+PjdiHMfs9fp4KyxQ/toGlVmzwnCm+jA2eJ4q38T/9Raor0n2hzNhOZB/X54lDcylgV6Si\n",
1026 "cjKVKyItClQ3GW4bInMkCsdXYaEwH1Q379hGzyZwLCE9hXOHO7EttQlgB/PNEfdJ93k3NKal7lXu\n",
1027 "de7Nbt48tsOw8XEoxEuyLPAna87XQCcgthsHeBO0AKK5OUzRHlDw24BlKGw94CHAFpx0rC/cgs3C\n",
1028 "ZZhBTyF23Qb3VpBGPoyEHZgzl1Wvrl4PfvchFHeq5gIvrnIcOx5vGmqiJ9DqAlmNXO1gtZk1RUFP\n",
1029 "oa/aW9A2MdKRM03rbewMBCdHSgp81b6CLJfenKIJAV9VXWkk2VKfE5hU43TVtvPBrKYi0OBD+6gd\n",
1030 "sbA9xLE3gQ2TPTeZ/KUvCyNYfZuxNwV6dn6NOOpZhnZyB5UsWi5TmXJvTFtJ5mQ4cNUZDtwxzeW9\n",
1031 "DLP1mMYSRmN5tHgjGoscP4Eay8wQux45H7WcseR8snlmptEYy0cbjQNnWw4i6cdL25eNPEhBB4mw\n",
1032 "cjNe2uN4aUtcK2FOt2nMCwThp/QIgF7lesB+wFa81Ffdp/FSwakkXUIqfD2knWhOu3FsuwsGvHjR\n",
1033 "2INH0yJLlw2AS/Qxs1soXaTtmQLU1o3ankI7I6LSTajeOjTl11HCYcASwFrAAOA8YPP48unYeDus\n",
1034 "a17PNuztaGmrqtehOm8j4QSK3g7A0Die4NCRp1HmZld2pFI3Doy2PVZwo8Y3yoY4p7iWt75QybWt\n",
1035 "r75SHp+e4auhuxRf41tT6pC0EcYVZ9XvwbjifrWsCcvHbUNyOF716JHWYqjzZ3MyjYSchIzyAlGt\n",
1036 "xDCXp9IA/8fqWlq+3tIivvLOO+/IZS8aeYDtpFiCOuGv5WiC14sZSCzEcEwZSGkOaQY1/Es1RUnv\n",
1037 "1/E2+lxONpZglrGYQpUjCGEP68NKb1x0Qv6NpknTo+lDmPEPEX1PrynQBDWqFYhBiH/f7uiYfQfF\n",
1038 "IkRNeT25jHYqMtrCnzKNo0VoIurLathYDFHUdmISkV5QgbBKRQHbidmNJvMXdDxVy2ubhMSeu5HE\n",
1039 "tIrEeBVVMOfsU6GKcK3Xq7DDQJXXwcKzT4dvEIBPryvQBXWqFSyi42LWedmdSu0zgh5f/+e4qAZe\n",
1040 "Fl8Tz4iqhf9tgdNLp9c/hnpOPkv9n74E21UvgZ1W2gsTmthp4Yf0HLeDgRQRVfhAda3saRMzDbd2\n",
1041 "6KbkSS0JmsyxDJnWoK7i0CeK2saFuUGW47iyV/KnJb/1NCwWwMYqXsYq5gXxZcUh/3pxL1ElOfgl\n",
1042 "akL+oteI7hMlBrk8IsuDZDHygPBD6js9qM/LIrth0TPHRdu8cQkupYS/xfPewZ/3OXreEGQNV3ox\n",
1043 "OwZIT1Dvzzq4ZkVKbma8r99B/Rz1nMbhVr4WdQnbU65Qv1N2b3RZYMx/CPYcZzC4m2E8AM8e6dHC\n",
1044 "cRSq1/U/pIM1nKVpDXQWdh5T4U+0tF7utzCZvxBbkk1opR9gFNeCZJqMK5vpow2mxJNxT6OyIbsw\n",
1045 "3ZjfxZeTiteeQn5HWztW70wVaxN17sp6T7HDZCr0R33WdtbuSUbm2bzFVm2bpmTCxILhDwX1uLil\n",
1046 "E4V2VSNFLpUDlsqRSrNRTJUApv+1yKXtQ+nF7fcjBoGlnd+WaucVD7cn23kTf49fp9qG5LBDwUFE\n",
1047 "Gq8bkmbV8U/NPLWZ/61D6PPUpJA0axJbAa19BLENZrYuasX6opWntfC0Fn7nJEvqpiEpBnPXXtht\n",
1048 "ngWEYTG8uAM/6VzUCUaETixPOl/ozOz+/A/CnBZiGzS9JvpElDc0rwVPchYWocloG9YTyRCM5qKW\n",
1049 "VIT/EMEphYglUhZR8TVhs7yf2jKIIEqTiL4GvvE3DG6qUTlU8ib/1cFNodcrFvTXi2yaq3PfMLIp\n",
1050 "+IPSOfpCHA40URDTa4Ob3iCuaRpxTUUloKnG6rg2oClI7saHMU3H8ruh/NwwkOl5QB/Oby+SyxDO\n",
1051 "8jpgntsIOAfoBdyKXa5zgCigG9AFQrlzgCigN4HFEeSXYbuTHSmkGB68RzFl5rqWdcqo74QShhT1\n",
1052 "oTCk52JKsenupnlNXHxN8Z54X5w/zgUU2YSCLgCmJD5DQNHsl3zOozWTDgYoDu+nhxJlwanO6nKb\n",
1053 "tdhrXdjy7Iyp7eEvtK28ueVTA4guUeUVu51Feepooi0e1fzzgQM0txaINcIp8SJ4L9gjktGJ9bvs\n",
1054 "BUu80ljgbuQrSJzGa8EZZg0V0C6AtAjqTAjkcJetIzhUNON6m/UFfg1jC7g0pVuLZsKfJFnEe6Zq\n",
1055 "CLYaORRSj85fQKIj9eLUZX6GlCppiuV1583LW5q3Km9dnnYh/2zuNs8zLzWvMq8z43OTrcfWZ1tm\n",
1056 "W21bb6PP9h47ztpX29fb6XNBT0FfwbKC1QXrC+hzIbiSlxXC+oLyK+kumVeytGRVyboSfI6WTi7t\n",
1057 "LV1SivBeWt5K6LSoj2qGk6F5qNk8qllTXk9eX96yvNV566lmTeYec595mXm1ef11axYr7C6cV7i0\n",
1058 "cFXhuuuWjLCo80qXlq4qXcdLtn3CblbaW1joxT+fuchrs1cUmc1FFXabt8gsfqWwoqIQ/+xed16e\n",
1059 "22u3ewvN5kIvrTfKR95nf8PnrnqxWzIjIix5KyEYLLmwgEpWr+YLIjNFh5XN9aRFINQ2W/rLuHJl\n",
1060 "tqTqB1P1ISkJy5BWmHediVCQ8ch9kTWRJyJqZdgkr4/M9EYhJMhUpM6ueIHBPg2H6jhXNciphpBU\n",
1061 "YK9THCoRzkTE/NBfJF7BfpFvSHrfJx/r+LEN+n3olEPCf0KPBI9X0vAQkw/6DjCNfLKX/gF7i8GE\n",
1062 "1bQOWy0P5j2ex/8M5B3hf6RfocmewPi0z3oUrRXBFtOnnBeg7VPIhp8U/BIhG45kwtZK57L60UnA\n",
1063 "G3BM2AnoqcCRIa4uUlzZQA9iBFzCAVYTzCNexy7U24BGuKycphhw4I7hQ+Q+TJCrAafoCvXewnYi\n",
1064 "2vgxdopd4EsfaQNWKAcAYApL42g2+1jSqjw8Q95RPNSr2ILfn9X0aD+D/DUvEbjGWDjSE1CoOFR5\n",
1065 "a8UuOKRMwYO8OfoMaRgXw+kKT3EOD3AScAKxISrrG+vFFSwT+NgJw45rSKj9gUAmZo/TxZLmBp+V\n",
1066 "Ly/q6jrq2zyR9orowvJm+03V9qDHNrEyaawKFJfUTyqvn+tid5ZU6K1uW3mpwWLoaPDHvJaqhkCZ\n",
1067 "P8dWavd6csx86JpQ7otWWP11sPegdk1+AP9GvD7zFgqCXpDek900RWHSyIPsP8RBwS7MVXkkfye8\n",
1068 "pDp5G+/kDZC397OyaXt/Hr/OUcHGULLTH2wmzB1MzQ3RJmOnJTV9MDU9lH5i+rbpIrlPSVWdfuW+\n",
1069 "2sFUbSj9aO3GWhEZpyYOpiaG+hv572ot/TfxW7vpVukRxFd6B7ChGyvDenlLcjbvI7MRGHUbHJqS\n",
1070 "9bPlJUJ/DrsiVcyul23XpTX83fTb4WUsJzlCqdnkMCVVJclot1H+YWMoVW/pb+Lp3RXEKroOBT7Q\n",
1071 "LXcgcofaTFyfmO/ID35n1lP7EjYyDsIg+yAmvFdghQSzJGkTYB1gB+Aoeedga2AfIIo5cQlgAABi\n",
1072 "ivS64Gb46dA2AbZJRXlzYOD5ur11h+v4gnFLZCfOOk9FLuDPgcirCMW9C4ukJqwDd7bvx8JwPoJT\n",
1073 "3YUT3j9N5rAcJ94HAKdm4AqwG3B8Bjx+Zh6YyX9zeiZP2DULTXYOKgvQz+XNOzgXK+WlEMG3III7\n",
1074 "8PTk0v8t/ahBzEEIYT+EsB3PehJmWevKN8Ms6ygJBA9/hMNA1DfZ1+tDWEVfRgD7AFsyZvbSBsDz\n",
1075 "kMFAzRGKLE3RrEFXcgEj6G6EIT8eeRPP/ndI+D7gTkiBREGPPxXy2N1+EPJIIGEp5PEB5LEMorgI\n",
1076 "ODgVLhQzTs7gwtwxY98MGJRBDgOAHYDtkMg5COMI4A2ACmKxAyo52OCJUyq6MiYLgVidalwX1+qu\n",
1077 "39FlY4/R7v7zkgkOj8/SbnI7TNaiCmvzFo21yOfyVrv0oYo/r46FA36Pp7HT13F3Qbt1SrW9qsLh\n",
1078 "L9sQiCQm5BYVWErCrd6OBWb2VWOwzOFx5evKNPmuYrOz3G3Tuw/lOm0mZ2mpvrLK2uRsm1iXdLib\n",
1079 "aqpvqrI1JcpCwdyCQImnytJhaw03JO06W3GgKJAI2mMBrG/auJ55guuC4GB7ERxsijGOHLjENbpz\n",
1080 "/YJW3rO+rB3RGhbK/HCfKZoJDkhMXHM1HTIN8mVxvxEEN5Z+M9dcX8CEowQKuaxwtfExIC80ntWB\n",
1081 "r4zyLBQjBNqtqcnUY+ozQbvFcltvKjAFTVx/HkfTFoscz+ykTYZS/R1lx+zjF5W9hiiHN8n/aV9G\n",
1082 "3yclu5+pwFQvxTH9vAYAAYq0FYBIVZn9E67kqkPpVvVMdUY1IqKrqx2iyK6KgckCIw2ZR+oxX0eJ\n",
1083 "fnPUZInP0WBdlLRYXkG54V+Ka0VZw8GXGaJ66Q/QY/QqtoIxL8hb2JvDv5zNvMM72HfFxz7+kvhY\n",
1084 "+2gMTYpTXct+IJUEsG4dwwCRhFfho4DnruaCIBqIN2H4SNaP20cJIWaho24cRwhBHBCZhyZ2CDot\n",
1085 "GscGgWhsChuEndggpPPI+BW7PPz2UvQjsjDKMi0QycIxABGQn8J8/SGgAAvuHMAHhZmVx2GYLR+G\n",
1086 "9+x5wBuAw9CO3gD8AYDY59IpjEgfAo4DSG06DtiPEelVwMUsUzi2lgderTpddbEKZMvVfKFxtPaN\n",
1087 "WhxZ3Iq69mVDXRzNslWczPjppLVOJ9gqfl+oLCvSpzwXcHx1CpUhb3DyAP8I1TqdDb5+AZU5TUNm\n",
1088 "hp5C3mLeh33uN6rerhKvCbsec40NeCFH/rNFVn8mJojXFAKICoUQ4jpEECzG+4pm5NfsXvGkoBL+\n",
1089 "VfHPuIKGbBy1mhJEUmCkK9Cvjapirn5fvfs1jhqNJQvBOtorLBFWCmuFTcJ2YUA4IpwUzgtG3vQz\n",
1090 "rKS9oBI0gZ62ly1h6C1aPpKzfTBbewPdZQu2AYJik9gjqviaF9HE5XN93mWoXcEoI92tmscrlN6p\n",
1091 "2q+SjX5a4yzUnG8TT9jJPhYd5p9Ufyn62WOKT/sZ4QWhWXoBFtqHALPA+oKABWnEIUQjoO8WGaDe\n",
1092 "GUZg274ICa0G2XqWCXN5nlV8jeVhd+1hav1ofKKz2ahEENhZTLKz9Iv14kIlQohMqJiNE2Ifkhaj\n",
1093 "CyTt8s9KFfdLYk8yjt09g0ZRqgYPRao0JIceIoUCNhqMWCNKiVTJYVUrayWrpb9AJr5ZD7s14jm9\n",
1094 "BKqsw7YT8HA5j1n/DxTJBVU4AnDBYe0Cri5iOfAWYCfa/YNo5ofdJ3Bg83t0Sw1ObZwIjTHPvdQN\n",
1095 "ma1DKedRyjrAryhnwO8BGhwyHrGBidc+aD9r593OhsIoisz5bDlbAQc4DPS5l7lXu/ltFISjgJfE\n",
1096 "vNaIo7wxIscwkefdMUFMdu/8ePjWJYsX28O3TKqdXRqyN3nroiX6nWzm8LstLczWMi/c2xYoLou4\n",
1097 "iv3NycLZFGeKj6OTxD7BLZzewzQ2dc1ogKnMGx0TZwqmmJJFIJNLaHDb0Cjew9MJNvzAthhyPaR4\n",
1098 "DtkpIIqTXk/hoLQmE8xcID+gzG5bRm0kJhFMKYVyhBOTpV8nM2XZBrG55hykyEeWPgQNXg3VZzlg\n",
1099 "A2C+ha/yBqK5k3N7wdONm5ZZ+IITbLciAlDRqIKwvDSGkPwiXGLxdbn5hWarz6yqnGirqnDefnv7\n",
1100 "OrZl+D/d5fm6XP1N1tzicIAFWr78ZdlefKRYTIjvk13Ccq7zpl+oe7kO3HBD1zUaHzUVh13CGH+8\n",
1101 "64a1IbsE/WeyF1fMES7VsDH24LJt9hTALsB27Pptxq6fbBMubcKIvoM2u7JRHaZmQzvsgj68v+BY\n",
1102 "AXTm0iNwoSJKnyMYwrHiTx+rPoWDv4MZw2/pVTpz3IyZu4m8gshYklyDUPZTKHuLfiesIDabdkB5\n",
1103 "3YGSyHx8B4qDu55ifC4bO+yvPoYiTlcruZMB/LUG5tZPNDB313fVZAzMneHQBPunGD+I9cMbSgNO\n",
1104 "/TgL8x+hb/h533ibj3Ex8XapLKiqgX80he3p1/Ilxn0Kw8dC4uuAZxz5IWH9J8WCZRiDYiHJHaOr\n",
1105 "oKW/ii+syiz99WplaWHh79iSGeHIeRojHLNUyvZ6KYuFtEGjnGAMga8xyhNyo3zQoKiCbkY8GFWV\n",
1106 "YOVJVYWkxXweRcCsWvkM4QQcdrXYy3odqg8ZbDuxofU2rh5E34VXU3pr3i5sJ2hwxrAUb8fBO/PA\n",
1107 "EttK21qbSj5sSC+xr8Re/0+gI96KnQWdy+XiSwAKV+XikD5Rcq6Ev+rekiWgwDiBl7oSgJAL0o+z\n",
1108 "jBjnAVrsPCDqgrSK4i+gka0CXMDh/kVspbwFOAatSQ+Sx1dh6XMMmtIxMDh8OBFt7xQeUI8HfAMP\n",
1109 "eAGPdRrgxlOuxgNuwANuztuBB1ySOTpJr7Ktw0BVgCF5Nfxh9K4CPM18PN4QoADPlQMYgp31CSwl\n",
1110 "5wH6UOHVgOWA04AcPE4f6r8asBxwkQCPcyqQeaYjeBwdHucoHuc4Hof4Oz7iYItkwkmM93p2jYae\n",
1111 "GBvty/vDSk9zdWHXpAmdztay29uqpzaV28prC1SlDT67b9ItdTMeKJme350sjVa5ShvavB72ZJ6n\n",
1112 "wdvcGvSXNccKQl21JRMR0VhbHm4pr58+sahzmitSb6+c6AnGKszkD107clblVPyhk0KnyphqC0l6\n",
1113 "EABW1fPekPNprtCgLh4kJ0bM9Gqa77VDSB7jD01ESRZsTKaq5H3IikH47duG5InlBWyQtML0uz7j\n",
1114 "EFbIC8LKM1lfJW+bINg3V2eT9JHf1jCEfOI8hzhIEtpSbXyUbsPhk3QZyvRrgMWAJM6cOobwZeeQ\n",
1115 "tGZyZpzOhtsa6/t2td80+a0lyW9a/1n9pkvoUOs+NIQzAEsJ7YFaQgMzLYss92HSMls8Fq5WlhBD\n",
1116 "KihRpcK6EgrmgkEBp16tCN5baWlF+a9iPd0g59IQwglZ49CAudHTGGpUUSbtg6l2WnB1DqY6yail\n",
1117 "sYx378llvWVLynj39iPm8FyEQT1HvHIAJ0VFBZxEu+0F28DbuOoGucB56oY4fDkNuAQ4hvO1Juxf\n",
1118 "rAbsByxvw+DStqsNPtttp9sutsGPog3O3ZD9euxx7G8/hj2O5bje2r6rHbuQ7ReVbaAVUi9O7NZ2\n",
1119 "kHN3x5GOkx3nO+Dc3YHq4atVgB10Uyfd1Hmk82Tn+U7chLO97s55OOfb0YnhAk+a7i6bB8+7GK5P\n",
1120 "eS/A0K4ADzqfJIBnpEeeh0c+GRz7yANHmk42nW9SyQ873kO8UgkJM7bvakcjll/VdW1wJH921JH8\n",
1121 "4/6CqkSVp6TSHnInq4vClY6Qt67eVdVYGplmixhrq80lBeacgurykuh4X/P7KyoLKmxF5f4Sc3GV\n",
1122 "29toEPXNgZI6j6VqQmlpmdFWaDIWuczDJaO+6BWsiHXzOa2e3Su54VpyFotLC9ayKcVSmy+3bKGM\n",
1123 "Sbf0Aga41grZBYRWfRlTbqm+gjjj6kOSs56uKkAugiy4Mg2eqzTOCUT55OCq6GYe3gmwvjgDYHke\n",
1124 "edKTY9GsGJDDAKjg9gPzkzIcxeTKN+ViIkyFh2R3PCcLUyfAotnroU7oDcEd2s87gd/jD/llX+hK\n",
1125 "ayNOJWW6GpXC6HEyw+OR1tlddj78v42hfh4G/RMYX96G0noK49OlKrSfydjOCVhjsCA8RbOGvQA/\n",
1126 "+yPyIcIBygBRmdMnqs6BdpFIil6to9H9v9BAHrtxe7BPHNsexMLyiiLvp7YAmVv3pJhkbvF7Qolw\n",
1127 "STILfAQ3w6lHpuETvpCy42gPjzILuph76Npjb3s2bM6A2eAxhAw8TaPElMWXJXx8C9EulmySsgxG\n",
1128 "KQ+RU0yTukfdp16mVisu529TSBUcAs/LX5q/Kl/D74nZum3zbEttapDZ4qR2ngrM7PSVuls9T70U\n",
1129 "Pz+a+fkAwnufxwH26nwU0Zw/JX9+/vJ8NYpTDuPUC1XEQEpuqNFYRA4T6Kf3UK0yOT2u/Mr8/Aqz\n",
1130 "y6Gp4R/LnPyjtcLCP4pJm78kPy9Hb/bY7JUl+WZ9Tp7HJusBLKiCbUme4GTbUvkhSa0BFakSbZer\n",
1131 "SSFsgW0kWwjF8oyUqkfhm6iBFizNhNXGNkBZDtemFF9/RasyykTnTJknFaJwaQ2WLwiqKc0CMXH+\n",
1132 "KI+jmeLGclU6hNe3puAa9g/rEGzDNYOw53aQC52YC0164Lj4pngJJgbwdEo7xEp4D2qV77Rvai/B\n",
1133 "ccWhrdTy5IcheKP8Xdw41bjAqFqRThinwQ/uTzAWMBiLjDU8UXoYxgLfMcokEQ6q2Xt2mDzYLfYy\n",
1134 "O280FrKuMjyv2qs6rDqhOoeoVRQ2bx2gFxPoETW4bDFhoAm+qjmtuajBq0YUEdkfKmmQPRVQS/77\n",
1135 "+Ub0UURvTb9u/BUqhRRYSqu8FPgzYiMmD0QALVc91yL+TeBvxJaFf/VXCz7+zeMt69kUFmQLhrfT\n",
1136 "v6eHX2Et0eGn2JIo/Ex55/ktHzPL2FelQnAvLabVR8bcBwqrXk27ptbBlDVE72TAbPVYQ1bVin4L\n",
1137 "baj2e1RXpD956G6ZNEMYPSy9egMJ4WtBlPQ+0X7aidHjACTzvoqsaPpNXA+wUDpfOUil8h25sLt5\n",
1138 "GEvu7wOIAeMpAALLY95HjARpOdE2QIqIKsVf6ztI6KOlMxbMR7O7JG/mX4IdxDKswuiUaBVG2T8A\n",
1139 "KkG8shbrZOKOjOLjKlytxADYDObIquLmYvipH0b25wDbAUsBy1DafMBFApT7JuA4CgfttrQEBb5B\n",
1140 "myfOTNEoK73KtQ5GtmB1KS9vZPKxxTVMQeXst3yadFvK3BaHv6E4Ot0w3fyXt9TcnPAWBiNFZ9gD\n",
1141 "c5jH4gvWFpTUlVlbIvqZC1x1XXVVnS1R90+VebKc5slSdpfMt/UCOU7iGc+Ca+ezUW7NwuzWiv3Q\n",
1142 "+8oynZJCQSu2htdjx3o+G7QzhsCtMkUWefdKGqT+SpQ7/41JsTJEiOmt6l0wg72E934RGtIlizLj\n",
1143 "SYux4WSH5//vcaXB1eTMTlQaNFbiGBorhRAKnF2SX2Hv4jXJ8kPtHM8PVQijjrdR1nlo/KP0WR/g\n",
1144 "isJGUlkghkrm6BwuR8ARc6hXsE+gfmLdN+Z7YuU3InmSY5lwPR6c7x7hB1KRCe60RUR+2++WObhf\n",
1145 "GMPBncLLGgSMQG/dWD5u5ZLZrMkyKY3ttZKK2JOkl7An+wPVW4jhcUlFIVz67SIOhbj+gsXI1NwF\n",
1146 "ueKK9FTDAgMX8iraFIHxjOIPsg7tvw9dqo+vKYQ02PXQArBlsip/HW7B9km53y9zuvsp3IuybS6z\n",
1147 "vbOnxhBsG0vqKxWK7SzBNqsa/jjQUuUgiu3hb9ri7pERWU50rn5C2ScGH3Je+v6yR7FkTpYxiqtz\n",
1148 "zX2fo/sK0ovK7uP3Ddzve9S30YfgX4j6oHCdyr85mP3NHfSboPQCF/XAa2Vnyi5DFyHquRdgbGJu\n",
1149 "4DrKaw1nGi43qMbnMVruGspDJy2qyHA6IC7zX7P3R/ZynbUI7v2aEE3Jg5h2GbaWQ2Tj6Sh3lLP3\n",
1150 "h43TGmgPlMPrvH3omGaPoGbqGmXXPweNHCqt7EOHNj8gx43jwzosU9WMepxAi1S42w/IUfl4ZyS/\n",
1151 "ci3gvYzt9Gs4VwkD7sfETyT6tA54AhDCxxSuLDkZ29pxXgvZZqYWiGQf8cmko7B2364egDn3CfU5\n",
1152 "tagEXaStUqEPvPqyu7NqxWjEsz/A6gQRonkjRHQz/kenduEPFlniinKvKmLj/zHn1H+e+S3xW9PY\n",
1153 "68Mr2VcERVbiK1xWZvbkHr7s4bJS0SLSPCTdj8F7FlwQzprBusAfmeVRVbdj9UMcApsBJwC/Umzx\n",
1154 "+WJIoyZjhjcxdLwD0+etml0wfV6tWa/BuQFXzCG1RZnYjDDjRqcCAbNBRWulPAs8RGT+7EF0KMzB\n",
1155 "0hOKodpC6WVAK0zWnsOVBVdy4KxrKPUz+9ASM9G0+jqkNZ8tx1b4g7A3lqPW8Nb6CyaTWKsGJY18\n",
1156 "73fxCA/iEeZrloOPZS1tvAEoZNEvKMgMMVvzNZhRIHagJViyDBn/k2LN43qisdMo09lSeIJ5ZJIG\n",
1157 "EhcKOhiEGIib8BQmzzewiRLAhkSAi95mi8j/qWjVo7rtHvGLnV8U75nx5NQviF+Y+iR/k19mX6B/\n",
1158 "tezR4Uf5m2TUcX7BrwziT2UPHqxf008I22BtdQbL2FmCTLjAV7J78fLuA/wQQOGeLHAoFoeSprCY\n",
1159 "FGeJi0XEctKuSJoR0ek5MRPPScfnTkz/r+FZZsH15zktnH9UY8M7aIbS0Db4wLgAMYkOao6jDaiH\n",
1160 "MiSdK5KG0VBgmoWye2T6rO49GHQKENAcwJtYrCZ1oDrMBIJTLxxAyK/FOkTCGUqaERQHca3kkDm6\n",
1161 "hUlTq17mIkPAHO0KJRaO1JyjCFx2rpRm4rAMSpBk5lcDLxheNrxmUC3McG8tlG7DsdkJwzkDkX4k\n",
1162 "TRtzn8tN5crBQ7V8wpuVuzj3/txHER8SjkeSBTy6IcATeJm0LYZYQRnncATMGHPcmGmoFC0IDTUn\n",
1163 "FwFUpd9j8IgCenIQQybnIiKJxVB7J6ALX6lxpRLB8SzHlqoCgCw5jbU473URVQesi+VQHrIpgKRV\n",
1164 "5ZDujWM2tEsX2mUfbPJOCRfQSpqIjQgNwo8GgUhaA7IGp5KDmkpVcBt4A68f/EhSAQAOIFIVXteU\n",
1165 "bISOPjTvD2HP3pPTByISP8Q9GfAHyPzDXCxHTqLsVcI6lP02WigqI92KZ6HYCyexwF2lXQc+JkhD\n",
1166 "WpCDKJsRVywCS1ud9192L3jsC7d855UFz2ye+9GbL7zw5kf//u8Y3ywjFnaC94V8MYklHW/wa9Dn\n",
1167 "t7EX2Mvo84vwjPdm2UT4OEgDXNZ9u4/iZ+JqX9bD+wTgV4LiWGO2IEyUtAUrAzPGv/QTOdvwpkZo\n",
1168 "8Jcz7IMT1y4K4AP4KBtio4micljkEzmu/1EM8UuAKwAjBrZ1GWNHaRaH/nw+EDdhb/81rL7uA0Ab\n",
1169 "G7MazbQoohREKDpBm49aoM7S3vHPcSfgAcA3BHkhynVKraXfKF6RT+V+byFtY2C/cEw4hdC41Dam\n",
1170 "4BcXs27tH2JWpfmVGqEOAFd0ya7mTXev+jAmtL2aw5gGTmrOYyh1ogF9iCPWXbCBbLL04CCQgo9c\n",
1171 "yJ4GHgCcBvwRkANpLcBVDwRDUsjJh0XYL1CV1wGHAT2AQpwknNJkFstFxO6VJwudKy2AUwA9cp2S\n",
1172 "LWRB9jUdB3wfANrYGB+FZWrnGG0+xFSRD56YdcnRdpPZY9Y5SrxBc8WhObPZX38sRZOiJmmoDS5g\n",
1173 "b/J1DrVBWuf8TI6x+BBWOa02WuVkvz+Y/f4O/v1UPizaXra9Zjtju2zj2jDuTntsIRvvQUmoURww\n",
1174 "dFa+XPla5ZnKy5W4B5RynspQJe6pZATyQoqNDPN5vk58RShglj2W0Vi+g3K0JOg+96Evi/K4zVMK\n",
1175 "hmgelCknFVerxTQdk8gEixJ7IndI5gtczKE/h99kyKWgEltxUINIxOJCOURFyjQo5VlylZ/ZlOAP\n",
1176 "Y8KhG6+2N7baKa6ZNYRFvVFnV87NTEMgejDCN13SU2r6cf23cCQKPWXgsP6E/pxetTD9Hf0emCno\n",
1177 "yI/eSsTDdOYs7aMh5wRGp/McYo0Bb2NEhe0EFcJMZPzZG3+re/oL/37rv/3brT985Gndd77T850z\n",
1178 "NxujrHf4e2zu8O6o8eborl0wyxJcHL7Jx5gcdk4SsHV0H5rbZQB8nSQPb3jyglX6BgYZiqb4AOBO\n",
1179 "rEVgLSIq9lSIZ5u2Mx+WchHWwf9ItyDp71k/bIozgXIhO5nsAu9uUMoFRV2Rtobr/+kW7XRsAyxE\n",
1180 "0j9p/5mPmAOyHRzvus/gHd8D+FvAIxhVp2jnY1QFtRwqyVczulAaUxxoTPBm4eojhQGHAPcDzmDo\n",
1181 "fgJwnyEz9IyLbpt14NbLx/78DX4HY/yXhScxxr8P32G1YBd8fCUrD0m9gJWAc4BXAD8B3I57I0KH\n",
1182 "MAccoypLv8jz4++eokj+ADCELaUWzXTNbRrVijQimfNh5h3Nn/ifAYOmSFMDptWHcOcUjbx1gkUg\n",
1183 "8XDBso0vtSBjZQVdoA1CjD3aPojxdJZx75IWrcalgSUbVzcayZhtw/CvWTFffuUPX2F3sO8Ob2kJ\n",
1184 "s2UtvE9Tm6A+/4txNs25ik2zf+R9UUuxjwJsZcobklq9vP9o1FfgasQX33zeQMx3c9I8y7zYfL/5\n",
1185 "UbN2ITko9RdmDpzHbTVlQrVQUBN2heKZyKfG7ytPSZsQimXeOvI9QgdYB8BKIx3NmYxZ6yO81B4s\n",
1186 "Y5oBGwAfAXqydmMfkd8aBqGPyGsaOwwgy+ZS0zgdTv5nu3MAJEaaYkcxPhUPgM+RfG+W4MxVi/AA\n",
1187 "fdhLyQE/wq6yA2AozC1zl/G7d/kPgMGxEKpjLgKK9AWWwZg9J1CIuCKI7rWQIlpDi6MIYLK/nBRF\n",
1188 "LbuzVV0P/brXsQQE1X0oehmKno+QPr2BJTxHNsYIgWxlx5mlTRKZM95RkZNT0RHP/J3+ZxPz8yf+\n",
1189 "2XTlr/i1Sbctq65edtukzN/2yff8VSLxV/dMzvwlHculvOsw+/dUZUh6lI/K/bkqtOH0Ws0mLIdz\n",
1190 "SeeSuaUtg9JKDLFLER34pOU8ZsVbLdhYedzyLcvzlr0WNYwCQBpN21cbOZCBO6jTB9Pf8jzvEemG\n",
1191 "siF43fGLanJwDA+mwsomJdmmZFqOm39wk3vHBLfs3pGawJc07IqkkRO4zs1Vtvdg+SXoLfAnM8lf\n",
1192 "mELSIqxtKQQmIiEh5NF7FuxhWSyWMgvvrW5Lvw2GLu4J+IEzlD7kHHTKM4KH1KYKOkUOkEJfTaPz\n",
1193 "KujBWwAxLHmex7uksDHnAX/gT5s0wVgh4Iq5ul3zXHxhfw67lLfiwCZGERYBsKYZWBVeF94cxtbF\n",
1194 "Q8gwigw3WTN5YddF+hNlaHAVuWpcCdc01+eQYV8mr/TukoMwf4A/vHRnmCesDK8Fm+hmfk3eE7py\n",
1195 "XTn8fFwRnVc+lFACIwS8sQiMqmP8LwVbdLHfuLqqN/lYkXX4XRVj7+WfMs/pCXZaQ8W3R6Ozm336\n",
1196 "afZ6xlRd9ubCr/6f6nmF4l1W50CTL5hXlBeb9/nKooq6Wl/bgmgsr8Ts9zZ9aVWBRT4H+kD8UNir\n",
1197 "Wi+ohDvw9hjCZbON7Dkme9+eRSRW8khOGkYDb/P1gllFY4wqqZqlWqy6X/WoimszBgSTl1M0UAKF\n",
1198 "L/CxvAAUjHSWx0cvVcTlzf3cHQnV+o3yHk2Cl/8RlT8XtslmbHPCpZscdMdGAc+GBv+EcOBKgEiR\n",
1199 "lyd6RJQHT+OViTs+J34olzfyS/FDZuLlaYXHJC3mW8Qjh+IoDMkEJjkZE281HdZczhzWSKKGljca\n",
1200 "Yri6TAHhM/TcamLGQuhD+Yll4h5G5/xch8WZmSgHLZbux0JSVGkoDAaD9hGLMFP7nDnt984SP7zn\n",
1201 "no3j6riG4l5KazCVPcqyrFyXiddpkXifuEZ8QhwtfcwmFF+UQb/mj6OVaTbUFNkWCwteR4Y6MpnQ\n",
1202 "C3VNm1UebFHej7W3mpG2p6Fw6KQmPTfrXtSQC/Ee8Fr2igbhLTnu2R6Visn7Ppqh6/iAQ/xPNE/q\n",
1203 "Fg0HcObIb3ar7vvfM8fPcuaoUt3ozHHkHJejQbVcMPCVwkKsagWM/0mb/KI3auWdlEHtWW0OH3a1\n",
1204 "FjgvGLGGTQv5lnxxBb8z//78R/M35j+Xn8o/lD+YfzY/B83CwTuPGWt3HNTl4P2PofEIjLl+vtjl\n",
1205 "Ksa/Q5kLVdTu8djH/EP8VpVLGFHd/InxW1Wu6H811uvIOXGYP/9jgklwCnt0DBuPOoUkC/GkeAOQ\n",
1206 "Va2ILHRmUM+eNGm2ulYX9/vjOtVjrV1drQH+P9nn9VfCKdW3/9fn9f+XPq+qjhv7vIojx/g4Oovm\n",
1207 "Fp3w7ZQ2RGM9kQ2l4eMjwkwtfVZ8T6G6yEwwY2edT5hs5A3Kgfs0azRPaOhXmpmaRZr7NPxXaoWq\n",
1208 "jf9Kl9lyHNSd1dEUpcaUqHCkyL5FCHYuD5Ya/u+HfL4a3pO4E5PWRj4fCF3isPAPqjt4G22gPdkB\n",
1209 "kCi9LKhGGZSUXj4g93oVSsnJ9J4x3bYr21vrM71U5k52C3tHfnL98Zz2w/UKxQhoNZbz8fz8Afxu\n",
1210 "sThROCe+y39n38NUKvmsBDGXBZG4K/mq5nsY/N89IHPkmDl8XTzG79cK5WNCJl9z5K1BJ46wCF/Q\n",
1211 "lJtZ4VTmGf7+L9hR8djHTeLjHx/4fzYvJoR4Xv8o/lioF97YY9F41DV7nJpCjiGNwLFKo1XXpGFY\n",
1212 "IC5MFuVoC7U4LIfmu1z7kBbmB7u0B7Svak38W63FafFbopbJll7LEstKy1rLJst2CziBEQrLco6v\n",
1213 "x2GQ5BqETWKYMKLI2ccr7LsmZNJYipCUz9JvEK+kTxsuGlAVvaHAEDRkWPZXG9Ybthh2GvYbjhlM\n",
1214 "GK/g75AK8YU7b1rljZmzcVltcTlg9Z5x2FPOVR0RB5MmdIVcgc7bGhtv6wy4Ql0T/nQ4NCXijvQ9\n",
1215 "0Nb2l/Mi7oYp4cN79VWTZkyILmjzVbYtaKydOalatzd+iyk6pS/ccf/sCRNm398enj8larol/r+y\n",
1216 "/X9Vtv8bv/y/Hr+8bOQjMZ/LrFD4CsyHi2Bc3K/nMnIrhHMQmCwOM39O8zV7Ulk6H3wwW/pz4J4y\n",
1217 "iDWodVAOTtvvFK8kixDEOeCMObud85xLnauc65ybnTuc+5xHnby5nnSeB9lAgcpMekClNuOLIlsk\n",
1218 "Obz0wDGHmG8tyS8pN/P5ZzL79XRDkd1p0OfYyqtdrHp4KduaSAy/5izLzcQwGPkt28b7WrlQI/w8\n",
1219 "VRtCLIJaouHkarjsimIbgpemiz9vNl6PzdJfobmSfrPiUgV1worCiqqK5oopFfMrllc8VLGhAgwB\n",
1220 "ByperTCRpUtwUKrS2KyZmL/jPBdo7U9kRiL2cfuLSRDFruJAcay4u3he8dLiVcXrijcX7yjeV3y0\n",
1221 "GIIoPl9MKj1ifqZPV16spN5XWVAZrGyq7Knsq1xWubpyfeWWyp2V+yuPVZoWSlWUN4QGc4dGnTcQ\n",
1222 "s8r+T2RFqXj3RFwqeUXhiEbZtkR3rCcuunvt3lBReNK8uXlOt8k+wSUWTCt1ufxN8apYa9tfTKqc\n",
1223 "y1TVbRNcnS1Tn+3d5K6w6fPtXtHrDzW1/Kztr2UZ145cFutFl1AkVAgFUnEF12IqsPZUmFg9FTTz\n",
1224 "Oa4iu5MHgkAjdH7HM4ne1tv8XlcolgwkFnX6fJ2LEvFFnf4VrXPntjDV3kRzq8MXKTfXTLsjHr9z\n",
1225 "ak3VlDtv8n29peXriHtTJSwTX2RfEwJCTJgibE5NDaWmkQIw1SJHa0b/D+J9Bi8F6X0GC4NVwebg\n",
1226 "lOD84PIgoo1uDe4KHgi+GjSR+Vi7hr8jbbuz3d8ebZ/c3tu+pH1l+9r2Te3b2wfaj7RjbG0/1y4u\n",
1227 "FPY0iho+ZHvFGj7Ra8jOyauE80rVWFI3DaZuIv7kLj4mVma8ca4iJpV9dXRy/HddKf8Urcz6mKOH\n",
1228 "iy/afRPLSibW1dic1RMipWWRSrvNFykraQzV2O1VSJnotzdXVzmqAl6zxRuocvmrh4+bfVXVDlup\n",
1229 "3VAbtFcHvVc80aDL5vHb8v0euzPQ6IHjg6M8YLMFyx3OQLTCH7UVl5vySt2WhkqTp9hmLizL9zdY\n",
1230 "3R45DtbI+3yB8GMu42amTsVDqQRJOE6m+7kkYQck7LjkIAk7Ch1VjmbHFMd8x3LHQ44Njq2OXY4D\n",
1231 "jlcdXMJ8RMjnnc/SHyY5h51hfzganhzuDS8JYztoU3h7eCB8JAw5h8+FeV8gJRYKWHAwFQwJ/N+1\n",
1232 "FKfkf8072h4z3oaUryGaynLig0ifdl90Uy9yF7iD7iZ3j1v2Hlzv3uLe6d7vPuY2Ybe+v5F6Z6Or\n",
1233 "MdAYa+xunNe4tHFV47rGzY07Gvc1Hm1E72w830jGB+MW5E7XxKvsstQZx8OMW9ZRS3h+T2hqpMjd\n",
1234 "0FNX3+th1qquid6I21c2uSY8NVrpzO0qmhWuiHitVm+koibus7C7Y3+9YnrlpNm1NTPiFXV+k9tU\n",
1235 "veiWqNteU1zqiXbPmvMFX8xdG/eUttSXhnvm0Fh+50gN26TKFxoEB19b+NU1wp4y0cHbaJ2oV9eg\n",
1236 "2jSsomZOp8MqG1eT1zyNEdGJjXzk8Mttkm1yWPK4tq0z5ulUjInOhrAjYMsz8SStKU/DRJWhaILX\n",
1237 "UOgwiWetVqPZ5A7U1ZRphvVl829pdhbm5RvzjBOaI1oHu+xqaW0Jl2iMNuiqH45Usw94HfXYwdcJ\n",
1238 "GB00XpUuELPZIszX/t26gjuefan1JJvLCxxOq57EcxWOVIvt/DcGwUFcd/rQnhwRyyWNqMVzuRoZ\n",
1239 "a4TVEit3FLIpw4dF8/Bk1ji8n50+GWOH2IGmScM3D0++CXl187z+iuelE7w8H64VcK2ECPX0il8/\n",
1240 "DqCFPVqRIWeNtZzPQOVWsXV4arsYP6nafaVXdeFKQYbj8qfst+I7gkbIEUKSBpaQWpEmeT39kSOq\n",
1241 "CDBK4t8IavqG/tBD2yI2lcpmY92tu3a1/sPx9es3eNk6tm74IdY1/P3h77Mu+BlRQeKP+Ejn5f2v\n",
1242 "RmgYncf8gyl/qN+pvoKJrHKov1jFK65iPi6YShFrSrX8ELHGiCMQmBiLRmNYmY3a2dMEwf9zuPgj\n",
1243 "Mv7vZ02NoknntFrsueoJHs8EbYNuajQ6udDPJ+SXh+9gPxoWHuzoeNDaVGgqsZpdNmuOr742ou9p\n",
1244 "624pa/SW2+wT94vLP94sPv1xA68ytclbRi6IPaJGsAm9kk3N5aBTY7KEtqcflEzyBxv2rCRr9oOD\n",
1245 "r1ONoT1Wesm5oo4PsGRKhA0DPnvLQSN1GHL50MrbjhzivjzmUsLbs6rpEyd9a2/nH5n75omtTx3s\n",
1246 "Glm9sejBlsdavlm8iiNE2i3ME+eybwilwk3C7XvyNGZ1jRJKz2xJ1Q0Ke5pFCNIuGjhGxGqOboz3\n",
1247 "ROZHHPnXbLSlIrQR7wnxxbMckw8pLYOpFuzBjd3p8o7bA3Pc+CtxrspaWlNaNs1f2VVUEdRM4B9r\n",
1248 "S8unVPq7Snw+XQ19LJtWqXyrtpTgW3/l5BKvT1fLvuFu8LtceXnOeo+7IVDgzMtz1ZXt5pfZxKCS\n",
1249 "SM3sFkHL35Wfa5C5gl/S6Plcrs8YCIqEuYTGIWGPHm+Fz+yNlQ6NxqHh3e8W9sHwQvad4Vz2AQu2\n",
1250 "vdT2zN+1LUkkrs53gpSTzVcS9WQ6o6d3m0PvNmdc9rHGyspGjYNR9t8dvo0XwbO/p+3vnuEFDP8M\n",
1251 "2fMxZf7IWTaTfPFyBHiHIqijl7nYDnIIGvXv+f88HkWWX+BmmV+AjzrvCmfG8A48lk2/jHQuK2Ek\n",
1252 "IL4oviKU8f4+g8JEY36z8fnNlpnsyNr2upoI+TRgGqxgZkyDKhvFu6Q/fMjJBJnmA0E0FijXeVmE\n",
1253 "edH/5V0mVq4SX8yGnLYYjTOGN82YyyZOZhO95fl2Cj89bGeRraMxqC3GnIMHxVc+bikvLKZY1GwD\n",
1254 "e0CJO/ZrcYdqPX/rufR8b7Pm66ZfYN7rpl9khWPS78im/5aVU3ovF9Zeut8o3y+cJfmZkM7lZxHK\n",
1255 "2VekonJogTBWXlMus1iDAOWQYuKsVRG7rInMJ/LAjA67hnIKLLsIrn7bAIJ3XNC/zFso4x/KsKHC\n",
1256 "2BVowAZ2RTI5y+SzvH6LCC0Th3J2OogrVLEVclSyFdJTOJl4C/A9QFP2jO6AWjG0UVgoFQ9x6QCO\n",
1257 "ZclufJ9iwbZQ2gp4C/A9AMWBJTcrCtjqB+cqRQ1cB02zF8rteYAfp8XrcNULj4h9UHgPeck5BHWZ\n",
1258 "nA2A0YW6bAI0oXSKAjUVsDtLvjoVQFGfDqD0uSh9CnmJoWDyXO8GfI6XFBv134J9sZeP2Nasm7r3\n",
1259 "2b+dvWqm3z9z1ey/ZeLwcM+UKe+0P353e/vdj7e/014/e2kstnR2/W+44hKpnf943/wvz6+lNrCY\n",
1260 "v2svtQGT0gZ+MCb95mz6u8KxMemPZdMvC8fHpN+RTf+t8B80XizmfbGTt6VKYd6eAjVmiAIY22R7\n",
1261 "5Thdb1yvzJwD73EwJ/8ZV+fyGTEfFfA/hYNSpcpynS5Zbi130H/875h+KXaO6ZSG4TVs3/DX2bzh\n",
1262 "XewRS6ZbjumRhlzxlfbftA//rj3TJ7P96B9JVnal35WPSX8sm36ZVYxJvyOb/lsWUtLd4j+KJ7Pp\n",
1263 "v2OerAz/gvJ3yPlzKaI/UjqXITimHuQSgwWSRZlC+xlfu2BKH+pXqzNcJTm0E2yk67zBqziIx/Nq\n",
1264 "Z6zyMlLPGH3uUYkmPl8bGa16bQotCJZymEgW97DHenqGv9TDjg9/SXzl+ec/bmEzh/vZ12+5ZWRk\n",
1265 "5Jf8xQdU9/HncPL6a4V3TBRHceQKT8+lNiWnv2uQ4yvewv/sJznJ6b81yese20hAOMqfu0SI78lH\n",
1266 "2/kMrYbsDbFdUKI0D9e45uG18qcYbRZHx7YKdU/+DdrC6NhM9c0b+TX7E72nIuU9/Vp+f/y9Pkw2\n",
1267 "NsXyexX2Zd4r+y3dX0LP93aDMJpO95fQ/ZeEXZl8xqX/Tvj2de9fKnw8olHazW7Kv0yZJ9zZ9jQ2\n",
1268 "/SIzZ+u5m/IpU/L/ONNeVfn0firkPs+qx6Q/lk2/zIJj0tdn03/DEtly45ReK9dH2H/d9IvCP2Xr\n",
1269 "E6f61Cr1+QdKb+By/ojun6Dkc+i66ReEPdReGkYC7CPxpDBb+GXqllBqTih1i0KcmJpjSU0bktjE\n",
1270 "aZjMS+lPaqKlv1MFBbrT2envjHZO7uztXNK5snNt56bO7Z3w9IYC3XmukyvQ8rbWNEt/jYor6TWX\n",
1271 "akhJrymsqapprplSM79mec1DNRtqttbsqjlQ82oNV4Zp70Lues28TTbz1soX40a+pPAX8gmVFRLT\n",
1272 "Y6GlXy1ekUrlT82W/lbGle3Wi62kbLcWtAZbm1p7Wvtal7Wubl3fuqV1Z+v+1mOtJq5Aa1yK/gEV\n",
1273 "VDYBzWrQMb4UHuPxqx0l81FUajVXW6C3MIOotxpKQ47yKvvECZaKoDOozrWb85y5+fXNE+NVba5b\n",
1274 "moqiNcWeSFtXW8QTaLulpuXz1a2hBcXRGnd01qJZ0aqO6uKSFqZSB3yuCkdugS/fXqjOM+VoNdYO\n",
1275 "0VHYFAqErOVhT2V9udNZXNNWH5neUOAP13eZPfXl4caKoglTk+GbJ+blqATl3brxDrPv9nfCJrnP\n",
1276 "8bYTpnceUtrODqUvusUwtZ2Qcv/mG6cr/iVhiuk5Y4+oVvxLdETJb1JGShoCr95+3GOGIoVFjprU\n",
1277 "Gy1UqH49n4r4MGvC+kTeZ4000l6rIyKWvtXz1lvvihXvvsW+OXwv+2bLnvb2PVS3uXxeWEDjYz3V\n",
1278 "7R3egkfTb86mvyv8fEz6Y9n0y+PSv51Nf0/45Zj09dn03wh/pGefy+fiBfzZY8KzqaYQb5appow3\n",
1279 "fjMFSTTZArL2SBpxwNLv4yu9GCVmh95xVn5EK5P5YOQfjJlxmEy68MFo6S9h2BQqcZUESsYe2G4u\n",
1280 "2VGyr+RoCTaFSs7Dqimmsl8zpfOmjF1seKCpeXNW0yW13TGr7pdGx3FV54SGuKPHXl5V5c8zBaqq\n",
1281 "yu09jnjEH3WarhnbVaqC4rm317IXh6dHpjSUWDQaS0nDlAhLD3fW3j632K4pyM8M+4q+oUqRXGPK\n",
1282 "/P9/aF7js7Q4ndKblfFIbpsunu6g9BZl/Hp6TPod2fTfCk9m4gyzfxa/xtMn0Tzx5JeEMemvZNPn\n",
1283 "fEne0gjz8e4X7CzXvmcwdWpmKDUrlKobws67vEUo2eqIQ3CmJVU0iGOJOksqMpiKhLBw71Bj6Otw\n",
1284 "dvg7oh2TO3o7lnSs7FjbsaljeweYMDD0dZzrEImW4ebR9VoVf69VudebeRv4h4arz8D2lImT+JBn\n",
1285 "UxF1ShVvUdhM9F300fjmK/AFfU2+Hl+fb5lvtW+9b4tvp2+/75jPtFC6Sf4J1wp6aE+xx9UT6In1\n",
1286 "dPfM61nas6pnXc/mnh09+3qO9qD59JzvwZ7i+KWgFw6MmRQ+/kUaJ3ordAHZ6RMWcmMWAqqxtpeN\n",
1287 "7Bdj1wVMpRJLZjZ74hOKEvPvrC5ffctNwfYvV7TWFWtUpsyK4YuF07rqbWUBu6/RZx23fLAGbaEq\n",
1288 "bEk2t5XpjQ/FQp32qkk1Py5K2LIK30qNLeh1lTtyCqpinsza8XfsJ/TOe6mNtAl7rpv+OWWuvDp9\n",
1289 "ntIGr05fKnyH0oMj74s/Fd/n6YvltYcoUptC+mzxfT6jR1lBKhbCQCEOEfEYbe2lYhlv5AmZjfoJ\n",
1290 "meY1QXFLxmBahlESQeZ5I/M6vX5v1DvZ2+td4l3pXevd5N3uRQRoNDLvOW+GAdTDG40nQ15G40zu\n",
1291 "VaPw+CVqBYZkSZML3g7JTX8wQPPKVNB2Eh+gg9R2gq5gIBgLdgfnBZcGVwXBI7wjuC94NIi2Ezwf\n",
1292 "lKnBG9A0Gy42UNNsKGgINjQ19DT0NSxrWN2wvmFLw86G/Q3HGjD1YqxvvDZAWob17SqKSXF29Lph\n",
1293 "0o4ebY8Oe66OqSaGPx68JiL17okbNw6vvYpYLDs2XKH3u1x57/8wJv1r2fQnhb+/7v1zsu1kfPpS\n",
1294 "rEWVMeYKH2NiQlL4ZqotBK6ftsyxULsFHuZ59lJI3i5zupda+pv4HzpokGLyV2WWVHIwlQxlR5EM\n",
1295 "Md+eJtHDX2GeqhCvMEZ/sCZK4FUkLiboVSQKEsFEU6In0ZdYllidWJ/YktiZ2J84ljBd0+Vprsgc\n",
1296 "jTnK6TAo5ho/WdjkkyIHWzvayTWaCcHaZKUv2dvQOLe5dPhhVXFdi7fxZnukOuLxui1yH2+b1VPW\n",
1297 "MqFoTO/WqEWLTXlP/tZbw6XeSRPc9WXVja48TbFT6d1/1zGnsDpakhnLLaKL5PxFpf8OXDd9jnDw\n",
1298 "uulLhe+PSX83m/6+sF32YeYT/WkVYtU/ruT/93w+YtjhYad5vy4T+lPlIRBglVtSBYOpghCd3DIy\n",
1299 "yVYN4gVVYPuw38RTuapePCizDYyhrcr00HH+FeMmfxf/4JJHf/RQlbFE3qLst+K9Wi9a6b1aC6xB\n",
1300 "a5O1x9pnXWZdbV1v3WLdad1vPWY1kXkwH1zK0JnR3eR4M04HX2Ipb8/hzZIsTvuXrCt6dAo5ore0\n",
1301 "tP+LGNouu6IPv8FUM+aQI7oYaty4UdZFT3F5FIuQ0zKaU38sCpm5nAnUb+T0J5k81+q5LvqiuJ9r\n",
1302 "XlXCQ3tKVT7YmPgu0TyW4yv0VfkQSXG+b7nvId8G31bfLt8B36uYx8w+6gLmUH8+l6hPCYMgpAKh\n",
1303 "ccrsdafUMcps4NOVWdWYfdSxe5AGsT0vM02x0vz8UvwbN0Wx14drM5ORyuEoKsI/0sFHfj5iEbay\n",
1304 "1wWbMH2PUZMDHTw7BueO3T/VT5oPVYaPtmqXOqDOGLeuUq9Tb1bvUO9TH1VjtFWfV2Om1rkU5QSr\n",
1305 "OVJgnCq9TV9QkqduF12xicUF/8hEdX5JhVX0f/xabn2DP1d+P7w+XGfh/YF9jt7P54YFxXffzX5J\n",
1306 "89nXKP13C+X0efwhnKqdPP0JZR4tFn6lpM+k+5+g+y89IN/vHnEL28ak/+7SaD438f6TyWep8I2R\n",
1307 "HJ7eQf0K/XOLkv8/0v1Xp88TnpLTeT1Ps7PZ9N8JX6X0/HH38/q8mF37ieXUHp9WxvH+MemvZNPn\n",
1308 "3CB9rfAmpVOcKUo/RPm3zZDzt/P63Er1kdN/9ys5vfSq++cl5PRxsRGQz6rrp39ukbyHU87nD8QI\n",
1309 "uUW4CIV8Lqnisk4+15KaDp18Osw6atSfUa8mfzDo7l20tuhydvm7ol2Tu3q7lnSt7Frbtalre9dA\n",
1310 "15EurC26znXxqZ2WK1zpRzlZq4IxmnnuZ9PMkxi7kheTNHYlC5LBZFOyJ9mXXJZcnVyf3JLcmdyf\n",
1311 "PJbEnOT6zJr5uIAWuquCX5CS86Mb6ueN4aq6G8S7SIyPjFFuy7++gt6jsjpuEAcjcHXEDL1alN+z\n",
1312 "G+8z+55/N1dQ9O332YP0/n+o7GU9ldHDwf+rpPP7m4Qbp4/hC64Qntuj1WDjV0sewE4iZ3TSClOL\n",
1313 "5aWAQ8LsnDQu9GbuVec6e1SiWi3H+MWRAlnl8XHK4DIEDDFDt2GeYalhlWGdYbNhh2Gf4agB45Th\n",
1314 "PEip86we5aDVRY4XhYPKArNYmZa4pj+e+rdR3gLI0P/+5V+OJwCeMUOmAF7S+NBYDuC/bVwCEuAs\n",
1315 "B8n3ZA4SLscfg4Mkm/61bPqTinzHcZbQOPD0mPSL2fR/FbZm0sX8MfevFU4KModNgI3wcb5ZGFCs\n",
1316 "U2qGaMaSz2fjyhq/vxTKJdmR1OCMN1UXwkeK4pNd3Y3jHb6xwkhBfTIfMqaBXFUE+XC/l16RF1Gr\n",
1317 "Yt5u7zzvUu8q7zrvZu8O7z7vUWgOJ73nQa7YTPdfV/e7AXnN2OO6kXHz5PVJba5/QvAJVDfZzWJl\n",
1318 "3+oVkveQsh77jTDqY634YGO8VMbRcX6aGF8/f/30pcr8thh7PeIrgrx3rhOKhB8p79nC79/P09dT\n",
1319 "+leFd+g9+4XXWIBZYQsBbY4NUUjKIUGOt90KzySK5XBWhGNoJXxKA8MjjL3WLq+DAP/EyxOFXPYX\n",
1320 "e7RqDR82x3kxbcN5VyuM/VtxZcbVGbUc+AFG3FjoF4D/Y59wFJ63CE8vG7bL7BphBRZKg4CNYLfR\n",
1321 "g+pFJDrUi/BQ3s+OwUPZBb+CHL2okGgslHJyFG4HKVdFqX+Ab3AUoIXTQRm4ZFPwyHwNAKcMaRvA\n",
1322 "jC/uU9JWSGdxNQvwqDFjyEqnJFeHg8YRuOyjKIl0lf6++AMEuxwS/xOsWn8HUd4lypHU9Rg8Ml6w\n",
1323 "q+B+NR9UBb3w9V3GVuOJdoHaZYpmPuhJQGeWnqzthddvN4QC1utYuYrRkXOg/CUW2Tr8sXy2PHfG\n",
1324 "8KYr7IGPN+Ks4qDynlQPkT+VjU0FqaZAMdbNQ/15XJhfAJ/LixwGvpL3VN7uPNUKSZVngMRA+C8z\n",
1325 "JRyE31Yu4DwdZsKlC4R6IoWRBCGdmrLMGZJeUPiGFkpn4Lm7JueJLN+EGbwm2iHJJGd/0ARud0vK\n",
1326 "MpQ0g452jeUJyzbLC5aXLboVSVvcMtWywHKX5WHLVyxPWXZbDlpyFqbftFyCGXaORdnUegHMXmYH\n",
1327 "2AZmOhY57nOscTzh0Cy8Dq1/lsBEsOYqnqRW+RRRHBy4W3xE/BswE8bxjo4T/Zl8mybUr+X35BI/\n",
1328 "Nl6ZkT5RjHlm9aoq5dNF3jV0XnhesxHD71kPsw//J2sYXjt88tFb2b+z54bfZHr28PDaDThGPHJE\n",
1329 "fIU6ENhwKpIC0+wpEITc3AZBLYRGXuQYHfkRx9jInzg2jwxwjBMmCF8a2c3xrZFfcxwi/BnhGcKz\n",
1330 "QBZFPixG2ESYRG6sDTmwh+meRzhqqEQNlaihEjVUooZK1FCJGipRQyVqqEQNlaihEjVUooZK1FCJ\n",
1331 "GipRQyVqqEQNlaihErVUopZK1FKJWipRSyVqqUQtlailErVUopZK1FKJWipRSyVqqUQtlailErVU\n",
1332 "opZK1FKJOipRRyXqqEQdlaijEnVUoo5K1FGJOipRRyXqqEQdlaijEnVUoo5K1FGJOipRRyXqqEQ9\n",
1333 "lainEvVUop5K1FOJeipRTyXqqUQ9lainEvVUop5K1FOJeipRTyXqqUQ9lainEvVUok1Qj7zKUUOo\n",
1334 "JdQR6gkXjqzhmCI8jhRmIDQSmggf41jCa/5djlHCGKU0jzyLU1fCBOFLhD8beYvjGcKzQEa/4rUF\n",
1335 "NhEmkQOvLb+f1/MtoZrXc4CjhlBLqCPUEy4cWcoxRXgcKbyeQCOhifAxjrVCiLeDWiFKGBMsHJtH\n",
1336 "fscxTpgg/JlQwPEM4Vkgo/tZjLCJMInf8hry+9kj/J4Qr+GLHDWEWkIdoZ5w0sjXObYSJgnbCTsJ\n",
1337 "JxNOI+wl7CO8jXAh4XLCuwjvJryH8F7CdfwdhYT1I3/k+DSlPEP4LOE2wm8T7iZMER7i0g4J/0bX\n",
1338 "rxAeITxOdT5B354kfIPwFOFpwiG682eEZwjPArnk+W+55IEmQnpG1kVIT8q6CXsIpxBOJbyZcAbh\n",
1339 "TMJZhLMJF+Dp2BK6Xkq4jHA56sPuIrybkCTDSDLszwnvI3yAvn2QcCXhKsLVhA8RPkx3PkK4hkp8\n",
1340 "jD9FlHpKlHpKlHpKlHpKlHpKlL9fYCthkrCdsJNwMuE0wtt4O4xSz4ryd4qUuwjvJryH8F7CdYTw\n",
1341 "t47yd4rrZwifJdxG+G3C3YQpyvMQ7y9R/h5RynFKP0EpJwnfIDxFeJoQo0eURo8ojR5R6uNR6uNR\n",
1342 "6uNRRk/B3yCQnoW/KeAMwpmEswhnEy5AnfmbwvVSwmWEy1Eif1PAuwkfIHyQcCXhKsLVhA8RPkK1\n",
1343 "WkN5YrSJ8Xfxa44aQi2hjlBPOIn/KsbfBTBJ2E7YSTiZcBrhbXT/Qi6rGH8XuL6L8G7CewjvJVzP\n",
1344 "+3iMvwVcP0P4LOE2wm8T7iZMUW6H6PoI4XHCE4QnCd8gPEV4GshlDjQSmgiptlzmQKozlznSZxDO\n",
1345 "JJxFOJtwAWrIZY7rpYTLCOm5GD0Xo+fiMgc+SLiScBXhasKHCNdQbo/x62Yae5tp7G2msbeZxt5m\n",
1346 "GnububS/y7GVMEnYTthJOJlwGuFthAtHHue4nK7vIryb8B7CewnX8d7XTKNZM5c5Up4hfJZwG+G3\n",
1347 "CXcT/gPVJDXyDMe9lHKE8DilnyA8SfgG4SnC04Rv8RbVTPNFM80XzTRfNDOqP5c/kJ6Cyx84g3Am\n",
1348 "4SzC2YQYnZq5/HG9lHAZ4QOU24OEKwlXEa4mfIhwDf0WM1ScpB0nacdJ2nGSdpykHSdpx0nacZJ2\n",
1349 "nKQdJ2nHSdpxknacpB0nacdJ2nGSdpykHSdpx0nacZJ2nKQdJ2nHSdpxknacpB0nacdJ2nGSdpyk\n",
1350 "HSdpx0nacZJ2nKQdJ2nHSdpxknacpB0nacdJ2nGSdpykHSdpx0nacZJ2nKQdJ2nHSdpxknacpB0n\n",
1351 "acdJ2nGSdpykHSdpx0nacZJ2nKQdJ2nHSdpxknacpJ0gaSdI2gmSdoKknSBpJ0jaCZJ2gqSdIGkn\n",
1352 "SNoJknaCpJ0gaSdI2gmSdoKknSBpJ0jaCZJ2gqSdIGknSNoJknaCpJ0gaSdI2gmSdoKknSBpJ0ja\n",
1353 "CZJ2gqSdIGknSNoJknaCpJ0gaSdI2gmSdoKknSBpJ0jaCZJ2gqSdIGknSNoJknaCpJ0gaSdI2gmS\n",
1354 "doKknSBpJ0jaCZJ2gqSdIGknSNoJknaCpJ0gaa8UMNqsFF4S8oUXhRdHhvjVS4RYgbxEK5CXhB/y\n",
1355 "e16iGfwlmsFfohn8JZrBX2L307crCP+C4yG+XgL2ES7ktTqE/QyOywnvIryb8B7Cewm/SIgZ9pDw\n",
1356 "TV6fQ8IWwqcIn6ZvnyF8lnAb4bcJdxOmqKy9uObrGWAP4RTCqYTTCG8mnEE4k3AW4WzCWwjnEM4l\n",
1357 "vJXw86gJu53wDsI7CZfQt0sJMcIfJ63hOGkNx0lrOE5aw3HSGo6T1nCctIbjpDUcJ63hOM37x2ne\n",
1358 "P07z/nHSGo6T1nCctIbjpDUcJ63hOGkNx2kufotmzLdophvi169yTHH8Gcn/ZySZM3R9hq7P0vVZ\n",
1359 "XDMDasuR15Yjry1HXluOccIEIa8tR15bjkOEPyM8Q3gWiNpyjBE2ESaRG2rL8WG6h9eWGalEI5Vo\n",
1360 "pBKNVKKRSjRSiUYq0UglGqlEI5VopBKNVKKRSjRSiUYq0UglGqlEI5VopBJNVKKJSjRRiSYq0UQl\n",
1361 "mqhEE5VoohJNVKKJSjRRiSYq0UQlmqhEE5VoohJNVKKJSjRRiZXQvzhGCbn+xZHrXxzjhAnClwi5\n",
1362 "/sXxDOFZIKNfQf/i2ESYRA7Qvzhy/Yv5KX8/5e+n/P2Uv5/y91P+fsrfT/n7KX8/5e+n/P2Uv5/y\n",
1363 "91P+fsrfT/kHKP8A5R+g/AOUf4DyD1D+Aco/QPkHKP8A5R+g/AOUf4DyD1D+Aco/QPkHKf8g5R+k\n",
1364 "/IOUf5DyD1L+Qco/SPkHKf8g5R+k/IOUf5DyD1L+Qco/SPmHoPNxjBJyvZIj1ys5xgkThFyv5HiG\n",
1365 "8CyQ0f3QKzk2ESbxW+iVHLleycKUc5hyDlPOYco5TDmHKecw5RymnMOUc5hyDlPOYco5TDmHKecw\n",
1366 "5VxPOddTzvWUcz3lXE8511PO9ZRzPeVcTznXU871lHM95VxPOddTzvWUM3SlFxl0JaCWUEeoJ+S6\n",
1367 "MIOuBEwSthN2Ek4mnEbYS9hHeBvhQsLlhHcR3k14D+G9hFwX5shnWAa9CSnPED5LuI3w24S7CVOE\n",
1368 "XBfm+G90/cr/7e1MgOwo7jPerZV2Vxe3AWMsP+MDDEKWhGBmxGGt7gvd4pAlpKe3o92Zefve8o6V\n",
1369 "VoBlrxHIB5CkcscCh5CkApWEHChEoOC4HBIUJakk5iocQ27HSZzEOSqpOFH+329mtU+ywJWqVLx+\n",
1370 "3+s309PT/f96ju7+PgG+CB6nzi+z9xXwVfA18HXwa+T8Ovgm+JZQY2GvkZRwJkgbNRb2GkkJV4Ar\n",
1371 "wVXgavBWcB24HtwAbgS3qXUaC3uNsISDYKL6aCzsNcISEhlPZPQkNayDLfa2wRFwL7gPHAX3k/Me\n",
1372 "8ABntLGwD+A3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8A\n",
1373 "fgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4\n",
1374 "DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3gN8AfgP4DeA3\n",
1375 "gN8AfgP4DeA3gN8AfgP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8Q\n",
1376 "fkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4\n",
1377 "DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4DeE3\n",
1378 "hN8QfkP4DeE3hN8QfkP4DeE3hN8QfkP4jeA3gt8IfiP4jeA3gt8IfiP4jeA3gt8IfiP4jeA3gt8I\n",
1379 "fiP4jeA3gt8IfiP4jeA3gl9G9z6C3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC\n",
1380 "3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4DeC3wh+I/iN4JfZAB/BbwS/EfxG8BvB\n",
1381 "bwS/EfxG8BvBbwS/EfxG8BvBbwS/EfxG8BvBbwS/zCH4CH4XaX7McArYDfaAveAt9saySPNjhovA\n",
1382 "xeBScDm4BtxOfnvbN0xIp2AGVsEh8JA99xdp3GR4GHwUfAx8HHwSfJrSvkT6RfA4+DL4Cvgq+Br4\n",
1383 "ulDzY4YzwJkgtdX8mCF11jjLcB24HtwAbgS3qYYaPRkOgIMg7fK0y9MuzY8ZtsERcC+4DxwFD1Da\n",
1384 "mKX7NIdgOAXsBnvAXvAWY6pPcwiGi8DF4FJwObgG3A7uOHnQMCGdghlYBYfAB43xPq6gPs0hGB4G\n",
1385 "HwUfAx8HnwSfoiZPnzxs+AxbXgSPs/1l8BXwVfA18HXwDXvX7dMcguEMcCZI/TWHYEgrNIdguA5c\n",
1386 "D24AN4K6Ivo0h2A4AA6CLUprgyPgXnAfOAoe4NgxS69xa12/YQscccsND5I+5LYZPgQ+zJZHwCPg\n",
1387 "s26+4VF3k+Fz4PPkPAa+AJ5wG/waf5vyW2+xLX4H6bvAneAusAwOk/9usAEesKN2Wg03GLbsLDut\n",
1388 "hlcZHmTLIfAh8GHwEfAIOZ91FxketXrutBoKn2f7MfAF8ISb5XdaDe0oq6FwB3gXuBPcBZbBYfLf\n",
1389 "DTbAA7Y90ZyJ4R2gjc0Nd5FOwBTMwCo4BN4HPmj9IdGcieGPgj8OfoG9h8FHwcfAx8Enwac51zNK\n",
1390 "a87EcCW4ClwNrgHXgreC68D14AZwI7gJ3AxuAbeCu1UfzZwY9oMxuIe9A6Cu/ZQ4pMQhJQ4pcUiJ\n",
1391 "Q0ocUuKQEoeUOKTEISUOKXFIiUNKHFLikBKHlDikxCElDilxSIlDShxS4pASh5Q4pMQhJQ4pcUiJ\n",
1392 "Q0ocUuKQEoeUOKTEISUOKXFIiUNKHFLikBKHlDikxCElDilxyIhDRhwy4pARh4w4ZMQhIw4ZcciI\n",
1393 "Q0YcMuKQEYeMOGTEISMOGXHIiENGHDLikBGHjDhkxCEjDhlxyIhDRhwy4pARh4w4ZMQhIw4ZcciI\n",
1394 "Q0YcMuKQEYeMOGTEISMOGXHIiENGHDLikBGHYbtyZxm2wIPgIfAh8GHwEfCI0K5E4TZwB3gXuBPc\n",
1395 "BZbBA4b7NVdm+LThPcT5HiIwxnzRGPNFY8wXjTFfNMZ80RjzRWPMF40xXzTGfNEY80VjzBeNMV80\n",
1396 "xnzRGPNFY8wXjTFfNMZ80RjzRWPM4Dl3ib8s/68qGU7PNSVos3rsV57uciV3QZGe3JFniuWZX6S7\n",
1397 "bXtUpKUnXFqkLyB/l/OTp9r3Z/XfWCHt3cXGRp6e5M7x+4p0l1vkHyjSkzvyTLE8Lxbpbtv+1SLd\n",
1398 "46/y3yzSve6yrguK9FQ3q2t2kZ7W/Uddq4v0dDdn2uVFeoZbPW18+3luxrQfLNLnu95pX+wbiWtJ\n",
1399 "o7S4Xs82xQPtarnRseXGUjhnbv918bwbS/Pnzpt/7dwF9v9iU57tWmUrjkiapXKp1Sj3x0PlRlaq\n",
1400 "7ymtjJP+uLo7bgzEjdLSRruSDZWblcGkFtdKfStml+J9lWq7mYzE1dFSNanEtWbcX2oNNurtgcHS\n",
1401 "2qRWb40Ox6UVQ7tXzi6Va/2lofJoaXdcasQDSbMVNyxzUitV4karbN9pu5E0+5NKK6nXmnPcEld3\n",
1402 "w27UNVziBtyg9fGfM37nu7lOs0ol6/mJq1meluUZdrFtWeGG3G630s229F7+5rjqGbnmuIr9GrLv\n",
1403 "krM3FPsrdZyhya/YvmP7HjHst5x9pGqWq2H7F9vxdZe5TbZtwLWthLJtP3ueGy0dWglzrZzrbP88\n",
1404 "tqgN8wyvte8FBZ6eq7O0a0+Vdvo5Empbtk/Lftvz3fYNUZfMttXdHsOVti1hT9UiozYNgCXr9w2r\n",
1405 "e8Xy6pimpQaJlMpXZFYQxdjtsz1Vy9m0vSOUM2rbFdUKeZvESHUYtBLrllOR/F7slG2fjtK5Vd5u\n",
1406 "cjSIqNrVopZ5yQk1qrClZfnz36mdqUHefurSMqxTnznvcO4+y62jypSxnBi0YD+Gw3faWyKOTX7X\n",
1407 "irqdyYiOm2f3l9D+8nbuKdpSsrrEsNM8xc6g/R7hqIEiJnkZ461XHMZLbbK/SSqmlnuIet7CPba3\n",
1408 "whHq16s44szydKbYrgldGwl8fTdLs6lVXJwvoY357z1w3zpVbt3iWSUW5VOxV33qZ8Qp76HVom+V\n",
1409 "icREW5LiqPwc4/046Sgxj9Qy27O7OHq87yyHnTbHzKYPtalfXoeynbNJSn0so/w2sRsvc/ys6uPD\n",
1410 "RUzFZYWt42dpEptq0SvV0/L25deC7lBDHNXq4HWiPXuLfSo5j3il2KJ6j8LWliL3Xju6cZZeNUTc\n",
1411 "8nhdaeWPtzq2X+MRXM7vGlfxRN0HC/abRZ3KRXzGa3d631Ht98JcicgNdcQqKUqZ6E3DnLF1FvY7\n",
1412 "eZnDvTDnpW15FMecizPZO9u9Le+ZJTtX3t783qOrMa9dC84q3FMTcg5yLytRVqPgq8w9vknuOmc/\n",
1413 "PR5lys63JNwR8+s1z9HZPwdhKHH7aW+r6GPj97OSu8K2X3Fa2ae3o0xbVLqupgrbKrRY99j4tDtj\n",
1414 "szhbi6jkd5v8Ph2TI+ZOMtF/8p5ds0iViz6cPx2Sjntotbi/7rZPlYiNdpxxoLjDn8lFuYhrw2Je\n",
1415 "Z2udK6mzrvmTIOGekF89w7S0DL/j19QeWqQrtV5cDS2uvtZppQ1yXP+pe0bnPS1/+i+gju98rx4v\n",
1416 "7czeXuL+0ijin9cn7+Nv/9TQ2TKOUizWcO/Tc6sMS4nLn1z59Zt1PA/PFsu8VhWOKNP+t8+9rojO\n",
1417 "ROTG823graNFjdtWyxJvS1WiP/EsnMM7Tctas9Bpve97vRP973J/lFrpOjj9uah+2dmO8beXQp/v\n",
1418 "3Mln3Hx3lv/5++0zyXJ1ud+2CP+8necX3Ifch638K91VVt7vuOPud93fuI+4q901drWccL/nft/9\n",
1419 "gb0hzbHa/BlvVXusbP0jwn9otflj9/3uF+2NaoG73t3g/sLeGv/enstfdS9bS1+xp/RCu3Pc5P7W\n",
1420 "Pedudn9lb0S6Nz1k7f2ivV1Mtdr3WYxnug9YW5e5j7md7i63y93iFrk33Dfcg9bn/tTa9XV3v40V\n",
1421 "3uvOdZ9zx6zHjLkvu0/buOtZqavdq9Z7honI3e497in3K+6Xjatv2ojhp6xHf8ld6n7T/Yy7xD3v\n",
1422 "VrvPGIfvt3fcJ91vuBesl71p7/prLbojxkLb3Wq9Yb17n3vC/bnb4LvcP7gfcf/oNrrLrYd027vo\n",
1423 "qLvH3et+yb1ld6eL3L+4f3X/5A67R91PuvvcZhsTTrdRRK873092L7pzbOy7xe5Uj9to5bfcr7pn\n",
1424 "bGz4a+4rbprbaiOfP3G3ub90D7hZ7jL3bhsXvWTjytvdt9zF7t/cP7vX3efdu9y33R3uE+6T7lPu\n",
1425 "gPF7p9vmPu62u79zR90Pux3ur92Fforv9j2+10/10/x0P8PP9Of4c/15/nx/gb/QX+Tf5S92j/lL\n",
1426 "/KXuJ/y7bWT3AzYS/4L7afdjNhb/df8eG7P+rI3Ofshf7t/rZ/n3+ZL7L/9+d9Jf4T/gP+g/5D/s\n",
1427 "r7QR1Uf81e7f/TV+tr/Wz/Ef9XP9PD/fX+cX+Ov9DT7woY/8Qn+jv8nf7G/xH/OLfJ9f7Je4//RL\n",
1428 "/TK/3K/wK/0qv9qv8Wv9rX6dX+83+I1+k9/st/it7r/9bd752/0d/k6/zX/cb/c7/F02Uv4Pv8uX\n",
1429 "/W5f8f0+9nv8gB/0iU9tTF71Q77m6zZ6vts3fNO3fNuP+L1+nx913/H7/T3+Xn+f/4Q/4D/pP2Uj\n",
1430 "20/7+/1B/4B/0B/yn/Gf9Z/zn3cfdN83ZU6tXa12D5UrjXrtnOG4kdT7bXDFiGnysnajPnWgUR6J\n",
1431 "51TKw1PLlXaL1DmVpFFpD+2pxvvYUSnbwR2pcrU1tZVU+8k8oz+xwppJUz+m5SdSsqddS+bOXxJN\n",
1432 "3d2I8xP0NpLagBLnDbZrA+VGe6habre0YWZ/vVWuqF76Nb1SHxoq57/P7UjrvFOWxtVWmbKvixbk\n",
1433 "331R/r14ydTyniS5Yd78MJoaN1vJULkV92vf8nD5cn3Pnz/v+uI76unL69rdRwV7+uoD9VqcTV8y\n",
1434 "0fhpS07Vq3spTbevRr3c6l7Gr55lRRHLKGLaslPZe5YVpa3oKG3Fqd0zVnQ0a/rKiTyTV+4uN7pX\n",
1435 "EdyeVXnp01ZNFLuqKHb1xCEz1nSU1b0WErvXUr8Zazt2TV5rxXSvy/evy/ev69jfs75ozHoaM3N9\n",
1436 "J0ndm/LjNuXHbeo85WZ2Td/cUaXNnfu35Mds6TwXfWNe3+Qtau7WvLlbi/Nv5fxTtqq3zNzaWYue\n",
1437 "rUXzb5841/Q7J9Ld26jKtG0TASsXhZZzkstFAZUOWioTJPfnJPfnJMc5yXFRRJyTHE8UHhelDXSU\n",
1438 "NjBB8kAnyYMdJA+q1Une6iQvvSfJy+q1w6txs5lOTzvimXXGs5pTUc3DWu2kuCqKa/n+Wr6/1lmJ\n",
1439 "Wnm43mw16sODcU+9aFY9p7t+Gt0NypjR6DxvIw9OM6e72VG9Zme2Vn7e1nfTvXhySw1v5w1vF+dv\n",
1440 "53S3obt9Gt3tIr57O+ge7aB7f073/lMhn7Rq9aQk5XRz+5YW33NPzd65cQeZPZ9m2VPfL12+dos9\n",
1441 "y/gXrk+eZI/P4kbNtuX5vO2bxHevfWrknN97YvzPvdK10Pd23dt11C+c/J0p39bfpKWT1k3aMmms\n",
1442 "90TX3N5ne7/MH7m7FhZ/9/J3NP/Tcd3f6Lmt5yv66x3hmBP61/jsbFPsidxj577Q3guuxsFzg717\n",
1443 "5O8bI/asP2ZP/uP2FvE1e3t4071VPB/Hn2n5U2z86aUn1hq/s3i+DPMMGbNnubwdcnbI1yFXhzwd\n",
1444 "cmjIUXH85EtyRMgPITcEDoQZ6IalGpZmWIph6YXlQpIHSatqWi/TapnWyqR9XXzWc8g1Is+IHCPy\n",
1445 "i8hnIX+FnCLbKfEAHhE5ROQPkTtE3hDpVuULkStEnhA5QuQHkRtEXhDVWz4QuUDkAZEDRP4PuT/k\n",
1446 "/ZDzQ/pPqT9RU3a0z+ogp4d8HnJ5yOMhh4f8HXJ3yNshZ4d8HXJ1yNMhR4f8HHJzyMshJ4d8HHJx\n",
1447 "yMOBRvGAHafYTUIFfIy5ZWmAp6MBlgJY+t8TllMr4loP12q41sKHbdvd9pHe9xr0vlL7SlMqpa90\n",
1448 "vlL5SuMrha/0vVL3KkZS9krXK1WvNL1S9ErPKzWvtLxS8kqhqhUIrT9o9UFrD1p50LqD1hu02qC1\n",
1449 "Bq00aJ1BqwxaY9AKg9YXtLqgtQWtLGhdQasKWlOQNncSSlnpZM/DISenm9xx8sbJGSdfnFxx8sTJ\n",
1450 "ESe9odSG0hpKaSidoVSG8sCdi3dNTjT51uRak2dNjjX51eRWewvtXTfaPCnzpMuTKk/+tA340+RO\n",
1451 "kzdNzjT50uRKkydNjjT50eTUkkNLTjT50ORCkwdNDjT5z+Q+k/dM6mxps+U6k5JdjjP5zeQ2k9dM\n",
1452 "TjP5zOQyk8dsnF25y+Qtk7NMvjK5yuQpk6NMfjK5yeQlkzpD2gwpM6TLkCpDmgwpMqTHkBpDWgwp\n",
1453 "MaTDkApDGgwpMKS/0FqztBdSXkh3odV0raVrJf3M3iWdhVQW0lhIYSF9hdQV0lZIWaG1ZznAbsZ1\n",
1454 "JM+RHEfyG8ltJK+RnEbyGcllJNeO3DryF22nlx45aw+Vn+jte+QR/ENyD8k7JOeQfENyDckz9DpX\n",
1455 "7LdQQ0gLISWEdBBSQZytx0r50NErUTywpmcfaR2kdJDOQSoHaRxGuVovxf1z81nvdPJFyBUhT4Qc\n",
1456 "EfITyEcgL4ScEPJByAUhD4QcEPI/yP0g70PeX57A9SDPgxwP8jvI7fAUV8thfA5yOcjjIIeD/A1y\n",
1457 "N8jbIGfDG9yTJ+6w0iJIiSAdglQI0iBIgSD9gdQHeX94At2BVAfSHEhxIL2B1AbSGkhpkHN9xEaX\n",
1458 "a22crLH4iI1MD9r3IRuVPWSfhy39iH2O2OdZez4dtTHvc/Z53vYds88L9pGOQCoCaQikIJB+QOoB\n",
1459 "aQekHJBuQKoBaQYOWH6dbYP0AlILSCsgpYB0AlIJSCMghYD0AVIHSBsgZYB0AVIFoAmQIkB6AKkB\n",
1460 "0ALYRzoAqQCkAZACQOv/B6ys2f+vd9C1/wd3UY3cZ2lVVmuyWpHVeqxWY7UWy0qs1mG1Cqs1WK3A\n",
1461 "av1Vq69l2jyL+/BLeBQm0WrV+EJ8E3JNyDMhx4T8EnJLyCshp4R8Ep1PSa2uam1VK6taV9WqqtZU\n",
1462 "8xXV/J1Kf+5/AIGHtqIKZW5kc3RyZWFtCmVuZG9iagoyMCAwIG9iago3MDc0OQplbmRvYmoKMTkg\n",
1463 "MCBvYmoKMTI3MzQwCmVuZG9iagoxNSAwIG9iago8PCAvRmlsdGVyIC9GbGF0ZURlY29kZSAvTGVu\n",
1464 "Z3RoIDY3ID4+CnN0cmVhbQp4nO3NMQ0AIQAEwVNMTYKOV4AZKhosIOQxQUNmuq02uWynZ2WmpWac\n",
1465 "LreHAAAAAAAAAAAAAAAAAAAAAPCY7weB+gXnCmVuZHN0cmVhbQplbmRvYmoKMTggMCBvYmoKPDwg\n",
1466 "L0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCAyNjEgPj4Kc3RyZWFtCnicXVE9b8MgEN35FTem\n",
1467 "Q0Rst5UHC6lKFw9Jq7qdogw2HBZSDQjjwf++fCRu1ZPg6T7ece+gx/a11coDfXeGd+hBKi0czmZx\n",
1468 "HGHAUWlSlCAU9zcv3XzqLaGB3K2zx6nV0pCmAfoRkrN3K+xehBnwgQAAfXMCndIj7L6OXQ51i7Xf\n",
1469 "OKH2cCCMgUAZ2p16e+4nBJrI+1aEvPLrPtB+Kz5Xi1Amv8gjcSNwtj1H1+sRSXMIxqCRwRhBLf7l\n",
1470 "q8wa5FZexfIAzwwuf9wiQ5mhyvCY4enOuKYGdXbrW4M6hsuyiNQMl4zXOM/95Tha3OOmmy/OBclp\n",
1471 "2UlrVKk0bv9hjY2seH4AHtCFLgplbmRzdHJlYW0KZW5kb2JqCjEzIDAgb2JqCjw8IC9DSURUb0dJ\n",
1472 "RE1hcCAxNSAwIFIgL0ZvbnREZXNjcmlwdG9yIDEyIDAgUiAvQmFzZUZvbnQgL0F2ZW5pci1Cb29r\n",
1473 "Ci9DSURTeXN0ZW1JbmZvIDw8IC9PcmRlcmluZyAoSWRlbnRpdHkpIC9TdXBwbGVtZW50IDAgL1Jl\n",
1474 "Z2lzdHJ5IChBZG9iZSkgPj4KL1N1YnR5cGUgL0NJREZvbnRUeXBlMiAvVyAxNyAwIFIgL1R5cGUg\n",
1475 "L0ZvbnQgPj4KZW5kb2JqCjE0IDAgb2JqCjw8IC9FbmNvZGluZyAvSWRlbnRpdHktSCAvQmFzZUZv\n",
1476 "bnQgL0F2ZW5pci1Cb29rCi9EZXNjZW5kYW50Rm9udHMgWyAxMyAwIFIgXSAvU3VidHlwZSAvVHlw\n",
1477 "ZTAgL1RvVW5pY29kZSAxOCAwIFIgL1R5cGUgL0ZvbnQKPj4KZW5kb2JqCjEyIDAgb2JqCjw8IC9E\n",
1478 "ZXNjZW50IC0zNjYgL0ZvbnRCQm94IFsgLTE2NyAtMjg4IDEwMDAgOTQwIF0gL1N0ZW1WIDAgL0Zs\n",
1479 "YWdzIDMyCi9YSGVpZ2h0IDAgL1R5cGUgL0ZvbnREZXNjcmlwdG9yIC9Gb250RmlsZTIgMTYgMCBS\n",
1480 "IC9Gb250TmFtZSAvQXZlbmlyLUJvb2sKL01heFdpZHRoIDY4MiAvQ2FwSGVpZ2h0IDAgL0l0YWxp\n",
1481 "Y0FuZ2xlIDAgL0FzY2VudCAxMDAwID4+CmVuZG9iagoxNyAwIG9iagpbIDQ4ClsgNTY5LjMzMzMz\n",
1482 "MzMzMzMgNTY5LjMzMzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMKNTY5LjMz\n",
1483 "MzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMgNTY5LjMzMzMzMzMzMzMgXQo1NiBbIDU2OS4zMzMzMzMz\n",
1484 "MzMzIF0gODcyMiBbIDY4MiBdIF0KZW5kb2JqCjMgMCBvYmoKPDwgL0YxIDE0IDAgUiA+PgplbmRv\n",
1485 "YmoKNCAwIG9iago8PCAvQTEgPDwgL0NBIDAgL1R5cGUgL0V4dEdTdGF0ZSAvY2EgMCA+PgovQTIg\n",
1486 "PDwgL0NBIDEgL1R5cGUgL0V4dEdTdGF0ZSAvY2EgMSA+PiA+PgplbmRvYmoKNSAwIG9iago8PCA+\n",
1487 "PgplbmRvYmoKNiAwIG9iago8PCA+PgplbmRvYmoKNyAwIG9iago8PCA+PgplbmRvYmoKMiAwIG9i\n",
1488 "ago8PCAvQ291bnQgMSAvS2lkcyBbIDEwIDAgUiBdIC9UeXBlIC9QYWdlcyA+PgplbmRvYmoKMjEg\n",
1489 "MCBvYmoKPDwgL0NyZWF0aW9uRGF0ZSAoRDoyMDE0MDIyMDE3NTMyNS0wNycwMCcpCi9Qcm9kdWNl\n",
1490 "ciAobWF0cGxvdGxpYiBwZGYgYmFja2VuZCkKL0NyZWF0b3IgKG1hdHBsb3RsaWIgMS4xLjEsIGh0\n",
1491 "dHA6Ly9tYXRwbG90bGliLnNmLm5ldCkgPj4KZW5kb2JqCnhyZWYKMCAyMgowMDAwMDAwMDAwIDY1\n",
1492 "NTM1IGYgCjAwMDAwMDAwMTYgMDAwMDAgbiAKMDAwMDA3MzYzOCAwMDAwMCBuIAowMDAwMDczNDQ0\n",
1493 "IDAwMDAwIG4gCjAwMDAwNzM0NzYgMDAwMDAgbiAKMDAwMDA3MzU3NSAwMDAwMCBuIAowMDAwMDcz\n",
1494 "NTk2IDAwMDAwIG4gCjAwMDAwNzM2MTcgMDAwMDAgbiAKMDAwMDAwMDA2NSAwMDAwMCBuIAowMDAw\n",
1495 "MDAwMzg4IDAwMDAwIG4gCjAwMDAwMDAyMDggMDAwMDAgbiAKMDAwMDAwMTMzMyAwMDAwMCBuIAow\n",
1496 "MDAwMDczMDYwIDAwMDAwIG4gCjAwMDAwNzI3MTIgMDAwMDAgbiAKMDAwMDA3MjkxOSAwMDAwMCBu\n",
1497 "IAowMDAwMDcyMjM5IDAwMDAwIG4gCjAwMDAwMDEzNTMgMDAwMDAgbiAKMDAwMDA3MzI3NyAwMDAw\n",
1498 "MCBuIAowMDAwMDcyMzc4IDAwMDAwIG4gCjAwMDAwNzIyMTYgMDAwMDAgbiAKMDAwMDA3MjE5NCAw\n",
1499 "MDAwMCBuIAowMDAwMDczNjk4IDAwMDAwIG4gCnRyYWlsZXIKPDwgL0luZm8gMjEgMCBSIC9Sb290\n",
1500 "IDEgMCBSIC9TaXplIDIyID4+CnN0YXJ0eHJlZgo3Mzg0OQolJUVPRgo=\n"
1501 ],
1502 "image/png": [
1503 "iVBORw0KGgoAAAANSUhEUgAAAJgAAABWCAYAAAAzIF/lAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
1504 "AAALEgAACxIB0t1+/AAACutJREFUeJzt3X1QE2ceB/BfNuHFsCExQDFECjqAhRa1DGOtAvbUuU4t\n",
1505 "teDUcQbbcDiTq1d7nSLT8bBjcuBh5WxBGRDB8eWOl/MG5uwInt6LN+Xl5uxdC7aQVAJnLeYAiRJI\n",
1506 "NrxE2L0/2vRiJkE27FJz/D4zzJjdfXYfnO/sbvbHs4+AYRhAiC/ED90B9P8NA4Z4hQFDvMKAIV5h\n",
1507 "wBCvMGCIV6LZVtpsNllZWVl9fHx8S0ZGRrHRaEyoqqqqJghiRqlU3lSr1XsFAgFTU1NzrLe3dz3D\n",
1508 "MIRKpdofGxv76UL9AujxNmvA6uvrjz777LOXJycnSQCAmpqaD/Py8l6TyWRDTU1NeW1tba8HBwcP\n",
1509 "EwRBFxYWpo6Pj0uLi4svFRQUbFqY7qPH3awBU6vVe/V6/SaDwbDebrcv8ff3H5fJZEMAAGlpaTV1\n",
1510 "dXXFUqn0bmpqai0AgFgsHouMjNSZTKaosLCwb1z3d+3aNXyq6+O2bNkiYLP9rAFzRlHUUpIkRxyf\n",
1511 "JRLJPYqi5EKh8AFJkvddl7sLGABAUlISm/49pKmpCV555RVs/wO17+joYN1mzgEjSdJMUZTc8dli\n",
1512 "sYSRJDlCkuSI1WoNlcvlAwAAVqs1VCKR3Pe8J3aGrFMwNf3tiS905dPwjXnyofViPwLCSH+uDoc4\n",
1513 "NueA+fv7T9jt9iVms1mxdOnSwdbW1jcSExP/KpVKh9vb23dHRUV9abPZZEajMSE0NLSfqw623x6F\n",
1514 "6k8HnJaMPbS+8McrMWCPsTkFTCAQMAAAKpUqr6SkpIEgiJnly5d/tX379g8BALq6urZqNJo2hmGI\n",
1515 "7Ozsd/nsMPItjwxYQkJCS0JCQgsAgFKpvHn48OEU12127959gI/OId+3qB60xsXFYfsFtqgCtmrV\n",
1516 "Kmy/wBZVwNDCm/O3SAe73R5YUVHxG4vFEkbTtHDHjh1FISEhRnclJD46jHwL64ANDw+vJEnSnJub\n",
1517 "u+vu3bsrGxsbtRaLJcy1hJSWllbDR4eRb2F9iVy+fLnebrcvyc3N/Uqr1ba++uqrR11LSN3d3Zu5\n",
1518 "7yryRazPYDdv3twYEBBgKy0tjTcajQnnzp0rCw8Pv+VYL5FI7js/8UeLG+szWE9Pz8b169c3AHx7\n",
1519 "NgMAsFqtIY71Fosl1LlmiRY31gFTKpU39Xr9CwAAZrNZQRDEzIMHDwLNZrMCAMBRQuK4n8hHsb5E\n",
1520 "JicnX+rq6tqq1WpbCIKgc3Jy3hEKhQ/clZAQYh0wAICcnJx3XJe5KyEhhA9aEa8wYIhXGDDEK6/u\n",
1521 "wQAAPv/88/TBwcG49PT0Ek+jjbjsKPJNXp3BJicnSYPB8Hx6enoJwP9GGxUUFGxSKBSGtra217nt\n",
1522 "JvJVXgXswoULv7p9+/bajz76qPHOnTtPY6kIecL6Ejk4OBhL07QwPz//5dHR0WUnTpz4nUKhMDjW\n",
1523 "Y6kIOWN9Buvs7Hxp3bp1fwAAkMlkQxKJ5B6WipAnrAMmkUju63S6zQAAExMTktHR0WVYKkKesL5E\n",
1524 "bty48cLp06crtVptKwBAVlZWvkQiuYelIuQO64ARBDHz5ptv/tR1OZaKkDv4oBXxCgOGeIUBQ7zy\n",
1525 "ulRkMpmitFpt6/79+3cGBgZSWCpC7nh1BqNpmvj444/zU1JS6hmGEWCpCHniVcCam5vztm7dWuXn\n",
1526 "5zfJMAyBpSLkCeuA9fX1rWMYRrBixYpOgG/PZi4vpsNSEfoe63uw7u7uzT09PRsMBsPzAwMDT3V0\n",
1527 "dLzs/D4wLBUhZ6wDlpGRcdTx74aGBu3atWuvNjY2alxfTMdtN5Gv8vpbpDNPL6ZDaF4B27lzZ4Hj\n",
1528 "31gqQu7gg1bEKwwY4hUGDPGK9T0YTdPEmTNnKoxG49M0TRO7du06JJPJ7mKpCLnDOmD9/f2rFQqF\n",
1529 "Qa1W/2x8fFxaUlLSIBQKp/EFdMgd1pfI6OjoG+np6aUAAFNTU+KgoKDRgIAAG5aKkDte34NRFCWv\n",
1530 "qqo6vW3btuNBQUFmx3IsFSFnXgVsbGzsifLy8t9mZ2fnrlixotNlDiMsFaHvsQ7YyMhIxMmTJ8/v\n",
1531 "2bPnbYVC0es8hxEAjipCD2N9k9/c3JxnMpmiKisrzwEAkCQ5gqUi5AnrgKlUqjyVSpXnuhxLRcid\n",
1532 "RfWgtaenB9svsEUVMIPB8OiNsD2nFlXA0MLj5O/BAABqamqO9fb2rmcYhlCpVPtjY2M/5WrfyHdx\n",
1533 "cga7cePGiwRB0IWFhan5+fnbamtrf83FfpHv4+QMptPpfpSamloLACAWi8ciIyN1JpMpKiws7Bsu\n",
1534 "9j+bQBEBXwxaPa5/IsgfFMEBfHfjsTBomYJhm93j+rDohZ8vkpOAURQlJ0nyvuOzRCK5R1GU3F3A\n",
1535 "Ojo6WO17JQAcTfK8nh7qnbX94Hc/AABKpZL18Z35ent/YP//P1+cBIwkyRGr1Roql8sHAACsVmuo\n",
1536 "RCK577rdli1bBFwcD/kOTu7BEhMTr7W3t+8GALDZbDKj0ZjgPJQNLV4ChuHm7wLr6uqKe3p6NjAM\n",
1537 "Q2RnZ78bExPzL052jHwaZwFDyB180Ip4hQFDvOLsSf5c6PX6tOPHj//+2LFja6RS6TAAwOXLl9+9\n",
1538 "fv36TpqmiczMzA+Sk5MvuWvrTaXAZrPJysrK6uPj41syMjKK2U55M98BLjMzM6JTp06dGRoaivH3\n",
1539 "9x//bhpEAZs+zOc9bDk5OSPR0dFfAACsWbPmanJychPbwTnznjKIYZgF+TGZTJEVFRXnTpw4UWc2\n",
1540 "m8MZhgGj0fhUaWnpBYZhYHp6WqTRaFqnpqYCXdt2dna+WFtbW8wwDNhsNqlGo2mZyzGrq6tPXbly\n",
1541 "Zd/FixcPMAwDR44c+aPZbF7GMAxcunQpr6Wl5Y3Z2n/99ddrm5qach3HPXz48J/Z7MNms0l1Ot0m\n",
1542 "x+9fVlZWw6b9zMwMUV1dfaquru4Dg8HwHNv+FxUVXXH+zLb9xMQEWV9fX+Rte4ZhFu4SGRoaeuet\n",
1543 "t97KEYlEdkfqdTrdCykpKXUAAEKhcDopKam5r6/vOde2nioFjzqmWq3e++STT3YDANjt9iVs32M2\n",
1544 "3wEuYrF4LCEhoQUAwGQyRUul0mE27ef7Hrb+/v5ErVbbWlhYeM1kMkWxbc/FlEGcXyIHBgZWnT9/\n",
1545 "/rjzMqlUenffvn0/cd2Woih5VFTUl47PjgqAu+3mWinwhKKopd6+x8wxwCUzM/PIJ5988v3vMdd9\n",
1546 "FBUV/WloaCimoKAgtaGh4Zdzae/8HrbPPvtsuzfvYSsvL18pEonsfX19606ePHmezZQ/XE0ZxHnA\n",
1547 "IiIieg4ePPjSXLZ1VAAcny0WS9iyZcv6PG33qErBI45l9mZwytjY2BOVlZVns7Ozc0NCQozNzc37\n",
1548 "2e7j/ffff3FgYCDu7Nmz5QKBgJ5Ley7ewyYSiewAADExMf8UiUR2NlP+cDVl0A/yLZJhGAEAwDPP\n",
1549 "PPO39vb2LACA6elpv87Ozm3ubt65qBR4MzhlvgNcDAbD83q9Pg0AIDg4+N7U1JR4rtPuZGRkHD1w\n",
1550 "4MD29957L3PDhg0X9uzZ83M2x+7t7X3u+vXrrwEA3Lp1K0kul/+HzZQ/XE0ZtKDfIh0c92ARERGG\n",
1551 "uLi4fxw6dOjvNE0TO3bsKPLz85ty3X716tV/6erq2qrRaNoclQJvjsd2cMp8B7iEh4f/u7Ky8ux3\n",
1552 "l0VBVlbWL8Ri8Zi3A2TYHFupVH518eLFg1evXn2bJMkRtVq9l6Io+VzbczVlED7JR7zCB62IVxgw\n",
1553 "xCsMGOIVBgzxCgOGeIUBQ7z6LzWkj3n7AHKHAAAAAElFTkSuQmCC\n"
1554 ],
1555 "text/plain": [
1556 "<matplotlib.figure.Figure at 0x10b0ecf10>"
1557 ]
1558 },
1559 "metadata": {},
1560 "output_type": "display_data"
1561 }
1562 ],
1563 "source": [
1564 "plt.hist(evs.real)"
1565 ]
1566 },
1567 {
1568 "cell_type": "markdown",
1569 "metadata": {},
1570 "source": [
1571 "```python\n",
1572 "def foo(bar=1):\n",
1573 " \"\"\"docstring\"\"\"\n",
1574 " raise Exception(\"message\")\n",
1575 "```"
1576 ]
1577 }
1578 ],
1579 "metadata": {
1580 "signature": "sha256:9fffd84e69e3d9b8aee7b4cde2099ca5d4158a45391698b191f94fabaf394b41"
1581 },
1582 "nbformat": 4,
1583 "nbformat_minor": 0
1584 } No newline at end of file
@@ -1,6 +0,0 b''
1 c = get_config()
2
3 #Export all the notebooks in the current directory to the sphinx_howto format.
4 c.NbConvertApp.notebooks = ['notebook2.ipynb']
5 c.NbConvertApp.export_format = 'python'
6
@@ -1,243 +0,0 b''
1 # -*- coding: utf-8 -*-
2 """Test NbConvertApp"""
3
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import os
8 import glob
9 import sys
10
11 from .base import TestsBase
12 from ..postprocessors import PostProcessorBase
13
14 from traitlets.tests.utils import check_help_all_output
15 from IPython.testing import decorators as dec
16
17 #-----------------------------------------------------------------------------
18 # Classes and functions
19 #-----------------------------------------------------------------------------
20
21 class DummyPost(PostProcessorBase):
22 def postprocess(self, filename):
23 print("Dummy:%s" % filename)
24
25 class TestNbConvertApp(TestsBase):
26 """Collection of NbConvertApp tests"""
27
28
29 def test_notebook_help(self):
30 """Will help show if no notebooks are specified?"""
31 with self.create_temp_cwd():
32 out, err = self.nbconvert('--log-level 0', ignore_return_code=True)
33 self.assertIn("see '--help-all'", out)
34
35 def test_help_output(self):
36 """ipython nbconvert --help-all works"""
37 check_help_all_output('jupyter_nbconvert')
38
39 def test_glob(self):
40 """
41 Do search patterns work for notebook names?
42 """
43 with self.create_temp_cwd(['notebook*.ipynb']):
44 self.nbconvert('--to python *.ipynb --log-level 0')
45 assert os.path.isfile('notebook1.py')
46 assert os.path.isfile('notebook2.py')
47
48
49 def test_glob_subdir(self):
50 """
51 Do search patterns work for subdirectory notebook names?
52 """
53 with self.create_temp_cwd():
54 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
55 self.nbconvert('--to python --log-level 0 ' +
56 os.path.join('subdir', '*.ipynb'))
57 assert os.path.isfile('notebook1.py')
58 assert os.path.isfile('notebook2.py')
59
60
61 def test_explicit(self):
62 """
63 Do explicit notebook names work?
64 """
65 with self.create_temp_cwd(['notebook*.ipynb']):
66 self.nbconvert('--log-level 0 --to python notebook2')
67 assert not os.path.isfile('notebook1.py')
68 assert os.path.isfile('notebook2.py')
69
70
71 @dec.onlyif_cmds_exist('pdflatex')
72 @dec.onlyif_cmds_exist('pandoc')
73 def test_filename_spaces(self):
74 """
75 Generate PDFs with graphics if notebooks have spaces in the name?
76 """
77 with self.create_temp_cwd(['notebook2.ipynb']):
78 os.rename('notebook2.ipynb', 'notebook with spaces.ipynb')
79 self.nbconvert('--log-level 0 --to pdf'
80 ' "notebook with spaces"'
81 ' --PDFExporter.latex_count=1'
82 ' --PDFExporter.verbose=True'
83 )
84 assert os.path.isfile('notebook with spaces.pdf')
85
86 def test_post_processor(self):
87 """Do post processors work?"""
88 with self.create_temp_cwd(['notebook1.ipynb']):
89 out, err = self.nbconvert('--log-level 0 --to python notebook1 '
90 '--post jupyter_nbconvert.tests.test_nbconvertapp.DummyPost')
91 self.assertIn('Dummy:notebook1.py', out)
92
93 @dec.onlyif_cmds_exist('pandoc')
94 def test_spurious_cr(self):
95 """Check for extra CR characters"""
96 with self.create_temp_cwd(['notebook2.ipynb']):
97 self.nbconvert('--log-level 0 --to latex notebook2')
98 assert os.path.isfile('notebook2.tex')
99 with open('notebook2.tex') as f:
100 tex = f.read()
101 self.nbconvert('--log-level 0 --to html notebook2')
102 assert os.path.isfile('notebook2.html')
103 with open('notebook2.html') as f:
104 html = f.read()
105 self.assertEqual(tex.count('\r'), tex.count('\r\n'))
106 self.assertEqual(html.count('\r'), html.count('\r\n'))
107
108 @dec.onlyif_cmds_exist('pandoc')
109 def test_png_base64_html_ok(self):
110 """Is embedded png data well formed in HTML?"""
111 with self.create_temp_cwd(['notebook2.ipynb']):
112 self.nbconvert('--log-level 0 --to HTML '
113 'notebook2.ipynb --template full')
114 assert os.path.isfile('notebook2.html')
115 with open('notebook2.html') as f:
116 assert "data:image/png;base64,b'" not in f.read()
117
118 @dec.onlyif_cmds_exist('pandoc')
119 def test_template(self):
120 """
121 Do export templates work?
122 """
123 with self.create_temp_cwd(['notebook2.ipynb']):
124 self.nbconvert('--log-level 0 --to slides '
125 'notebook2.ipynb')
126 assert os.path.isfile('notebook2.slides.html')
127 with open('notebook2.slides.html') as f:
128 assert '/reveal.css' in f.read()
129
130 def test_output_ext(self):
131 """test --output=outputfile[.ext]"""
132 with self.create_temp_cwd(['notebook1.ipynb']):
133 self.nbconvert('--log-level 0 --to python '
134 'notebook1.ipynb --output nb.py')
135 assert os.path.exists('nb.py')
136
137 self.nbconvert('--log-level 0 --to python '
138 'notebook1.ipynb --output nb2')
139 assert os.path.exists('nb2.py')
140
141 def test_glob_explicit(self):
142 """
143 Can a search pattern be used along with matching explicit notebook names?
144 """
145 with self.create_temp_cwd(['notebook*.ipynb']):
146 self.nbconvert('--log-level 0 --to python '
147 '*.ipynb notebook1.ipynb notebook2.ipynb')
148 assert os.path.isfile('notebook1.py')
149 assert os.path.isfile('notebook2.py')
150
151
152 def test_explicit_glob(self):
153 """
154 Can explicit notebook names be used and then a matching search pattern?
155 """
156 with self.create_temp_cwd(['notebook*.ipynb']):
157 self.nbconvert('--log-level 0 --to=python '
158 'notebook1.ipynb notebook2.ipynb *.ipynb')
159 assert os.path.isfile('notebook1.py')
160 assert os.path.isfile('notebook2.py')
161
162
163 def test_default_config(self):
164 """
165 Does the default config work?
166 """
167 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
168 self.nbconvert('--log-level 0')
169 assert os.path.isfile('notebook1.py')
170 assert not os.path.isfile('notebook2.py')
171
172
173 def test_override_config(self):
174 """
175 Can the default config be overriden?
176 """
177 with self.create_temp_cwd(['notebook*.ipynb',
178 'ipython_nbconvert_config.py',
179 'override.py']):
180 self.nbconvert('--log-level 0 --config="override.py"')
181 assert not os.path.isfile('notebook1.py')
182 assert os.path.isfile('notebook2.py')
183
184 def test_accents_in_filename(self):
185 """
186 Can notebook names include accents?
187 """
188 with self.create_temp_cwd():
189 self.create_empty_notebook(u'nb1_análisis.ipynb')
190 self.nbconvert('--log-level 0 --to python nb1_*')
191 assert os.path.isfile(u'nb1_análisis.py')
192
193 @dec.onlyif_cmds_exist('pdflatex', 'pandoc')
194 def test_filename_accent_pdf(self):
195 """
196 Generate PDFs if notebooks have an accent in their name?
197 """
198 with self.create_temp_cwd():
199 self.create_empty_notebook(u'nb1_análisis.ipynb')
200 self.nbconvert('--log-level 0 --to pdf "nb1_*"'
201 ' --PDFExporter.latex_count=1'
202 ' --PDFExporter.verbose=True')
203 assert os.path.isfile(u'nb1_análisis.pdf')
204
205 def test_cwd_plugin(self):
206 """
207 Verify that an extension in the cwd can be imported.
208 """
209 with self.create_temp_cwd(['hello.py']):
210 self.create_empty_notebook(u'empty.ipynb')
211 self.nbconvert('empty --to html --NbConvertApp.writer_class=\'hello.HelloWriter\'')
212 assert os.path.isfile(u'hello.txt')
213
214 def test_output_suffix(self):
215 """
216 Verify that the output suffix is applied
217 """
218 with self.create_temp_cwd():
219 self.create_empty_notebook('empty.ipynb')
220 self.nbconvert('empty.ipynb --to notebook')
221 assert os.path.isfile('empty.nbconvert.ipynb')
222
223 def test_different_build_dir(self):
224 """
225 Verify that the output suffix is not applied
226 """
227 with self.create_temp_cwd():
228 self.create_empty_notebook('empty.ipynb')
229 os.mkdir('output')
230 self.nbconvert(
231 'empty.ipynb --to notebook '
232 '--FilesWriter.build_directory=output')
233 assert os.path.isfile('output/empty.ipynb')
234
235 def test_inplace(self):
236 """
237 Verify that the notebook is converted in place
238 """
239 with self.create_temp_cwd():
240 self.create_empty_notebook('empty.ipynb')
241 self.nbconvert('empty.ipynb --to notebook --inplace')
242 assert os.path.isfile('empty.ipynb')
243 assert not os.path.isfile('empty.nbconvert.ipynb')
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,29 +0,0 b''
1 """Global configuration class."""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 from IPython.utils.traitlets import List
7 from IPython.config.configurable import LoggingConfigurable
8 from IPython.utils.traitlets import Unicode
9
10 class NbConvertBase(LoggingConfigurable):
11 """Global configurable class for shared config
12
13 Useful for display data priority that might be use by many transformers
14 """
15
16 display_data_priority = List(['text/html', 'application/pdf', 'text/latex', 'image/svg+xml', 'image/png', 'image/jpeg', 'text/plain'],
17 config=True,
18 help= """
19 An ordered list of preferred output type, the first
20 encountered will usually be used when converting discarding
21 the others.
22 """
23 )
24
25 default_language = Unicode('ipython', config=True,
26 help='DEPRECATED default highlight language, please use language_info metadata instead')
27
28 def __init__(self, **kw):
29 super(NbConvertBase, self).__init__(**kw)
@@ -1,17 +0,0 b''
1 """NbConvert specific exceptions"""
2 #-----------------------------------------------------------------------------
3 # Copyright (c) 2013, the IPython Development Team.
4 #
5 # Distributed under the terms of the Modified BSD License.
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
9
10 #-----------------------------------------------------------------------------
11 # Classes and functions
12 #-----------------------------------------------------------------------------
13
14 class ConversionException(Exception):
15 """An exception raised by the conversion process."""
16
17 pass No newline at end of file
@@ -1,33 +0,0 b''
1 # coding: utf-8
2 """io-related utilities"""
3
4 # Copyright (c) Jupyter Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import codecs
8 import sys
9 from IPython.utils.py3compat import PY3
10
11
12 def unicode_std_stream(stream='stdout'):
13 u"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
14
15 This ignores environment variables and default encodings, to reliably write
16 unicode to stdout or stderr.
17
18 ::
19
20 unicode_std_stream().write(u'ł@e¶ŧ←')
21 """
22 assert stream in ('stdout', 'stderr')
23 stream = getattr(sys, stream)
24 if PY3:
25 try:
26 stream_b = stream.buffer
27 except AttributeError:
28 # sys.stdout has been replaced - use it directly
29 return stream
30 else:
31 stream_b = stream
32
33 return codecs.getwriter('utf-8')(stream_b)
@@ -1,3 +0,0 b''
1 """Deprecated; import from IPython.lib.lexers instead."""
2
3 from IPython.lib.lexers import *
@@ -1,127 +0,0 b''
1 """Utility for calling pandoc"""
2 # Copyright (c) IPython Development Team.
3 # Distributed under the terms of the Modified BSD License.
4
5 from __future__ import print_function, absolute_import
6
7 import subprocess
8 import warnings
9 import re
10 from io import TextIOWrapper, BytesIO
11
12 from jupyter_nbconvert.utils.version import check_version
13 from IPython.utils.py3compat import cast_bytes, which
14
15 from .exceptions import ConversionException
16
17 _minimal_version = "1.12.1"
18
19 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
20 """Convert an input string in format `from` to format `to` via pandoc.
21
22 Parameters
23 ----------
24 source : string
25 Input string, assumed to be valid format `from`.
26 fmt : string
27 The name of the input format (markdown, etc.)
28 to : string
29 The name of the output format (html, etc.)
30
31 Returns
32 -------
33 out : unicode
34 Output as returned by pandoc.
35
36 Raises
37 ------
38 PandocMissing
39 If pandoc is not installed.
40
41 Any error messages generated by pandoc are printed to stderr.
42
43 """
44 cmd = ['pandoc', '-f', fmt, '-t', to]
45 if extra_args:
46 cmd.extend(extra_args)
47
48 # this will raise an exception that will pop us out of here
49 check_pandoc_version()
50
51 # we can safely continue
52 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
53 out, _ = p.communicate(cast_bytes(source, encoding))
54 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
55 return out.rstrip('\n')
56
57
58 def get_pandoc_version():
59 """Gets the Pandoc version if Pandoc is installed.
60
61 If the minimal version is not met, it will probe Pandoc for its version, cache it and return that value.
62 If the minimal version is met, it will return the cached version and stop probing Pandoc
63 (unless :func:`clean_cache()` is called).
64
65 Raises
66 ------
67 PandocMissing
68 If pandoc is unavailable.
69 """
70 global __version
71
72 if __version is None:
73 if not which('pandoc'):
74 raise PandocMissing()
75
76 out = subprocess.check_output(['pandoc', '-v'],
77 universal_newlines=True)
78 out_lines = out.splitlines()
79 version_pattern = re.compile(r"^\d+(\.\d+){1,}$")
80 for tok in out_lines[0].split():
81 if version_pattern.match(tok):
82 __version = tok
83 break
84 return __version
85
86
87 def check_pandoc_version():
88 """Returns True if minimal pandoc version is met.
89
90 Raises
91 ------
92 PandocMissing
93 If pandoc is unavailable.
94 """
95 v = get_pandoc_version()
96 if v is None:
97 warnings.warn("Sorry, we cannot determine the version of pandoc.\n"
98 "Please consider reporting this issue and include the"
99 "output of pandoc --version.\nContinuing...",
100 RuntimeWarning, stacklevel=2)
101 return False
102 ok = check_version(v , _minimal_version )
103 if not ok:
104 warnings.warn( "You are using an old version of pandoc (%s)\n" % v +
105 "Recommended version is %s.\nTry updating." % _minimal_version +
106 "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
107 RuntimeWarning, stacklevel=2)
108 return ok
109
110 #-----------------------------------------------------------------------------
111 # Exception handling
112 #-----------------------------------------------------------------------------
113 class PandocMissing(ConversionException):
114 """Exception raised when Pandoc is missing. """
115 def __init__(self, *args, **kwargs):
116 super(PandocMissing, self).__init__( "Pandoc wasn't found.\n" +
117 "Please check that pandoc is installed:\n" +
118 "http://johnmacfarlane.net/pandoc/installing.html" )
119
120 #-----------------------------------------------------------------------------
121 # Internal state management
122 #-----------------------------------------------------------------------------
123 def clean_cache():
124 global __version
125 __version = None
126
127 __version = None
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,50 +0,0 b''
1 # encoding: utf-8
2 """Tests for utils.io"""
3
4 # Copyright (c) Jupyter Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import io as stdlib_io
8 import sys
9
10 import nose.tools as nt
11
12 from IPython.testing.decorators import skipif
13 from ..io import unicode_std_stream
14 from IPython.utils.py3compat import PY3
15
16 if PY3:
17 from io import StringIO
18 else:
19 from StringIO import StringIO
20
21 def test_UnicodeStdStream():
22 # Test wrapping a bytes-level stdout
23 if PY3:
24 stdoutb = stdlib_io.BytesIO()
25 stdout = stdlib_io.TextIOWrapper(stdoutb, encoding='ascii')
26 else:
27 stdout = stdoutb = stdlib_io.BytesIO()
28
29 orig_stdout = sys.stdout
30 sys.stdout = stdout
31 try:
32 sample = u"@łe¶ŧ←"
33 unicode_std_stream().write(sample)
34
35 output = stdoutb.getvalue().decode('utf-8')
36 nt.assert_equal(output, sample)
37 assert not stdout.closed
38 finally:
39 sys.stdout = orig_stdout
40
41 @skipif(not PY3, "Not applicable on Python 2")
42 def test_UnicodeStdStream_nowrap():
43 # If we replace stdout with a StringIO, it shouldn't get wrapped.
44 orig_stdout = sys.stdout
45 sys.stdout = StringIO()
46 try:
47 nt.assert_is(unicode_std_stream(), sys.stdout)
48 assert not sys.stdout.closed
49 finally:
50 sys.stdout = orig_stdout
@@ -1,131 +0,0 b''
1 """Test lexers module"""
2 #-----------------------------------------------------------------------------
3 # Copyright (C) 2014 The IPython Development Team
4 #
5 # Distributed under the terms of the BSD License. The full license is in
6 # the file COPYING, distributed as part of this software.
7 #-----------------------------------------------------------------------------
8
9 #-----------------------------------------------------------------------------
10 # Imports
11 #-----------------------------------------------------------------------------
12 from pygments.token import Token
13
14 from jupyter_nbconvert.tests.base import TestsBase
15 from .. import lexers
16
17
18 #-----------------------------------------------------------------------------
19 # Classes and functions
20 #-----------------------------------------------------------------------------
21 class TestLexers(TestsBase):
22 """Collection of lexers tests"""
23 def setUp(self):
24 self.lexer = lexers.IPythonLexer()
25
26 def testIPythonLexer(self):
27 fragment = '!echo $HOME\n'
28 tokens = [
29 (Token.Operator, '!'),
30 (Token.Name.Builtin, 'echo'),
31 (Token.Text, ' '),
32 (Token.Name.Variable, '$HOME'),
33 (Token.Text, '\n'),
34 ]
35 self.assertEqual(tokens, list(self.lexer.get_tokens(fragment)))
36
37 fragment_2 = '!' + fragment
38 tokens_2 = [
39 (Token.Operator, '!!'),
40 ] + tokens[1:]
41 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
42
43 fragment_2 = '\t %%!\n' + fragment[1:]
44 tokens_2 = [
45 (Token.Text, '\t '),
46 (Token.Operator, '%%!'),
47 (Token.Text, '\n'),
48 ] + tokens[1:]
49 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
50
51 fragment_2 = 'x = ' + fragment
52 tokens_2 = [
53 (Token.Name, 'x'),
54 (Token.Text, ' '),
55 (Token.Operator, '='),
56 (Token.Text, ' '),
57 ] + tokens
58 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
59
60 fragment_2 = 'x, = ' + fragment
61 tokens_2 = [
62 (Token.Name, 'x'),
63 (Token.Punctuation, ','),
64 (Token.Text, ' '),
65 (Token.Operator, '='),
66 (Token.Text, ' '),
67 ] + tokens
68 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
69
70 fragment_2 = 'x, = %sx ' + fragment[1:]
71 tokens_2 = [
72 (Token.Name, 'x'),
73 (Token.Punctuation, ','),
74 (Token.Text, ' '),
75 (Token.Operator, '='),
76 (Token.Text, ' '),
77 (Token.Operator, '%'),
78 (Token.Keyword, 'sx'),
79 (Token.Text, ' '),
80 ] + tokens[1:]
81 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
82
83 fragment_2 = 'f = %R function () {}\n'
84 tokens_2 = [
85 (Token.Name, 'f'),
86 (Token.Text, ' '),
87 (Token.Operator, '='),
88 (Token.Text, ' '),
89 (Token.Operator, '%'),
90 (Token.Keyword, 'R'),
91 (Token.Text, ' function () {}\n'),
92 ]
93 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
94
95 fragment_2 = '\t%%xyz\n$foo\n'
96 tokens_2 = [
97 (Token.Text, '\t'),
98 (Token.Operator, '%%'),
99 (Token.Keyword, 'xyz'),
100 (Token.Text, '\n$foo\n'),
101 ]
102 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
103
104 fragment_2 = '%system?\n'
105 tokens_2 = [
106 (Token.Operator, '%'),
107 (Token.Keyword, 'system'),
108 (Token.Operator, '?'),
109 (Token.Text, '\n'),
110 ]
111 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
112
113 fragment_2 = 'x != y\n'
114 tokens_2 = [
115 (Token.Name, 'x'),
116 (Token.Text, ' '),
117 (Token.Operator, '!='),
118 (Token.Text, ' '),
119 (Token.Name, 'y'),
120 (Token.Text, '\n'),
121 ]
122 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
123
124 fragment_2 = ' ?math.sin\n'
125 tokens_2 = [
126 (Token.Text, ' '),
127 (Token.Operator, '?'),
128 (Token.Text, 'math.sin'),
129 (Token.Text, '\n'),
130 ]
131 self.assertEqual(tokens_2, list(self.lexer.get_tokens(fragment_2)))
@@ -1,70 +0,0 b''
1 """Test Pandoc module"""
2 #-----------------------------------------------------------------------------
3 # Copyright (C) 2014 The IPython Development Team
4 #
5 # Distributed under the terms of the BSD License. The full license is in
6 # the file COPYING, distributed as part of this software.
7 #-----------------------------------------------------------------------------
8
9 #-----------------------------------------------------------------------------
10 # Imports
11 #-----------------------------------------------------------------------------
12 import os
13 import warnings
14
15 from IPython.testing import decorators as dec
16
17 from jupyter_nbconvert.tests.base import TestsBase
18 from .. import pandoc
19
20 #-----------------------------------------------------------------------------
21 # Classes and functions
22 #-----------------------------------------------------------------------------
23 class TestPandoc(TestsBase):
24 """Collection of Pandoc tests"""
25
26 def __init__(self, *args, **kwargs):
27 super(TestPandoc, self).__init__(*args, **kwargs)
28 self.original_env = os.environ.copy()
29
30 @dec.onlyif_cmds_exist('pandoc')
31 def test_pandoc_available(self):
32 """ Test behaviour that pandoc functions raise PandocMissing as documented """
33 pandoc.clean_cache()
34
35 os.environ["PATH"] = ""
36 with self.assertRaises(pandoc.PandocMissing):
37 pandoc.get_pandoc_version()
38 with self.assertRaises(pandoc.PandocMissing):
39 pandoc.check_pandoc_version()
40 with self.assertRaises(pandoc.PandocMissing):
41 pandoc.pandoc("", "markdown", "html")
42
43 # original_env["PATH"] should contain pandoc
44 os.environ["PATH"] = self.original_env["PATH"]
45 with warnings.catch_warnings(record=True) as w:
46 pandoc.get_pandoc_version()
47 pandoc.check_pandoc_version()
48 pandoc.pandoc("", "markdown", "html")
49 self.assertEqual(w, [])
50
51 @dec.onlyif_cmds_exist('pandoc')
52 def test_minimal_version(self):
53 original_minversion = pandoc._minimal_version
54
55 pandoc._minimal_version = "120.0"
56 with warnings.catch_warnings(record=True) as w:
57 assert not pandoc.check_pandoc_version()
58 self.assertEqual(len(w), 1)
59
60 pandoc._minimal_version = pandoc.get_pandoc_version()
61 assert pandoc.check_pandoc_version()
62
63
64 def pandoc_function_raised_missing(f, *args, **kwargs):
65 try:
66 f(*args, **kwargs)
67 except pandoc.PandocMissing:
68 return True
69 else:
70 return False
@@ -1,25 +0,0 b''
1 # encoding: utf-8
2 """
3 Utilities for version comparison
4
5 It is a bit ridiculous that we need these.
6 """
7
8 # Copyright (c) Jupyter Development Team.
9 # Distributed under the terms of the Modified BSD License.
10
11 from distutils.version import LooseVersion
12
13
14 def check_version(v, check):
15 """check version string v >= check
16
17 If dev/prerelease tags result in TypeError for string-number comparison,
18 it is assumed that the dependency is satisfied.
19 Users on dev branches are responsible for keeping their own packages up to date.
20 """
21 try:
22 return LooseVersion(v) >= LooseVersion(check)
23 except TypeError:
24 return True
25
@@ -1,3 +0,0 b''
1 from .files import FilesWriter
2 from .stdout import StdoutWriter
3 from .base import WriterBase
@@ -1,56 +0,0 b''
1 """
2 Contains writer base class.
3 """
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
6 #
7 #Distributed under the terms of the Modified BSD License.
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 from IPython.utils.traitlets import List
17
18 from ..utils.base import NbConvertBase
19
20 #-----------------------------------------------------------------------------
21 # Classes
22 #-----------------------------------------------------------------------------
23
24 class WriterBase(NbConvertBase):
25 """Consumes output from nbconvert export...() methods and writes to a
26 useful location. """
27
28
29 files = List([], config=True, help="""
30 List of the files that the notebook references. Files will be
31 included with written output.""")
32
33
34 def __init__(self, config=None, **kw):
35 """
36 Constructor
37 """
38 super(WriterBase, self).__init__(config=config, **kw)
39
40
41 def write(self, output, resources, **kw):
42 """
43 Consume and write Jinja output.
44
45 Parameters
46 ----------
47 output : string
48 Conversion results. This string contains the file contents of the
49 converted file.
50 resources : dict
51 Resources created and filled by the nbconvert conversion process.
52 Includes output from preprocessors, such as the extract figure
53 preprocessor.
54 """
55
56 raise NotImplementedError()
@@ -1,43 +0,0 b''
1 """
2 Contains debug writer.
3 """
4 from __future__ import print_function
5 #-----------------------------------------------------------------------------
6 #Copyright (c) 2013, the IPython Development Team.
7 #
8 #Distributed under the terms of the Modified BSD License.
9 #
10 #The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 from .base import WriterBase
18 from pprint import pprint
19
20 #-----------------------------------------------------------------------------
21 # Classes
22 #-----------------------------------------------------------------------------
23
24 class DebugWriter(WriterBase):
25 """Consumes output from nbconvert export...() methods and writes usefull
26 debugging information to the stdout. The information includes a list of
27 resources that were extracted from the notebook(s) during export."""
28
29
30 def write(self, output, resources, notebook_name='notebook', **kw):
31 """
32 Consume and write Jinja output.
33
34 See base for more...
35 """
36
37 if isinstance(resources['outputs'], dict):
38 print("outputs extracted from %s" % notebook_name)
39 print('-' * 80)
40 pprint(resources['outputs'], indent=2, width=70)
41 else:
42 print("no outputs extracted from %s" % notebook_name)
43 print('=' * 80)
@@ -1,135 +0,0 b''
1 """Contains writer for writing nbconvert output to filesystem."""
2
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
5
6 import io
7 import os
8 import glob
9
10 from IPython.utils.traitlets import Unicode
11 from IPython.utils.path import link_or_copy, ensure_dir_exists
12 from IPython.utils.py3compat import unicode_type
13
14 from .base import WriterBase
15
16 #-----------------------------------------------------------------------------
17 # Classes
18 #-----------------------------------------------------------------------------
19
20 class FilesWriter(WriterBase):
21 """Consumes nbconvert output and produces files."""
22
23
24 build_directory = Unicode("", config=True,
25 help="""Directory to write output to. Leave blank
26 to output to the current directory""")
27
28 relpath = Unicode(
29 "", config=True,
30 help="""When copying files that the notebook depends on, copy them in
31 relation to this path, such that the destination filename will be
32 os.path.relpath(filename, relpath). If FilesWriter is operating on a
33 notebook that already exists elsewhere on disk, then the default will be
34 the directory containing that notebook.""")
35
36
37 # Make sure that the output directory exists.
38 def _build_directory_changed(self, name, old, new):
39 if new:
40 ensure_dir_exists(new)
41
42
43 def __init__(self, **kw):
44 super(FilesWriter, self).__init__(**kw)
45 self._build_directory_changed('build_directory', self.build_directory,
46 self.build_directory)
47
48 def _makedir(self, path):
49 """Make a directory if it doesn't already exist"""
50 if path:
51 self.log.info("Making directory %s", path)
52 ensure_dir_exists(path)
53
54 def write(self, output, resources, notebook_name=None, **kw):
55 """
56 Consume and write Jinja output to the file system. Output directory
57 is set via the 'build_directory' variable of this instance (a
58 configurable).
59
60 See base for more...
61 """
62
63 # Verify that a notebook name is provided.
64 if notebook_name is None:
65 raise TypeError('notebook_name')
66
67 # Pull the extension and subdir from the resources dict.
68 output_extension = resources.get('output_extension', None)
69
70 # Get the relative path for copying files
71 if self.relpath == '':
72 relpath = resources.get('metadata', {}).get('path', '')
73 else:
74 relpath = self.relpath
75
76 # Write all of the extracted resources to the destination directory.
77 # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG
78 # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS...
79
80 items = resources.get('outputs', {}).items()
81 if items:
82 self.log.info("Support files will be in %s", os.path.join(resources.get('output_files_dir',''), ''))
83 for filename, data in items:
84
85 # Determine where to write the file to
86 dest = os.path.join(self.build_directory, filename)
87 path = os.path.dirname(dest)
88 self._makedir(path)
89
90 # Write file
91 self.log.debug("Writing %i bytes to support file %s", len(data), dest)
92 with io.open(dest, 'wb') as f:
93 f.write(data)
94
95 # Copy referenced files to output directory
96 if self.build_directory:
97 for filename in self.files:
98
99 # Copy files that match search pattern
100 for matching_filename in glob.glob(filename):
101
102 # compute the relative path for the filename
103 if relpath != '':
104 dest_filename = os.path.relpath(matching_filename, relpath)
105 else:
106 dest_filename = matching_filename
107
108 # Make sure folder exists.
109 dest = os.path.join(self.build_directory, dest_filename)
110 path = os.path.dirname(dest)
111 self._makedir(path)
112
113 # Copy if destination is different.
114 if not os.path.normpath(dest) == os.path.normpath(matching_filename):
115 self.log.info("Linking %s -> %s", matching_filename, dest)
116 link_or_copy(matching_filename, dest)
117
118 # Determine where to write conversion results.
119 if output_extension is not None:
120 dest = notebook_name + output_extension
121 else:
122 dest = notebook_name
123 if self.build_directory:
124 dest = os.path.join(self.build_directory, dest)
125
126 # Write conversion results.
127 self.log.info("Writing %i bytes to %s", len(output), dest)
128 if isinstance(output, unicode_type):
129 with io.open(dest, 'w', encoding='utf-8') as f:
130 f.write(output)
131 else:
132 with io.open(dest, 'wb') as f:
133 f.write(output)
134
135 return dest
@@ -1,23 +0,0 b''
1 """
2 Contains Stdout writer
3 """
4
5 # Copyright (c) Jupyter Development Team.
6 # Distributed under the terms of the Modified BSD License.
7
8 from jupyter_nbconvert.utils import io
9 from .base import WriterBase
10
11
12 class StdoutWriter(WriterBase):
13 """Consumes output from nbconvert export...() methods and writes to the
14 stdout stream."""
15
16
17 def write(self, output, resources, **kw):
18 """
19 Consume and write Jinja output.
20
21 See base for more...
22 """
23 io.unicode_std_stream().write(output)
1 NO CONTENT: file was removed
NO CONTENT: file was removed
@@ -1,56 +0,0 b''
1 """
2 Module with tests for debug
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 import sys
18
19 from ...tests.base import TestsBase
20 from ..debug import DebugWriter
21 from IPython.utils.py3compat import PY3
22
23 if PY3:
24 from io import StringIO
25 else:
26 from StringIO import StringIO
27
28
29 #-----------------------------------------------------------------------------
30 # Class
31 #-----------------------------------------------------------------------------
32
33 class TestDebug(TestsBase):
34 """Contains test functions for debug.py"""
35
36 def test_output(self):
37 """Test debug writer output."""
38
39 # Capture the stdout. Remember original.
40 stdout = sys.stdout
41 stream = StringIO()
42 sys.stdout = stream
43
44 # Create stdout writer, get output
45 writer = DebugWriter()
46 writer.write('aaa', {'outputs': {'bbb': 'ccc'}})
47 output = stream.getvalue()
48
49 # Check output. Make sure resources dictionary is dumped, but nothing
50 # else.
51 assert 'aaa' not in output
52 assert 'bbb' in output
53 assert 'ccc' in output
54
55 # Revert stdout
56 sys.stdout = stdout No newline at end of file
@@ -1,307 +0,0 b''
1 """
2 Module with tests for files
3 """
4
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 import sys
18 import os
19
20 from ...tests.base import TestsBase
21 from ..files import FilesWriter
22 from IPython.utils.py3compat import PY3
23
24 if PY3:
25 from io import StringIO
26 else:
27 from StringIO import StringIO
28
29
30 #-----------------------------------------------------------------------------
31 # Class
32 #-----------------------------------------------------------------------------
33
34 class Testfiles(TestsBase):
35 """Contains test functions for files.py"""
36
37 def test_basic_output(self):
38 """Is FilesWriter basic output correct?"""
39
40 # Work in a temporary directory.
41 with self.create_temp_cwd():
42
43 # Create the resoruces dictionary
44 res = {}
45
46 # Create files writer, test output
47 writer = FilesWriter()
48 writer.write(u'y', res, notebook_name="z")
49
50 # Check the output of the file
51 with open('z', 'r') as f:
52 output = f.read()
53 self.assertEqual(output, u'y')
54
55 def test_ext(self):
56 """Does the FilesWriter add the correct extension to the output?"""
57
58 # Work in a temporary directory.
59 with self.create_temp_cwd():
60
61 # Create the resoruces dictionary
62 res = {'output_extension': '.txt'}
63
64 # Create files writer, test output
65 writer = FilesWriter()
66 writer.write(u'y', res, notebook_name="z")
67
68 # Check the output of the file
69 assert os.path.isfile('z.txt')
70 with open('z.txt', 'r') as f:
71 output = f.read()
72 self.assertEqual(output, u'y')
73
74
75 def test_extract(self):
76 """Can FilesWriter write extracted figures correctly?"""
77
78 # Work in a temporary directory.
79 with self.create_temp_cwd():
80
81 # Create the resoruces dictionary
82 res = {'outputs': {os.path.join('z_files', 'a'): b'b'}}
83
84 # Create files writer, test output
85 writer = FilesWriter()
86 writer.write(u'y', res, notebook_name="z")
87
88 # Check the output of the file
89 with open('z', 'r') as f:
90 output = f.read()
91 self.assertEqual(output, u'y')
92
93 # Check the output of the extracted file
94 extracted_file_dest = os.path.join('z_files', 'a')
95 assert os.path.isfile(extracted_file_dest)
96 with open(extracted_file_dest, 'r') as f:
97 output = f.read()
98 self.assertEqual(output, 'b')
99
100
101 def test_builddir(self):
102 """Can FilesWriter write to a build dir correctly?"""
103
104 # Work in a temporary directory.
105 with self.create_temp_cwd():
106
107 # Create the resoruces dictionary
108 res = {'outputs': {os.path.join('z_files', 'a'): b'b'}}
109
110 # Create files writer, test output
111 writer = FilesWriter()
112 writer.build_directory = u'build'
113 writer.write(u'y', res, notebook_name="z")
114
115 # Check the output of the file
116 assert os.path.isdir(writer.build_directory)
117 dest = os.path.join(writer.build_directory, 'z')
118 with open(dest, 'r') as f:
119 output = f.read()
120 self.assertEqual(output, u'y')
121
122 # Check the output of the extracted file
123 extracted_file_dest = os.path.join(writer.build_directory, 'z_files', 'a')
124 assert os.path.isfile(extracted_file_dest)
125 with open(extracted_file_dest, 'r') as f:
126 output = f.read()
127 self.assertEqual(output, 'b')
128
129
130 def test_links(self):
131 """Can the FilesWriter handle linked files correctly?"""
132
133 # Work in a temporary directory.
134 with self.create_temp_cwd():
135
136 # Create test file
137 os.mkdir('sub')
138 with open(os.path.join('sub', 'c'), 'w') as f:
139 f.write('d')
140
141 # Create the resoruces dictionary
142 res = {}
143
144 # Create files writer, test output
145 writer = FilesWriter()
146 writer.files = [os.path.join('sub', 'c')]
147 writer.build_directory = u'build'
148 writer.write(u'y', res, notebook_name="z")
149
150 # Check the output of the file
151 assert os.path.isdir(writer.build_directory)
152 dest = os.path.join(writer.build_directory, 'z')
153 with open(dest, 'r') as f:
154 output = f.read()
155 self.assertEqual(output, u'y')
156
157 # Check to make sure the linked file was copied
158 path = os.path.join(writer.build_directory, 'sub')
159 assert os.path.isdir(path)
160 dest = os.path.join(path, 'c')
161 assert os.path.isfile(dest)
162 with open(dest, 'r') as f:
163 output = f.read()
164 self.assertEqual(output, 'd')
165
166 def test_glob(self):
167 """Can the FilesWriter handle globbed files correctly?"""
168
169 # Work in a temporary directory.
170 with self.create_temp_cwd():
171
172 # Create test files
173 os.mkdir('sub')
174 with open(os.path.join('sub', 'c'), 'w') as f:
175 f.write('e')
176 with open(os.path.join('sub', 'd'), 'w') as f:
177 f.write('e')
178
179 # Create the resoruces dictionary
180 res = {}
181
182 # Create files writer, test output
183 writer = FilesWriter()
184 writer.files = ['sub/*']
185 writer.build_directory = u'build'
186 writer.write(u'y', res, notebook_name="z")
187
188 # Check the output of the file
189 assert os.path.isdir(writer.build_directory)
190 dest = os.path.join(writer.build_directory, 'z')
191 with open(dest, 'r') as f:
192 output = f.read()
193 self.assertEqual(output, u'y')
194
195 # Check to make sure the globbed files were copied
196 path = os.path.join(writer.build_directory, 'sub')
197 assert os.path.isdir(path)
198 for filename in ['c', 'd']:
199 dest = os.path.join(path, filename)
200 assert os.path.isfile(dest)
201 with open(dest, 'r') as f:
202 output = f.read()
203 self.assertEqual(output, 'e')
204
205 def test_relpath(self):
206 """Can the FilesWriter handle relative paths for linked files correctly?"""
207
208 # Work in a temporary directory.
209 with self.create_temp_cwd():
210
211 # Create test file
212 os.mkdir('sub')
213 with open(os.path.join('sub', 'c'), 'w') as f:
214 f.write('d')
215
216 # Create the resoruces dictionary
217 res = {}
218
219 # Create files writer, test output
220 writer = FilesWriter()
221 writer.files = [os.path.join('sub', 'c')]
222 writer.build_directory = u'build'
223 writer.relpath = 'sub'
224 writer.write(u'y', res, notebook_name="z")
225
226 # Check the output of the file
227 assert os.path.isdir(writer.build_directory)
228 dest = os.path.join(writer.build_directory, 'z')
229 with open(dest, 'r') as f:
230 output = f.read()
231 self.assertEqual(output, u'y')
232
233 # Check to make sure the linked file was copied
234 dest = os.path.join(writer.build_directory, 'c')
235 assert os.path.isfile(dest)
236 with open(dest, 'r') as f:
237 output = f.read()
238 self.assertEqual(output, 'd')
239
240 def test_relpath_default(self):
241 """Is the FilesWriter default relative path correct?"""
242
243 # Work in a temporary directory.
244 with self.create_temp_cwd():
245
246 # Create test file
247 os.mkdir('sub')
248 with open(os.path.join('sub', 'c'), 'w') as f:
249 f.write('d')
250
251 # Create the resoruces dictionary
252 res = dict(metadata=dict(path="sub"))
253
254 # Create files writer, test output
255 writer = FilesWriter()
256 writer.files = [os.path.join('sub', 'c')]
257 writer.build_directory = u'build'
258 writer.write(u'y', res, notebook_name="z")
259
260 # Check the output of the file
261 assert os.path.isdir(writer.build_directory)
262 dest = os.path.join(writer.build_directory, 'z')
263 with open(dest, 'r') as f:
264 output = f.read()
265 self.assertEqual(output, u'y')
266
267 # Check to make sure the linked file was copied
268 dest = os.path.join(writer.build_directory, 'c')
269 assert os.path.isfile(dest)
270 with open(dest, 'r') as f:
271 output = f.read()
272 self.assertEqual(output, 'd')
273
274 def test_relpath_default(self):
275 """Does the FilesWriter relpath option take precedence over the path?"""
276
277 # Work in a temporary directory.
278 with self.create_temp_cwd():
279
280 # Create test file
281 os.mkdir('sub')
282 with open(os.path.join('sub', 'c'), 'w') as f:
283 f.write('d')
284
285 # Create the resoruces dictionary
286 res = dict(metadata=dict(path="other_sub"))
287
288 # Create files writer, test output
289 writer = FilesWriter()
290 writer.files = [os.path.join('sub', 'c')]
291 writer.build_directory = u'build'
292 writer.relpath = 'sub'
293 writer.write(u'y', res, notebook_name="z")
294
295 # Check the output of the file
296 assert os.path.isdir(writer.build_directory)
297 dest = os.path.join(writer.build_directory, 'z')
298 with open(dest, 'r') as f:
299 output = f.read()
300 self.assertEqual(output, u'y')
301
302 # Check to make sure the linked file was copied
303 dest = os.path.join(writer.build_directory, 'c')
304 assert os.path.isfile(dest)
305 with open(dest, 'r') as f:
306 output = f.read()
307 self.assertEqual(output, 'd')
@@ -1,54 +0,0 b''
1 # coding: utf-8
2 """
3 Module with tests for stdout
4 """
5
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2013, the IPython Development Team.
8 #
9 # Distributed under the terms of the Modified BSD License.
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
13
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
17
18 import sys
19
20 from ...tests.base import TestsBase
21 from ..stdout import StdoutWriter
22 from IPython.utils.py3compat import PY3
23
24 if PY3:
25 from io import StringIO
26 else:
27 from StringIO import StringIO
28
29
30 #-----------------------------------------------------------------------------
31 # Class
32 #-----------------------------------------------------------------------------
33
34 class TestStdout(TestsBase):
35 """Contains test functions for stdout.py"""
36
37 def test_output(self):
38 """Test stdout writer output."""
39
40 # Capture the stdout. Remember original.
41 stdout = sys.stdout
42 stream = StringIO()
43 sys.stdout = stream
44
45 # Create stdout writer, test output
46 writer = StdoutWriter()
47 writer.write(u'a×', {'b': 'c'})
48 output = stream.getvalue()
49 if not PY3:
50 output = output.decode('utf-8')
51 self.fuzzy_compare(output, u'a×')
52
53 # Revert stdout
54 sys.stdout = stdout No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now