nbparts-0.1.0.0: src/Nbparts/Types/Error.hs
module Nbparts.Types.Error where
import Commonmark qualified
import Control.Exception qualified as Exception
import Data.Ord qualified as Ord
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Version qualified as Data
import Data.Version qualified as Version
import Data.Yaml qualified as Yaml
import Nbparts.Types.Manifest qualified as Manifest
import Text.Megaparsec qualified as Megaparsec
import Text.Parsec (errorPos)
recommendedNotebookFormat :: (Int, Int)
recommendedNotebookFormat = (4, 5)
data NbpartsError = UnpackError UnpackError | PackError PackError
deriving (Show, Eq)
data UnpackError
= UnpackParseNotebookError Text
| UnpackParseMarkdownError Commonmark.ParseError
| UnpackUnsupportedNotebookFormat (Int, Int)
| UnpackMissingCellIdError
deriving (Show, Eq)
data PackError
= PackUnsupportedNotebookFormat (Int, Int)
| PackParseManifestError ParseYamlError
| PackManifestUnknownVersionError Data.Version
| PackIllegalFormatError IllegalFormatContext Manifest.Format
| PackParseYamlSourcesError ParseYamlError
| PackParseJsonSourcesError Text
| PackParseMarkdownSourcesError (Megaparsec.ParseErrorBundle Text ParseMarkdownSourcesError)
| PackParseYamlMetadataError ParseYamlError
| PackParseJsonMetadataError Text
| PackParseYamlOutputsError ParseYamlError
| PackParseJsonOutputsError Text
| PackMissingCellIdError
| PackCellMetadataTypeMismatch {expected :: CellMetadataTag, actual :: CellMetadataTag}
deriving (Show, Eq)
-- Wrapper so that we can make an `Eq` instance.
newtype ParseYamlError = ParseYamlError Yaml.ParseException
deriving (Show)
-- The author of `yaml` performs equality checks with the `Show` instance as well,
-- so this should be fine. https://github.com/snoyberg/yaml/issues/189
instance Eq ParseYamlError where
a == b = show a == show b
data IllegalFormatContext = IllegalFormatSources | IllegalFormatMetadata | IllegalFormatOutputs
deriving (Show, Eq, Ord)
data ParseMarkdownSourcesError
= ParseMarkdownSourcesJsonError Text
| ParseMarkdownSourcesMarkdownError Commonmark.ParseError
deriving (Show, Eq)
instance Ord ParseMarkdownSourcesError where
compare (ParseMarkdownSourcesMarkdownError mdErr1) (ParseMarkdownSourcesMarkdownError mdErr2) =
compare (errorPos mdErr1) (errorPos mdErr2)
compare (ParseMarkdownSourcesJsonError t1) (ParseMarkdownSourcesJsonError t2) = compare t1 t2
compare _ _ = Ord.EQ
data CellMetadataTag = CodeCellMetadataTag | GenericCellMetadataTag
deriving (Show, Eq, Ord)
instance Megaparsec.ShowErrorComponent ParseMarkdownSourcesError where
showErrorComponent (ParseMarkdownSourcesJsonError msg) =
"Invalid JSON in nbparts cell marker: " <> Text.unpack msg
showErrorComponent (ParseMarkdownSourcesMarkdownError mdErr) =
"Failed to parse markdown: " <> show mdErr
renderError :: NbpartsError -> Text
renderError err = case err of
UnpackError (UnpackParseNotebookError message) -> "Failed to parse notebook: " <> message
UnpackError (UnpackParseMarkdownError mdErr) -> "Failed to parse markdown: " <> Text.pack (show mdErr)
UnpackError (UnpackUnsupportedNotebookFormat (major, minor)) ->
"Unsupported notebook format: "
<> Text.pack (show major)
<> "."
<> Text.pack (show minor)
UnpackError UnpackMissingCellIdError ->
"Notebook contains cell(s) without an identifier. Try upgrading your notebook to at least version "
<> Text.pack (show $ fst recommendedNotebookFormat)
<> "."
<> Text.pack (show $ snd recommendedNotebookFormat)
<> "."
PackError (PackUnsupportedNotebookFormat (major, minor)) ->
"Unsupported notebook format: "
<> Text.pack (show major)
<> "."
<> Text.pack (show minor)
PackError (PackParseManifestError (ParseYamlError ex)) -> "Failed to parse manifest: " <> Text.pack (Exception.displayException ex)
PackError (PackManifestUnknownVersionError version) -> "Unknown manifest version: " <> Text.pack (Version.showVersion version)
PackError (PackIllegalFormatError ctx fmt) -> "Illegal format for " <> renderIllegalFormatContext ctx <> ":" <> renderFormat fmt
PackError (PackParseYamlSourcesError (ParseYamlError ex)) -> "Failed to parse sources: " <> Text.pack (Exception.displayException ex)
PackError (PackParseJsonSourcesError parseErr) -> "Failed to parse sources: " <> parseErr
PackError (PackParseMarkdownSourcesError errBundle) -> Text.pack $ Megaparsec.errorBundlePretty errBundle
PackError (PackParseYamlMetadataError (ParseYamlError ex)) -> "Failed to parse metadata: " <> Text.pack (Exception.displayException ex)
PackError (PackParseJsonMetadataError parseErr) -> "Failed to parse metadata: " <> parseErr
PackError (PackParseYamlOutputsError (ParseYamlError ex)) -> "Failed to parse outputs: " <> Text.pack (Exception.displayException ex)
PackError (PackParseJsonOutputsError parseErr) -> "Failed to parse outputs: " <> parseErr
PackError PackMissingCellIdError -> "Markdown content contains missing cell ID"
PackError (PackCellMetadataTypeMismatch expected actual) ->
"Cell metadata type mismatch. Expected: "
<> renderCellMetadataTag expected
<> ", but got: "
<> renderCellMetadataTag actual
renderFormat :: Manifest.Format -> Text
renderFormat Manifest.FormatYaml = "yaml"
renderFormat Manifest.FormatJson = "json"
renderFormat Manifest.FormatMarkdown = "markdown"
renderIllegalFormatContext :: IllegalFormatContext -> Text
renderIllegalFormatContext IllegalFormatSources = "sources"
renderIllegalFormatContext IllegalFormatMetadata = "metadata"
renderIllegalFormatContext IllegalFormatOutputs = "outputs"
renderCellMetadataTag :: CellMetadataTag -> Text
renderCellMetadataTag CodeCellMetadataTag = "code cell metadata"
renderCellMetadataTag GenericCellMetadataTag = "generic cell metadata"