pandoc-pyplot 2.1.0.0 → 2.1.0.1
raw patch · 9 files changed
+171/−116 lines, 9 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ Text.Pandoc.Filter.Pyplot: EPS :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: GIF :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: JPG :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: PDF :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: PNG :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: SVG :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: TIF :: SaveFormat
+ Text.Pandoc.Filter.Pyplot: data SaveFormat
+ Text.Pandoc.Filter.Pyplot: type PythonScript = Text
Files
- CHANGELOG.md +6/−0
- executable/Main.hs +4/−5
- pandoc-pyplot.cabal +4/−3
- src/Text/Pandoc/Filter/Pyplot.hs +34/−2
- src/Text/Pandoc/Filter/Pyplot/Configuration.hs +3/−31
- src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs +2/−58
- src/Text/Pandoc/Filter/Pyplot/Internal.hs +3/−1
- src/Text/Pandoc/Filter/Pyplot/Scripting.hs +7/−16
- src/Text/Pandoc/Filter/Pyplot/Types.hs +108/−0
CHANGELOG.md view
@@ -2,6 +2,12 @@ pandoc-pyplot uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html) +Release 2.1.0.1 +--------------- + +* Fixed outdated documentation (referencing "target" parameter) +* Fixed types required to build Configuration values that were not exported (SaveFormat, PythonScript) + Release 2.1.0.0 ---------------
executable/Main.hs view
@@ -8,8 +8,7 @@ import System.Environment (getArgs) import System.Directory (doesFileExist) -import Text.Pandoc.Filter.Pyplot (makePlotWithConfig, configuration) -import Text.Pandoc.Filter.Pyplot.Internal (SaveFormat(..)) +import Text.Pandoc.Filter.Pyplot (plotTransformWithConfig, configuration, SaveFormat(..)) import Text.Pandoc.JSON (toJSONFilter) import qualified Data.Version as V @@ -31,10 +30,10 @@ \ Optional arguments:\n\ \ -h, --help Show this help message and exit\n\ \ -v, --version Show version number and exit \n\ - \ -f, --formats Show available output figure formats and exit \n\ + \ -f, --formats Show supported output figure formats and exit \n\ \\n\ \ To use with pandoc: \n\ - \ pandoc --filter pandoc-pyplot input.md --output output.html\n\ + \ pandoc -s --filter pandoc-pyplot input.md --output output.html\n\ \\n\ \ More information can be found in the repository README, located at \n\ \ https://github.com/LaurentRDC/pandoc-pyplot\n" @@ -51,7 +50,7 @@ | arg `elem` ["-h", "--help"] -> showHelp | arg `elem` ["-v", "--version"] -> showVersion | arg `elem` ["-f", "--formats"] -> showFormats - _ -> toJSONFilter (makePlotWithConfig config) + _ -> toJSONFilter (plotTransformWithConfig config) where showHelp = putStrLn help showVersion = putStrLn (V.showVersion version)
pandoc-pyplot.cabal view
@@ -1,5 +1,5 @@ name: pandoc-pyplot -version: 2.1.0.0 +version: 2.1.0.1 cabal-version: >= 1.12 synopsis: A Pandoc filter for including figures generated from Matplotlib description: A pandoc filter for including figures generated from Matplotlib. Keep the document and Python code in the same location. Output from Matplotlib is captured and included as a figure. @@ -28,9 +28,10 @@ Text.Pandoc.Filter.Pyplot.Internal other-modules: Paths_pandoc_pyplot - Text.Pandoc.Filter.Pyplot.Scripting - Text.Pandoc.Filter.Pyplot.FigureSpec Text.Pandoc.Filter.Pyplot.Configuration + Text.Pandoc.Filter.Pyplot.FigureSpec + Text.Pandoc.Filter.Pyplot.Scripting + Text.Pandoc.Filter.Pyplot.Types hs-source-dirs: src ghc-options: -Wall -Wcompat
src/Text/Pandoc/Filter/Pyplot.hs view
@@ -25,9 +25,9 @@ Here are the possible attributes what pandoc-pyplot understands: - * @target=...@: Filepath where the resulting figure should be saved. * @directory=...@ : Directory where to save the figure. - * @caption="..."@: Specify a plot caption (or alternate text). + * @format=...@: Format of the generated figure. This can be an extension or an acronym, e.g. @format=png@. + * @caption="..."@: Specify a plot caption (or alternate text). Captions support Markdown formatting and LaTeX math (@$...$@). * @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Default is 80DPI. * @include=...@: Path to a Python script to include before the code block. Ideal to avoid repetition over many figures. @@ -43,6 +43,34 @@ plt.plot([0,1,2,3,4], [1,2,3,4,5]) plt.title('This is an example figure') ``` + +This is another paragraph + +```{.pyplot dpi=150 format=SVG} +# This example was taken from the Matplotlib gallery +# https://matplotlib.org/examples/pylab_examples/bar_stacked.html + +import numpy as np +import matplotlib.pyplot as plt + +N = 5 +menMeans = (20, 35, 30, 35, 27) +womenMeans = (25, 32, 34, 20, 25) +menStd = (2, 3, 4, 1, 2) +womenStd = (3, 5, 2, 3, 3) +ind = np.arange(N) # the x locations for the groups +width = 0.35 # the width of the bars: can also be len(x) sequence + +p1 = plt.bar(ind, menMeans, width, color='#d62728', yerr=menStd) +p2 = plt.bar(ind, womenMeans, width, + bottom=menMeans, yerr=womenStd) + +plt.ylabel('Scores') +plt.title('Scores by group and gender') +plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5')) +plt.yticks(np.arange(0, 81, 10)) +plt.legend((p1[0], p2[0]), ('Men', 'Women')) +``` @ This filter was originally designed to be used with [Hakyll](https://jaspervdj.be/hakyll/). @@ -64,6 +92,8 @@ (unsafeCompiler . plotTransform) @ +Custom configurations are possible via the @Configuration@ type and the filter +functions @plotTransformWithConfig@ and @makePlotWithConfig@. -} module Text.Pandoc.Filter.Pyplot ( -- * Operating on single Pandoc blocks @@ -75,6 +105,8 @@ -- * For configuration purposes , configuration , Configuration (..) + , PythonScript + , SaveFormat (..) -- * For testing and internal purposes only , PandocPyplotError(..) , makePlot'
src/Text/Pandoc/Filter/Pyplot/Configuration.hs view
@@ -11,8 +11,7 @@ -} module Text.Pandoc.Filter.Pyplot.Configuration ( - Configuration (..) - , configuration + configuration -- * For testing and internal purposes only , inclusionKeys , directoryKey @@ -23,14 +22,13 @@ ) where import Data.Maybe (fromMaybe) -import Data.Default.Class (Default, def) +import Data.Default.Class (def) import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Yaml import Data.Yaml.Config (loadYamlSettings, ignoreEnv) -import Text.Pandoc.Filter.Pyplot.FigureSpec -import Text.Pandoc.Filter.Pyplot.Scripting +import Text.Pandoc.Filter.Pyplot.Types -- | Keys that pandoc-pyplot will look for in code blocks. These are only exported for testing purposes. directoryKey, captionKey, dpiKey, includePathKey, saveFormatKey :: String @@ -48,32 +46,6 @@ , includePathKey , saveFormatKey ] - --- | Configuration of pandoc-pyplot, describing the default behavior --- of the filter. --- --- A Configuration is useful when dealing with lots of figures; it avoids --- repeating the same values.sta --- --- @since 2.1.0.0 -data Configuration - = Configuration - { defaultDirectory :: FilePath -- ^ The default directory where figures will be saved. - , defaultIncludeScript :: PythonScript -- ^ The default script to run before other instructions. - , defaultSaveFormat :: SaveFormat -- ^ The default save format of generated figures. - , defaultDPI :: Int -- ^ The default dots-per-inch value for generated figures. - , interpreter :: String -- ^ The name of the interpreter to use to render figures. - } - deriving (Eq, Show) - -instance Default Configuration where - def = Configuration { - defaultDirectory = "generated/" - , defaultIncludeScript = mempty - , defaultSaveFormat = PNG - , defaultDPI = 80 - , interpreter = "python" - } -- A @Configuration@ cannot be directly created from a YAML file -- for two reasons:
src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs view
@@ -25,8 +25,7 @@ import Control.Monad (join) -import Data.Char (toLower) -import Data.Hashable (Hashable, hash, hashWithSalt) +import Data.Hashable (hash) import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) import qualified Data.Text as T @@ -42,7 +41,7 @@ import Text.Pandoc.Options (def, ReaderOptions(..)) import Text.Pandoc.Readers (readMarkdown) -import Text.Pandoc.Filter.Pyplot.Scripting +import Text.Pandoc.Filter.Pyplot.Types readerOptions :: ReaderOptions readerOptions = def @@ -67,61 +66,6 @@ extractInlines (Para inlines) = inlines extractInlines (LineBlock multiinlines) = join multiinlines extractInlines _ = [] - --- | Generated figure file format supported by pandoc-pyplot. -data SaveFormat - = PNG - | PDF - | SVG - | JPG - | EPS - | GIF - | TIF - deriving (Bounded, Enum, Eq, Show) - --- | Parse an image save format string --- --- >>> saveFormatFromString ".png" --- Just PNG --- --- >>> saveFormatFromString "jpeg" --- Just JPEG --- --- >>> SaveFormatFromString "arbitrary" --- Nothing -saveFormatFromString :: String -> Maybe SaveFormat -saveFormatFromString s - | s `elem` ["png", "PNG", ".png"] = Just PNG - | s `elem` ["pdf", "PDF", ".pdf"] = Just PDF - | s `elem` ["svg", "SVG", ".svg"] = Just SVG - | s `elem` ["eps", "EPS", ".eps"] = Just EPS - | s `elem` ["gif", "GIF", ".gif"] = Just GIF - | s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = Just JPG - | s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = Just TIF - | otherwise = Nothing - --- | Save format file extension -extension :: SaveFormat -> String -extension fmt = mconcat [".", fmap toLower . show $ fmt] - --- | Datatype containing all parameters required to run pandoc-pyplot -data FigureSpec = FigureSpec - { caption :: String -- ^ Figure caption. - , script :: PythonScript -- ^ Source code for the figure. - , saveFormat :: SaveFormat -- ^ Save format of the figure - , directory :: FilePath -- ^ Directory where to save the file - , dpi :: Int -- ^ Dots-per-inch of figure - , blockAttrs :: Attr -- ^ Attributes not related to @pandoc-pyplot@ will be propagated. - } - -instance Hashable FigureSpec where - hashWithSalt salt spec = - hashWithSalt salt ( caption spec - , script spec - , fromEnum . saveFormat $ spec - , directory spec, dpi spec - , blockAttrs spec - ) -- | Convert a FigureSpec to a Pandoc block component toImage :: FigureSpec -> Block
src/Text/Pandoc/Filter/Pyplot/Internal.hs view
@@ -14,8 +14,10 @@ module Text.Pandoc.Filter.Pyplot.Configuration , module Text.Pandoc.Filter.Pyplot.FigureSpec , module Text.Pandoc.Filter.Pyplot.Scripting + , module Text.Pandoc.Filter.Pyplot.Types ) where import Text.Pandoc.Filter.Pyplot.Configuration import Text.Pandoc.Filter.Pyplot.FigureSpec -import Text.Pandoc.Filter.Pyplot.Scripting+import Text.Pandoc.Filter.Pyplot.Scripting +import Text.Pandoc.Filter.Pyplot.Types
src/Text/Pandoc/Filter/Pyplot/Scripting.hs view
@@ -14,13 +14,10 @@ module Text.Pandoc.Filter.Pyplot.Scripting ( runTempPythonScript , hasBlockingShowCall - , PythonScript - , ScriptResult(..) ) where import Data.Hashable (hash) import Data.Monoid (Any(..)) -import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T @@ -29,40 +26,34 @@ import System.IO.Temp (getCanonicalTemporaryDirectory) import System.Process.Typed (runProcess, shell) --- | String representation of a Python script -type PythonScript = Text - --- | Possible result of running a Python script -data ScriptResult - = ScriptSuccess - | ScriptFailure Int +import Text.Pandoc.Filter.Pyplot.Types -- | Take a python script in string form, write it in a temporary directory, -- then execute it. runTempPythonScript :: String -- ^ Interpreter (e.g. "python" or "python35") -> PythonScript -- ^ Content of the script -> IO ScriptResult -- ^ Result with exit code. -runTempPythonScript interpreter script = do +runTempPythonScript interpreter' script' = do -- We involve the script hash as a temporary filename -- so that there is never any collision scriptPath <- (</> hashedPath) <$> getCanonicalTemporaryDirectory - T.writeFile scriptPath script + T.writeFile scriptPath script' - ec <- runProcess $ shell $ mconcat [interpreter, " ", show scriptPath] + ec <- runProcess $ shell $ mconcat [interpreter', " ", show scriptPath] case ec of ExitSuccess -> return ScriptSuccess ExitFailure code -> return $ ScriptFailure code where - hashedPath = show . hash $ script + hashedPath = show . hash $ script' -- | Detect the presence of a blocking show call, for example "plt.show()" hasBlockingShowCall :: PythonScript -> Bool -hasBlockingShowCall script = +hasBlockingShowCall script' = anyOf [ "plt.show()" `elem` scriptLines , "pyplot.show()" `elem` scriptLines , "matplotlib.pyplot.show()" `elem` scriptLines ] where - scriptLines = T.lines script + scriptLines = T.lines script' anyOf xs = getAny $ mconcat $ Any <$> xs
+ src/Text/Pandoc/Filter/Pyplot/Types.hs view
@@ -0,0 +1,108 @@+{-| +Module : Text.Pandoc.Filter.Pyplot.Types +Copyright : (c) Laurent P René de Cotret, 2019 +License : MIT +Maintainer : laurent.decotret@outlook.com +Stability : internal +Portability : portable + +This module defines types in use in pandoc-pyplot +-} + +module Text.Pandoc.Filter.Pyplot.Types where + +import Data.Char (toLower) +import Data.Default.Class (Default, def) +import Data.Hashable (Hashable, hashWithSalt) +import Data.Text (Text) + +import Text.Pandoc.Definition (Attr) + +-- | String representation of a Python script +type PythonScript = Text + +-- | Possible result of running a Python script +data ScriptResult + = ScriptSuccess + | ScriptFailure Int + +-- | Generated figure file format supported by pandoc-pyplot. +data SaveFormat + = PNG + | PDF + | SVG + | JPG + | EPS + | GIF + | TIF + deriving (Bounded, Enum, Eq, Show) + +-- | Parse an image save format string +-- +-- >>> saveFormatFromString ".png" +-- Just PNG +-- +-- >>> saveFormatFromString "jpeg" +-- Just JPEG +-- +-- >>> SaveFormatFromString "arbitrary" +-- Nothing +saveFormatFromString :: String -> Maybe SaveFormat +saveFormatFromString s + | s `elem` ["png", "PNG", ".png"] = Just PNG + | s `elem` ["pdf", "PDF", ".pdf"] = Just PDF + | s `elem` ["svg", "SVG", ".svg"] = Just SVG + | s `elem` ["eps", "EPS", ".eps"] = Just EPS + | s `elem` ["gif", "GIF", ".gif"] = Just GIF + | s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = Just JPG + | s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = Just TIF + | otherwise = Nothing + +-- | Save format file extension +extension :: SaveFormat -> String +extension fmt = mconcat [".", fmap toLower . show $ fmt] + +-- | Configuration of pandoc-pyplot, describing the default behavior +-- of the filter. +-- +-- A Configuration is useful when dealing with lots of figures; it avoids +-- repeating the same values.sta +-- +-- @since 2.1.0.0 +data Configuration + = Configuration + { defaultDirectory :: FilePath -- ^ The default directory where figures will be saved. + , defaultIncludeScript :: PythonScript -- ^ The default script to run before other instructions. + , defaultSaveFormat :: SaveFormat -- ^ The default save format of generated figures. + , defaultDPI :: Int -- ^ The default dots-per-inch value for generated figures. + , interpreter :: String -- ^ The name of the interpreter to use to render figures. + } + deriving (Eq, Show) + +instance Default Configuration where + def = Configuration { + defaultDirectory = "generated/" + , defaultIncludeScript = mempty + , defaultSaveFormat = PNG + , defaultDPI = 80 + , interpreter = "python" + } + +-- | Datatype containing all parameters required to run pandoc-pyplot +data FigureSpec = FigureSpec + { caption :: String -- ^ Figure caption. + , script :: PythonScript -- ^ Source code for the figure. + , saveFormat :: SaveFormat -- ^ Save format of the figure + , directory :: FilePath -- ^ Directory where to save the file + , dpi :: Int -- ^ Dots-per-inch of figure + , blockAttrs :: Attr -- ^ Attributes not related to @pandoc-pyplot@ will be propagated. + } + +instance Hashable FigureSpec where + hashWithSalt salt spec = + hashWithSalt salt ( caption spec + , script spec + , fromEnum . saveFormat $ spec + , directory spec, dpi spec + , blockAttrs spec + )