Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: unliterate() #106

Open
PaulSoderlind opened this issue May 4, 2020 · 7 comments
Open

Feature request: unliterate() #106

PaulSoderlind opened this issue May 4, 2020 · 7 comments

Comments

@PaulSoderlind
Copy link

Just so this (from Julia Discourse) does not get lost: have you considered adding an unliterate()?

@PaulSoderlind
Copy link
Author

from your reply on Discourse:
See also https://github.com/oxinabox/ipynb2LiterateJulia

@fredrikekre
Copy link
Owner

Just pasting a link to the referenced discourse post: https://discourse.julialang.org/t/way-to-add-tests-that-utilize-jupyter-notebooks/38341/6

@PaulSoderlind
Copy link
Author

PaulSoderlind commented Feb 21, 2021

Maybe also relevant: ipynb2LiterateJulia does not work with the new nbconvert, see oxinabox/ipynb2LiterateJulia#8

@PaulSoderlind
Copy link
Author

PaulSoderlind commented Mar 4, 2021

To soothe my mind (after a certain cross country relay) I attempted a rewrite of the archived JuliaAcademy material. The simple code below actually allows for a roundtrip (Literate.notebook(),unliterate(),...) without changing anything. Since my notebooks do not contain any important metadata, I did not implement anything for that.

"""
    unliterate(input,outputdir=pwd())

Convert a ipynb notebook to a jl script. Based on code from the Julia Academy, but simplified.
If input is a directory, then all notebooks in that directly are converted.

"""
function unliterate(input,outputdir=pwd())

  !isdir(outputdir) && error("$outputdir is not a directory")

  if isdir(input)
    Files = filter(x->splitext(x)[2]==".ipynb", readdir(input,join=true))  #all .ipynb files
    for file in Files
      unliterate(file,outputdir)
    end
    return
  end

  outputfile = joinpath(outputdir, splitext(basename(input))[1] * ".jl")
  println(input,"\n",outputfile,"\n")

  nb = open(JSON.parse,input, "r")
  ioscript = IOBuffer()

  prev_type = ""
  for cell in nb["cells"]

    cell["cell_type"] == prev_type && print(ioscript, "#-\n\n")

    #if !isempty(cell["metadata"])
    #  println(cell["metadata"])
    #  @warn("Still not implemented. Use parse_nbmeta here?")
    #end

    if cell["cell_type"] == "markdown"
      for line in cell["source"]
        print(ioscript, "# ", line)
      end
    elseif cell["cell_type"] == "code"
      for line in cell["source"]
        line_i = lstrip(line)
        if startswith(line_i, "#") && !startswith(line_i, "##")
          print(ioscript, "#", line_i)
        else
          print(ioscript, line)
        end
      end
    end

    print(ioscript,"\n\n")
    prev_type = cell["cell_type"]

  end

  content = String(take!(ioscript))
  open(outputfile, "w") do io
    print(io, content)
  end

  return

end
#------------------------------------------------------------------------------


@PaulSoderlind
Copy link
Author

and from stevengj's answer at discourse (https://discourse.julialang.org/t/export-jupyter-to-jl-does-not-preserve-markdown-cells/57556)

using JSON, Markdown

function ipynb2jl(ipynfile)
    jlfile = replace(ipynfile, r"(\.ipynb)?$" => ".jl")
    nb = open(JSON.parse, ipynfile, "r")
    open(jlfile, "w") do f
        for cell in nb["cells"]
            if cell["cell_type"] == "code"
                print(f, "\n\n")
                print.(Ref(f), cell["source"])
            elseif cell["cell_type"] == "markdown"
                md = Markdown.parse(join(cell["source"]))
                print(f, "\n\n# ", replace(repr("text/plain", md), '\n' => "\n# "))
            end
        end
    end
end

@miguelraz
Copy link

@PaulSoderlind thanks a million, I just found this - you've saved me a lot of hassle.

@kbarros
Copy link
Contributor

kbarros commented Oct 24, 2022

The package NBInclude provides a function nbexport(filename, notebookfile) that generates a .jl from a .pynb.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants