packages feed

cabal-doctest 1.0.10 → 1.0.11

raw patch · 4 files changed

+171/−38 lines, 4 filesdep ~CabalPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: Cabal

API changes (from Hackage documentation)

+ Distribution.Extra.Doctest: instance Distribution.Extra.Doctest.CompatSymPath GHC.IO.FilePath GHC.IO.FilePath

Files

README.md view
@@ -1,12 +1,57 @@ cabal-doctest ============= -[![Hackage](https://img.shields.io/hackage/v/cabal-doctest.svg)](https://hackage.haskell.org/package/cabal-doctest) [![Haskell-CI](https://github.com/ulidtko/cabal-doctest/actions/workflows/haskell-ci.yml/badge.svg?branch=master)](https://github.com/ulidtko/cabal-doctest/actions/workflows/haskell-ci.yml)+[![Hackage](https://img.shields.io/hackage/v/cabal-doctest.svg)](https://hackage.haskell.org/package/cabal-doctest) [![Haskell-CI](https://github.com/ulidtko/cabal-doctest/actions/workflows/haskell-ci.yml/badge.svg?branch=master)](https://github.com/ulidtko/cabal-doctest/actions/workflows/haskell-ci.yml) [![stack test](https://github.com/ulidtko/cabal-doctest/actions/workflows/stack-test.yml/badge.svg)](https://github.com/ulidtko/cabal-doctest/actions/workflows/stack-test.yml) -A `Setup.hs` helper for running [doctests][].+A `Setup.hs` helper for running [doctests][doctest]. -[doctests]: https://github.com/sol/doctest#readme+[doctest]: https://github.com/sol/doctest#readme +Why this exists+---------------++**Doctesting** is a nifty technique that stimulates 3 good things to happen:++ * library documentation gains *runnable code examples* that are also tested;+ * library test suite gains *documented usage examples* as "tests for free";+ * get both of the above for the price of one.++That's what the [doctest][] tool does — not this package! — just for clarity.+Off the shelf, `doctest` doesn't require any package management mumbo-jumbo:+you just run it on a source file with haddocks with doctests.++Issues come in when library authors and maintainers wish to integrate doctests+into CI pipelines. When doctests start to require dependencies or non-default+compiler flags: that's when it gets hairy. There, if you want `stack test` and/or+`cabal test` to run doctests too with minimal shenanigans, then read on.++Among different available approaches, this package `cabal-doctest` helps with+one, which is known as [custom setup][], `build-type: Custom` more precisely.+You should stick to the default `build-type: Simple`, unless you know what+you're doing.++In a nutshell, this custom Setup.hs shim generates a module `Build_doctests`+that allows your doctest driver `test-suite` to look like this:++```haskell+module Main where++import Build_doctests (flags, pkgs, module_sources)+import Test.Doctest (doctest)++main :: IO ()+main = doctest (flags ++ pkgs ++ module_sources)+```++More detailed examples below.++Regardless of the name, this **also works with Stack**.++For old versions of stack, cabal-install, GHC, see [caveats](#notes) below.++[custom setup]: https://cabal.readthedocs.io/en/stable/cabal-package-description-file.html#pkg-field-build-type++ Simple example -------------- @@ -148,8 +193,8 @@ ------------------------  The `cabal-doctest` based `Setup.hs` supports a few extensions fields-in `pkg.cabal` files to customise the `doctest` runner behaviour, without-customising the default `doctest.hs`.+in `pkg.cabal` files to customize the `doctest` runner behavior, without+customizing the default `doctest.hs`.  ``` test-suite doctests:@@ -161,7 +206,7 @@  * `x-doctest-options` Additional arguments passed into `doctest` command. * `x-doctest-modules` Additional modules to `doctest`. May be useful if you-  have `doctest` in test or executables (i.e not default library component).+  have doctests in tests or executables (i.e not the default library component). * `x-doctest-src-dirs` Additional source directories to look for the modules.  Notes
cabal-doctest.cabal view
@@ -1,9 +1,9 @@ name:               cabal-doctest-version:            1.0.10+version:            1.0.11 -- x-revision:      0 synopsis:           A Setup.hs helper for running doctests description:-  As of now (end of 2021), there isn't @cabal doctest@+  As of now (end of 2024), there isn't @cabal doctest@   command. Yet, to properly work, @doctest@ needs plenty of configuration.   This library provides the common bits for writing a custom @Setup.hs@. @@ -53,7 +53,7 @@     -- In any case, revisions may set tighter bounds afterwards, if exceptional     -- circumstances would warrant that.       base       >=4.9  && <5-    , Cabal      >=1.10 && <3.14+    , Cabal      >=1.24 && <3.16     , directory  >=1.3  && <2     , filepath   >=1.4  && <2 
changelog.md view
@@ -1,3 +1,12 @@+# 1.0.11 -- 2024-11-22++* Support Cabal 3.14.0.0. [cabal-doctest#85][].+* Motivate the package in README [cabal-doctest#43][].+* Fix `stack test` of examples, add CI integration.++[cabal-doctest#43]: https://github.com/ulidtko/cabal-doctest/issues/43+[cabal-doctest#85]: https://github.com/ulidtko/cabal-doctest/issues/85+ # 1.0.10 -- 2024-06-26  * Maintainership hand-over. See [cabal-doctest#79][].
src/Distribution/Extra/Doctest.hs view
@@ -1,5 +1,11 @@ {-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+#if MIN_VERSION_Cabal(3,14,0)+{-# LANGUAGE DataKinds #-}+#endif+{-# LANGUAGE MultiParamTypeClasses #-}+ -- | See cabal-doctest README for full-fledged recipes & caveats. -- -- The provided 'generateBuildModule' generates a @Build_{suffix}@ module, with@@ -43,11 +49,6 @@     generateBuildModule,     ) where --- Hacky way to suppress few deprecation warnings.-#if MIN_VERSION_Cabal(1,24,0)-#define InstalledPackageId UnitId-#endif- import Control.Monad        (when) import Data.IORef@@ -59,7 +60,7 @@ import Data.String        (fromString) import Distribution.Package-       (InstalledPackageId, Package (..))+       (UnitId, Package (..)) import Distribution.PackageDescription        (BuildInfo (..), Executable (..), GenericPackageDescription,        Library (..), PackageDescription, TestSuite (..))@@ -67,26 +68,29 @@        (UserHooks (..), autoconfUserHooks, defaultMainWithHooks,        simpleUserHooks) import Distribution.Simple.Compiler-       (CompilerFlavor (GHC), CompilerId (..), PackageDB (..), compilerId)+       (CompilerFlavor (GHC), CompilerId (..), compilerId) import Distribution.Simple.LocalBuildInfo        (ComponentLocalBuildInfo (componentPackageDeps), LocalBuildInfo,        compiler, withExeLBI, withLibLBI, withPackageDB, withTestLBI) import Distribution.Simple.Setup-       (BuildFlags (buildDistPref, buildVerbosity),-       HaddockFlags (haddockDistPref, haddockVerbosity), emptyBuildFlags,+       (BuildFlags (..),+       emptyBuildFlags,        fromFlag) import Distribution.Simple.Utils        (createDirectoryIfMissingVerbose, info) import Distribution.Text        (display)-import System.FilePath-       ((</>))  import qualified Data.Foldable    as F                  (for_) import qualified Data.Traversable as T                  (traverse)+import qualified System.FilePath ((</>)) +#if MIN_VERSION_base(4,11,0)+import Data.Functor ((<&>))+#endif+ #if MIN_VERSION_Cabal(1,25,0) import Distribution.Simple.BuildPaths        (autogenComponentModulesDir)@@ -134,6 +138,24 @@        (getSymbolicPath) #endif +#if MIN_VERSION_Cabal(3,14,0)+-- https://github.com/haskell/cabal/issues/10559+import Distribution.Simple.Compiler+       (PackageDB, PackageDBX (GlobalPackageDB, UserPackageDB, SpecificPackageDB))+import Distribution.Simple.LocalBuildInfo+       (absoluteWorkingDirLBI, interpretSymbolicPathLBI)+import Distribution.Simple.Setup+       (HaddockFlags, haddockCommonFlags)+import Distribution.Utils.Path+       (FileOrDir(..), SymbolicPath, interpretSymbolicPathAbsolute, makeRelativePathEx, makeSymbolicPath)+import qualified Distribution.Utils.Path as SymPath ((</>))+#else+import Distribution.Simple.Compiler+       (PackageDB (GlobalPackageDB, UserPackageDB, SpecificPackageDB))+import Distribution.Simple.Setup+       (HaddockFlags (haddockDistPref, haddockVerbosity))+#endif+ #if MIN_VERSION_directory(1,2,2) import System.Directory        (makeAbsolute)@@ -142,7 +164,42 @@        (getCurrentDirectory) import System.FilePath        (isAbsolute)+#endif +{- HLINT ignore "Use fewer imports" -}++-------------------------------------------------------------------------------+-- Compat+-------------------------------------------------------------------------------++#if !MIN_VERSION_base(4,11,0)+(<&>) :: Functor f => f a -> (a -> b) -> f b+(<&>) = flip fmap+infixl 1 <&>+#endif++class CompatSymPath p q where+  (</>) :: p -> FilePath -> q+infixr 5 </>+instance CompatSymPath FilePath FilePath where+  (</>) = (System.FilePath.</>)+#if MIN_VERSION_Cabal(3,14,0)+instance CompatSymPath (SymbolicPath allowAbs ('Dir loc1))+                       (SymbolicPath allowAbs ('Dir loc2)) where+  dir </> name = dir SymPath.</> makeRelativePathEx name+#endif++#if MIN_VERSION_Cabal(3,14,0)+unsymbolizePath = getSymbolicPath+#else+makeSymbolicPath :: FilePath -> FilePath+makeSymbolicPath = id+unsymbolizePath :: FilePath -> FilePath+unsymbolizePath = id+#endif+++#if !MIN_VERSION_directory(1,2,2) makeAbsolute :: FilePath -> IO FilePath makeAbsolute p | isAbsolute p = return p                | otherwise    = do@@ -216,10 +273,16 @@  -- | Convert only flags used by 'generateBuildModule'. haddockToBuildFlags :: HaddockFlags -> BuildFlags-haddockToBuildFlags f = emptyBuildFlags+haddockToBuildFlags f =+#if MIN_VERSION_Cabal(3,14,0)+  emptyBuildFlags+    { buildCommonFlags = haddockCommonFlags f }+#else+   emptyBuildFlags     { buildVerbosity = haddockVerbosity f     , buildDistPref  = haddockDistPref f     }+#endif  data Name = NameLib (Maybe String) | NameExe String deriving (Eq, Show) @@ -270,12 +333,16 @@         | otherwise = []    withTestLBI pkg lbi $ \suite suitecfg -> when (testName suite == fromString testSuiteName) $ do-#if MIN_VERSION_Cabal(1,25,0)++    -- Locate autogen dir, to put our output into.+#if MIN_VERSION_Cabal(3,14,0)+    let testAutogenDir = interpretSymbolicPathLBI lbi+                       $ autogenComponentModulesDir lbi suitecfg+#elif MIN_VERSION_Cabal(1,25,0)     let testAutogenDir = autogenComponentModulesDir lbi suitecfg #else     let testAutogenDir = autogenModulesDir lbi #endif-     createDirectoryIfMissingVerbose verbosity True testAutogenDir      let buildDoctestsFile = testAutogenDir </> "Build_doctests.hs"@@ -326,23 +393,35 @@            let module_sources = modules             -- We need the directory with the component's cabal_macros.h!-#if MIN_VERSION_Cabal(1,25,0)+#if MIN_VERSION_Cabal(3,14,0)+           let compAutogenDir = interpretSymbolicPathLBI lbi+                              $ autogenComponentModulesDir lbi compCfg+#elif MIN_VERSION_Cabal(1,25,0)            let compAutogenDir = autogenComponentModulesDir lbi compCfg #else            let compAutogenDir = autogenModulesDir lbi #endif             -- Lib sources and includes-           iArgsNoPrefix-              <- mapM makeAbsolute-               $ compAutogenDir           -- autogenerated files-               : (distPref ++ "/build")   -- preprocessed files (.hsc -> .hs); "build" is hardcoded in Cabal.-#if MIN_VERSION_Cabal(3,5,0)-               : map getSymbolicPath (hsSourceDirs compBI)+           let iArgsSymbolic =+                  makeSymbolicPath compAutogenDir -- autogen dir+                -- preprocessed files (.hsc -> .hs); "build" is hardcoded in Cabal.+                : (distPref </> "build")+#if MIN_VERSION_Cabal(3,14,0)+                : hsSourceDirs compBI+#elif MIN_VERSION_Cabal(3,5,0)+                : (hsSourceDirs compBI <&> getSymbolicPath) #else-               : hsSourceDirs compBI+                : hsSourceDirs compBI #endif+#if MIN_VERSION_Cabal(3,14,0)+           pkgWorkdir <- absoluteWorkingDirLBI lbi+           let iArgsNoPrefix = iArgsSymbolic <&> interpretSymbolicPathAbsolute pkgWorkdir+           let includeArgs = includeDirs compBI <&> ("-I"++) . interpretSymbolicPathAbsolute pkgWorkdir+#else+           iArgsNoPrefix <- mapM makeAbsolute iArgsSymbolic            includeArgs <- mapM (fmap ("-I"++) . makeAbsolute) $ includeDirs compBI+#endif            -- We clear all includes, so the CWD isn't used.            let iArgs' = map ("-i"++) iArgsNoPrefix                iArgs  = "-i" : iArgs'@@ -360,11 +439,11 @@            -- even though the main-is module is named Main, its filepath might            -- actually be Something.hs. To account for this possibility, we simply            -- pass the full path to the main-is module instead.-           mainIsPath <- T.traverse (findFileEx verbosity iArgsNoPrefix) (compMainIs comp)+           mainIsPath <- T.traverse (findFileEx verbosity iArgsSymbolic) (compMainIs comp)             let all_sources = map display module_sources                              ++ additionalModules-                             ++ maybeToList mainIsPath+                             ++ maybeToList (mainIsPath <&> unsymbolizePath)             let component = Component                 (mbCompName comp)@@ -462,11 +541,11 @@     packageDbArgsConf :: [PackageDB] -> [String]     packageDbArgsConf dbstack = case dbstack of       (GlobalPackageDB:UserPackageDB:dbs) -> concatMap specific dbs-      (GlobalPackageDB:dbs)               -> ("-no-user-package-conf")+      (GlobalPackageDB:dbs)               -> "-no-user-package-conf"                                            : concatMap specific dbs       _ -> ierror       where-        specific (SpecificPackageDB db) = [ "-package-conf=" ++ db ]+        specific (SpecificPackageDB db) = [ "-package-conf=" ++ unsymbolizePath db ]         specific _                      = ierror         ierror = error $ "internal error: unexpected package db stack: "                       ++ show dbstack@@ -484,7 +563,7 @@       dbs                                 -> "-clear-package-db"                                            : concatMap single dbs      where-       single (SpecificPackageDB db) = [ "-package-db=" ++ db ]+       single (SpecificPackageDB db) = [ "-package-db=" ++ unsymbolizePath db ]        single GlobalPackageDB        = [ "-global-package-db" ]        single UserPackageDB          = [ "-user-package-db" ]        isSpecific (SpecificPackageDB _) = True@@ -512,9 +591,9 @@ -- | In compat settings it's better to omit the type-signature testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo #if MIN_VERSION_Cabal(2,0,0)-         -> [(InstalledPackageId, MungedPackageId)]+         -> [(UnitId, MungedPackageId)] #else-         -> [(InstalledPackageId, PackageId)]+         -> [(UnitId, PackageId)] #endif testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys