JuPyTer-notebook (empty) → 0.1.0.0
raw patch · 7 files changed
+308/−0 lines, 7 filesdep +JuPyTer-notebookdep +aesondep +basesetup-changed
Dependencies added: JuPyTer-notebook, aeson, base, bytestring, json-autotype, text
Files
- ChangeLog.md +6/−0
- JuPyTer-notebook.cabal +45/−0
- LICENSE +30/−0
- README.md +13/−0
- Setup.hs +2/−0
- src/Data/JuPyTer.hs +173/−0
- src/Main.hs +39/−0
+ ChangeLog.md view
@@ -0,0 +1,6 @@+# Revision history for IPyNb++0.1.0.0 -- 2017-11-21++ * First version. Released on an unsuspecting world.+
+ JuPyTer-notebook.cabal view
@@ -0,0 +1,45 @@+-- Initial IPyNb.cabal generated by cabal init. For further documentation,+-- see http://haskell.org/cabal/users-guide/++name: JuPyTer-notebook+version: 0.1.0.0+synopsis: JuPyTer notebook parser+description: JuPyTer also called IPython notebook.+ .+ It is cross-language interactive data science platform+ that allows for interactive editing of code and visualizing its results.+ .+ This library allows to directly parse `.ipynb` files, and process them.+homepage: http://github.com/mgajda/ipynb+cabal-version: >=1.10+license: BSD3+license-file: LICENSE+author: Michal J. Gajda+maintainer: migamake@migamake.com+category: Data+build-type: Simple+extra-source-files: ChangeLog.md+ README.md+source-repository head+ type: git+ location: https://github.com/mgajda/jupyter-notebook.git++library+ build-depends: base >=4.9 && <4.10,+ json-autotype >=1.0 && <2.0+ hs-source-dirs: src+ exposed-modules: Data.JuPyTer+ default-language: Haskell2010++executable jupyter-extract+ hs-source-dirs: src+ main-is: Main.hs+ --other-modules: Data.+ --other-extensions: TemplateHaskell,+ build-depends: base >=4.3 && <4.11,+ text >=1.0 && <1.3,+ json-autotype >=1.0 && <1.1,+ aeson >=1.0 && <1.3,+ bytestring >=0.10 && <1.0,+ JuPyTer-notebook+ default-language: Haskell2010
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Michal J. Gajda++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Michal J. Gajda nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,13 @@+JuPyTer notebook parser+=======================+[JuPyTer](https://jupyter.org/) was formerly called IPython notebook.++It is cross-language interactive data science platform+that allows for interactive editing of code and visualizing its results.++This library allows to directly parse `.ipynb` files, and process them.++There is an example script `jupyter-extract` that just extracts+all the source code cells, and prints them.++Initial version was generated with [`json-autotype`](https://hackage.haskell.org/package/json-autotype)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Data/JuPyTer.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DeriveGeneric #-}++module Data.JuPyTer where++import System.Exit (exitFailure, exitSuccess)+import System.IO (stderr, hPutStrLn)+import qualified Data.ByteString.Lazy.Char8 as BSL+import System.Environment (getArgs)+import Control.Monad (forM_, mzero, join)+import Control.Applicative+import Data.Aeson.AutoType.Alternative+import Data.Aeson(decode, Value(..), FromJSON(..), ToJSON(..),+ pairs,+ (.:), (.:?), (.=), object)+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as Text+import qualified GHC.Generics++-- | Workaround for https://github.com/bos/aeson/issues/287.+o .:?? val = fmap join (o .:? val)+++data CodemirrorMode = CodemirrorMode { + codemirrorModeName :: Text,+ codemirrorModeVersion :: Double+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON CodemirrorMode where+ parseJSON (Object v) = CodemirrorMode <$> v .: "name" <*> v .: "version"+ parseJSON _ = mzero+++instance ToJSON CodemirrorMode where+ toJSON (CodemirrorMode {..}) = object ["name" .= codemirrorModeName, "version" .= codemirrorModeVersion]+ toEncoding (CodemirrorMode {..}) = pairs ("name" .= codemirrorModeName<>"version" .= codemirrorModeVersion)+++data LanguageInfo = LanguageInfo { + languageInfoNbconvertExporter :: Text,+ languageInfoFileExtension :: Text,+ languageInfoPygmentsLexer :: Text,+ languageInfoMimetype :: Text,+ languageInfoName :: Text,+ languageInfoVersion :: Text,+ languageInfoCodemirrorMode :: CodemirrorMode+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON LanguageInfo where+ parseJSON (Object v) = LanguageInfo <$> v .: "nbconvert_exporter" <*> v .: "file_extension" <*> v .: "pygments_lexer" <*> v .: "mimetype" <*> v .: "name" <*> v .: "version" <*> v .: "codemirror_mode"+ parseJSON _ = mzero+++instance ToJSON LanguageInfo where+ toJSON (LanguageInfo {..}) = object ["nbconvert_exporter" .= languageInfoNbconvertExporter, "file_extension" .= languageInfoFileExtension, "pygments_lexer" .= languageInfoPygmentsLexer, "mimetype" .= languageInfoMimetype, "name" .= languageInfoName, "version" .= languageInfoVersion, "codemirror_mode" .= languageInfoCodemirrorMode]+ toEncoding (LanguageInfo {..}) = pairs ("nbconvert_exporter" .= languageInfoNbconvertExporter<>"file_extension" .= languageInfoFileExtension<>"pygments_lexer" .= languageInfoPygmentsLexer<>"mimetype" .= languageInfoMimetype<>"name" .= languageInfoName<>"version" .= languageInfoVersion<>"codemirror_mode" .= languageInfoCodemirrorMode)+++data Kernelspec = Kernelspec { + kernelspecDisplayName :: Text,+ kernelspecName :: Text,+ kernelspecLanguage :: Text+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON Kernelspec where+ parseJSON (Object v) = Kernelspec <$> v .: "display_name" <*> v .: "name" <*> v .: "language"+ parseJSON _ = mzero+++instance ToJSON Kernelspec where+ toJSON (Kernelspec {..}) = object ["display_name" .= kernelspecDisplayName, "name" .= kernelspecName, "language" .= kernelspecLanguage]+ toEncoding (Kernelspec {..}) = pairs ("display_name" .= kernelspecDisplayName<>"name" .= kernelspecName<>"language" .= kernelspecLanguage)+++data Slideshow = Slideshow { + slideshowSlideType :: Text+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON Slideshow where+ parseJSON (Object v) = Slideshow <$> v .: "slide_type"+ parseJSON _ = mzero+++instance ToJSON Slideshow where+ toJSON (Slideshow {..}) = object ["slide_type" .= slideshowSlideType]+ toEncoding (Slideshow {..}) = pairs ("slide_type" .= slideshowSlideType)+++data Metadata = Metadata { + metadataScrolled :: (Maybe (Bool:|:[(Maybe Value)])),+ metadataCelltoolbar :: (Maybe (Text:|:[(Maybe Value)])),+ metadataLanguageInfo :: (Maybe (LanguageInfo:|:[(Maybe Value)])),+ metadataKernelspec :: (Maybe (Kernelspec:|:[(Maybe Value)])),+ metadataEditable :: (Maybe (Bool:|:[(Maybe Value)])),+ metadataDeletable :: (Maybe (Bool:|:[(Maybe Value)])),+ metadataSlideshow :: (Maybe (Slideshow:|:[(Maybe Value)])),+ metadataCollapsed :: (Maybe (Bool:|:[(Maybe Value)]))+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON Metadata where+ parseJSON (Object v) = Metadata <$> v .:?? "scrolled" <*> v .:?? "celltoolbar" <*> v .:?? "language_info" <*> v .:?? "kernelspec" <*> v .:?? "editable" <*> v .:?? "deletable" <*> v .:?? "slideshow" <*> v .:?? "collapsed"+ parseJSON _ = mzero+++instance ToJSON Metadata where+ toJSON (Metadata {..}) = object ["scrolled" .= metadataScrolled, "celltoolbar" .= metadataCelltoolbar, "language_info" .= metadataLanguageInfo, "kernelspec" .= metadataKernelspec, "editable" .= metadataEditable, "deletable" .= metadataDeletable, "slideshow" .= metadataSlideshow, "collapsed" .= metadataCollapsed]+ toEncoding (Metadata {..}) = pairs ("scrolled" .= metadataScrolled<>"celltoolbar" .= metadataCelltoolbar<>"language_info" .= metadataLanguageInfo<>"kernelspec" .= metadataKernelspec<>"editable" .= metadataEditable<>"deletable" .= metadataDeletable<>"slideshow" .= metadataSlideshow<>"collapsed" .= metadataCollapsed)++data CellsElt = CellsElt { + cellsEltExecutionCount :: (Maybe (Double:|:[(Maybe Value)])),+ cellsEltOutputs :: (Maybe ([[(Maybe Value)]])),+ cellsEltMetadata :: Metadata,+ cellsEltSource :: [Text:|:[(Maybe Value)]],+ cellsEltCellType :: Text+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON CellsElt where+ parseJSON (Object v) = CellsElt <$> v .:?? "execution_count" <*> v .:?? "outputs" <*> v .: "metadata" <*> v .: "source" <*> v .: "cell_type"+ parseJSON _ = mzero+++instance ToJSON CellsElt where+ toJSON (CellsElt {..}) = object ["execution_count" .= cellsEltExecutionCount, "outputs" .= cellsEltOutputs, "metadata" .= cellsEltMetadata, "source" .= cellsEltSource, "cell_type" .= cellsEltCellType]+ toEncoding (CellsElt {..}) = pairs ("execution_count" .= cellsEltExecutionCount<>"outputs" .= cellsEltOutputs<>"metadata" .= cellsEltMetadata<>"source" .= cellsEltSource<>"cell_type" .= cellsEltCellType)++data IPyNb = IPyNb { + iPyNbNbformatMinor :: Double,+ iPyNbNbformat :: Double,+ iPyNbCells :: [CellsElt],+ iPyNbMetadata :: Metadata+ } deriving (Show,Eq,GHC.Generics.Generic)+++instance FromJSON IPyNb where+ parseJSON (Object v) = IPyNb <$> v .: "nbformat_minor" <*> v .: "nbformat" <*> v .: "cells" <*> v .: "metadata"+ parseJSON _ = mzero+++instance ToJSON IPyNb where+ toJSON (IPyNb {..}) = object ["nbformat_minor" .= iPyNbNbformatMinor, "nbformat" .= iPyNbNbformat, "cells" .= iPyNbCells, "metadata" .= iPyNbMetadata]+ toEncoding (IPyNb {..}) = pairs ("nbformat_minor" .= iPyNbNbformatMinor<>"nbformat" .= iPyNbNbformat<>"cells" .= iPyNbCells<>"metadata" .= iPyNbMetadata)+++++parse :: FilePath -> IO IPyNb+parse filename = do input <- BSL.readFile filename+ case decode input of+ Nothing -> fatal $ case (decode input :: Maybe Value) of+ Nothing -> "Invalid JSON file: " ++ filename+ Just v -> "Mismatched JSON value from file: " ++ filename+ Just r -> return (r :: IPyNb)+ where+ fatal :: String -> IO a+ fatal msg = do hPutStrLn stderr msg+ exitFailure++main :: IO ()+main = do+ filenames <- getArgs+ forM_ filenames (\f -> parse f >>= (\p -> p `seq` putStrLn $ "Successfully parsed " ++ f))+ exitSuccess
+ src/Main.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DeriveGeneric #-}++module Main(main) where++import System.Exit (exitFailure, exitSuccess)+import System.IO (stderr, hPutStrLn)+import qualified Data.ByteString.Lazy.Char8 as BSL+import System.Environment (getArgs)+import Control.Monad (forM_, mzero, join)+import Control.Applicative+import Data.Aeson.AutoType.Alternative+import Data.Aeson(decode, Value(..), FromJSON(..), ToJSON(..),+ pairs,+ (.:), (.:?), (.=), object)+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as Text+import qualified GHC.Generics++import Data.JuPyTer(IPyNb(..), CellsElt(..), parse)++main :: IO ()+main = do+ filenames <- getArgs+ forM_ filenames (\f -> parse f >>= (\p -> p `seq` putStrLn $ "Successfully parsed " ++ f+ ++ ":\n" ++ extract p))+ exitSuccess++extract :: IPyNb -> String+extract = unlines+ . map (concatMap (alt Text.unpack show)+ . cellsEltSource)+ . iPyNbCells+