Commit 9e8642f2 authored by Mads M. Pedersen's avatar Mads M. Pedersen
Browse files

fix documentation ci

parent fdc55e44
......@@ -36,23 +36,25 @@ pages: # "pages" is a job specifically for GitLab pages [1]
deploy
script: # use sphinx to build docs, move to public page
- pip install sphinx --upgrade
- pip install nbsphinx==0.3.5
- pip install git+https://github.com/vidartf/nbsphinx-link.git
- pip install nbsphinx --upgrade
- pip install -e .
- cd docs/source/validation_report
- python tests.py
- cd docs/validation_report
- python generate_validation_figures.py
- cd report
- apt-get install -y texlive-latex-extra
- pdflatex validation_report.tex
- bibtex validation_report.aux
- pdflatex validation_report.tex
- pdflatex validation_report.tex
- cd ../../../../
- cd docs; make html
- cd ../../
- pwd
- make html
#- make latexpdf
- cd ../; mv docs/build/html public/
artifacts: # required for GitLab pages [1]
paths:
- public
#- docs/build/latex/PyWake.pdf
only: # only run for these branches
- master
- /^test_doc.*/
......
......@@ -5,7 +5,7 @@
SPHINXOPTS =
SPHINXBUILD = python -msphinx
SPHINXPROJ = PyWake
SOURCEDIR = source
SOURCEDIR = .
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="dw_cw.svg"
inkscape:export-filename="C:\mmpe\programming\python\Topfarm\PyWake\docs\source\_static\dw_cw.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2">
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker2604"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path2602"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="marker2516"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path2514"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) translate(6,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker2228"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Send">
<path
transform="scale(0.2) rotate(180) translate(6,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path2226" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker2158"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Sstart">
<path
transform="scale(0.2) translate(6,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path2156" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker2043"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path2041"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Sstart"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path833"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) translate(6,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker1577"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend">
<path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path1575" />
</marker>
<marker
inkscape:stockid="Arrow2Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mend"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path848"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) rotate(180) translate(0,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path836"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="marker1327"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1325"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path842"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="marker1105"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path1103"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path839"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) translate(1,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.64144687"
inkscape:cx="-39.918551"
inkscape:cy="709.9846"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
id="path10"
cx="71.815475"
cy="48.291664"
r="2.725625"
style="stroke-width:0.26458332" />
<circle
style="stroke-width:0.26458332"
r="2.725625"
cy="115.38244"
cx="108.10119"
id="circle12" />
<path
style="fill:none;stroke:#000000;stroke-width:1.265;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
d="M 142.30803,27.313988 127.18899,56.985119"
id="path14"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path1573"
d="M 70.492554,49.992559 51.698081,86.876732"
style="fill:none;stroke:#000000;stroke-width:0.76499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.295, 0.765;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
style="fill:none;stroke:#000000;stroke-width:0.76499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.295, 0.765;stroke-dashoffset:0;stroke-opacity:1"
d="M 107.85099,115.26278 51.52946,86.563913"
id="path1975"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cc"
style="fill:none;stroke:#000000;stroke-width:0.765;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#Arrow1Sstart);marker-end:url(#marker2043)"
d="M 61.799102,43.566964 43.004629,80.451137"
id="path1977"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path2326"
d="M 103.84445,123.20028 47.522913,94.501413"
style="fill:none;stroke:#000000;stroke-width:0.76499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker2516);marker-end:url(#marker2604)"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="153.00131"
y="39.494705"
id="text2740"><tspan
sodipodi:role="line"
id="tspan2738"
x="154.0121"
y="39.494705"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.26458332">Wind </tspan><tspan
sodipodi:role="line"
x="153.00131"
y="47.432205"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.26458332"
id="tspan2742">direction</tspan></text>
<text
id="text2748"
y="50.219158"
x="19.645741"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
id="tspan2746"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332"
y="50.219158"
x="19.645741"
sodipodi:role="line">Down wind </tspan><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332"
y="58.156658"
x="19.645741"
sodipodi:role="line"
id="tspan2752">distance</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="35.319942"
y="112.91596"
id="text2806"><tspan
id="tspan2804"
sodipodi:role="line"
x="35.319942"
y="112.91596"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332">cross wind </tspan><tspan
sodipodi:role="line"
x="35.319942"
y="120.85346"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332"
id="tspan2996">distance</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="72.183823"
y="35.075863"
id="text3000"><tspan
sodipodi:role="line"
id="tspan2998"
x="72.183823"
y="44.439632"
style="stroke-width:0.26458332"></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="64.605949"
y="41.144623"
id="text3006"><tspan
id="tspan3004"
sodipodi:role="line"
x="64.605949"
y="41.144623"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332">Source</tspan><tspan
sodipodi:role="line"
x="64.605949"
y="49.082123"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332"
id="tspan3010" /></text>
<text
id="text3016"
y="117.86571"
x="114.92838"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332"
y="117.86571"
x="114.92838"
sodipodi:role="line"
id="tspan3012">Destination</tspan><tspan
id="tspan3014"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3499999px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332"
y="125.80321"
x="114.92838"
sodipodi:role="line" /></text>
</g>
</svg>
......@@ -51,6 +51,7 @@ extensions = [
'sphinx.ext.inheritance_diagram',
'nbsphinx',
'sphinx.ext.doctest',
#'sphinx.ext.imgconverter',
]
intersphinx_mapping = {
......@@ -127,6 +128,7 @@ nbsphinx_timeout = 180
nbsphinx_prolog = r"""
{% set docname = 'docs/' + env.doc2path(env.docname, base=None) %}
.. only:: html
.. role:: raw-html(raw)
......@@ -134,8 +136,9 @@ nbsphinx_prolog = r"""
.. nbinfo::
Interactive online version:
:raw-html:`<a href="https://colab.research.google.com/github/DTUWindEnergy/PyWake/blob/master/{{ docname }}"><img alt="Open In Colab" src="https://colab.research.google.com/assets/colab-badge.svg" style="vertical-align:text-bottom"></a>`
:raw-html:`<a href="https://colab.research.google.com/github/DTUWindEnergy/PyWake/blob/master/{{ docname }}"><img alt="Open and run in Colab (interactive)" src="https://colab.research.google.com/assets/colab-badge.svg" style="vertical-align:text-bottom"></a>
<a href="https://gitlab.windenergy.dtu.dk/TOPFARM/PyWake/-/tree/master/{{ docname }}"><img alt="Edit on Gitlab" src="https://img.shields.io/badge/Edit%20on-Gitlab-blue?style=flat&logo=gitlab" style="vertical-align:text-bottom"></a>`
"""
......
This diff is collapsed.
from pathlib import Path
import os
def svg2eps(f, replace=lambda s: s.replace(".svg", ".eps")):
txt = replace(f.read_text(encoding='utf-8')).replace("\r", "")
with open(f, 'w', encoding='utf-8', newline='\n') as fid:
fid.write(txt)
if __name__ == '__main__':
import py_wake
docs_path = Path(py_wake.__file__).parents[1] / 'docs'
if os.path.isdir(docs_path / 'api'):
for ext in ['*.rst', 'notebooks/*.ipynb']:
for f in docs_path.glob(ext):
svg2eps(f)
(docs_path / 'api').rename("api_hide")
else:
for ext in ['*.rst', 'notebooks/*.ipynb']:
for f in docs_path.glob(ext):
svg2eps(f, lambda s: s.replace('.eps', '.svg'))
(docs_path / 'api_hide').rename("api")
import json
import os
from os.path import dirname
from os.path import join as pjoin
import re
import ssl
import sys
class Notebook():
def __init__(self, filename):
self.filename = filename
try:
self.nb = self.load_notebook(self.filename)
except Exception as e:
raise Exception('Error in ', os.path.relpath(filename)) from e
def load_notebook(self, filename):
with open(filename, encoding='utf-8') as fid:
nb = json.load(fid)
return nb
def save(self, filename=None):
filename = filename or self.filename
with open(filename, 'w') as fid:
json.dump(self.nb, fid, indent=4)
def __getitem__(self, key):
return self.nb[key]
def __setitem__(self, key, value):
self.nb[key] = value
def __getattribute__(self, name):
try:
return object.__getattribute__(self, name)
except AttributeError:
if name in self.nb.keys():
return self.nb[name]
raise
def insert_markdown_cell(self, index, text):
self.cells.insert(index, {"cell_type": "markdown",
"metadata": {},
"source": [l + "\n" for l in text.split("\n")]
})
def insert_code_cell(self, index, code):
self.cells.insert(index,
{"cell_type": "code",
"execution_count": 0,
"metadata": {},
"outputs": [],
"source": [l + "\n" for l in code.split("\n")]
})
def replace_include_tag(self):
cells = []
for cell in self.nb['cells']:
if cell['cell_type'] == 'code' and len(cell['source']) > 0 and '%%include' in cell['source'][0]:
filename = pjoin(dirname(self.filename), cell['source'][0].replace('%%include', '').strip())
nb = Notebook(filename)
nb.replace_include_tag()
cells.extend(nb.cells)
else:
cells.append(cell)
return cells
def get_code(self):
code = []
for cell in self.cells:
if cell['cell_type'] == "code":
if "".join(cell['source']).strip() != "":
code.append("".join(cell['source']))
return code
def get_text(self):
txt = []
for cell in self.cells:
if cell['cell_type'] == "markdown":
if "".join(cell['source']).strip() != "":
txt.append("".join(cell['source']))
return txt
def check_code(self):
code = "\n".join(self.get_code())
def fix(line):
for p in ['%', '!']:
if line.strip().startswith(p):
line = line.replace(p, "pass #")
return line
lines = [fix(l) for l in code.split("\n")]
if len(lines) == 1 and lines[0] == '':
return
try:
import contextlib
with contextlib.redirect_stdout(None):
with contextlib.redirect_stderr(None):
exec("def test():\n " + "\n ".join(lines) + "\ntest()", {}, {})
except Exception as e:
raise type(e)("Code error in %s\n%s\n" % (self.filename, str(e))).with_traceback(sys.exc_info()[2])
def check_links(self):
txt = "\n".join(self.get_text())
for link in re.finditer(r"\[([^]]*)]\(([^)]*)\)", txt):
label, url = link.groups()
# print(label)
# print(url)
if url.startswith('attachment') or url.startswith("#"):
continue
if url.startswith("../_static"):
assert os.path.isfile(os.path.join(os.path.dirname(self.filename), url))
return
try:
import urllib.request
context = ssl._create_unverified_context()
assert urllib.request.urlopen(url, context=context).getcode() == 200
except Exception as e:
print("%s broken in %s\n%s" %