packages feed

path-extra 0.1.2 → 0.2.0

raw patch · 3 files changed

+122/−284 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Path.Extended: (</>) :: PathAppend right base type' => Path base Dir -> right Rel type' -> right base type'
- Path.Extended: [locFileExt] :: Location b t -> Maybe String
- Path.Extended: [locParentJumps] :: Location b t -> Int
- Path.Extended: addFileExt :: String -> Location b File -> Location b File
- Path.Extended: addParent :: Location Rel t -> Location Rel t
- Path.Extended: class PathAppend right base type'
- Path.Extended: delFileExt :: Location b File -> Location b File
- Path.Extended: delParent :: Location Rel t -> Location Rel t
- Path.Extended: fromPath :: Path b t -> Location b t
- Path.Extended: getFileExt :: Location b File -> Maybe String
- Path.Extended: instance GHC.Classes.Eq (Path.Extended.Location b t)
- Path.Extended: instance GHC.Classes.Ord (Path.Extended.Location b t)
- Path.Extended: instance GHC.Show.Show (Path.Extended.Location b t)
- Path.Extended: instance Path.Extended.PathAppend Path.Extended.Location Path.Abs Path.Dir
- Path.Extended: instance Path.Extended.PathAppend Path.Extended.Location Path.Abs Path.File
- Path.Extended: instance Path.Extended.PathAppend Path.Extended.Location Path.Rel Path.Dir
- Path.Extended: instance Path.Extended.PathAppend Path.Extended.Location Path.Rel Path.File
- Path.Extended: instance Path.Extended.PathAppend Path.Internal.Path Path.Abs Path.Dir
- Path.Extended: instance Path.Extended.PathAppend Path.Internal.Path Path.Abs Path.File
- Path.Extended: instance Path.Extended.PathAppend Path.Internal.Path Path.Rel Path.Dir
- Path.Extended: instance Path.Extended.PathAppend Path.Internal.Path Path.Rel Path.File
- Path.Extended: locationAbsDirParser :: Parser (Location Abs Dir)
- Path.Extended: locationAbsFileParser :: Parser (Location Abs File)
- Path.Extended: setFileExt :: Maybe String -> Location b File -> Location b File
+ Path.Extended: fromAbsDir :: Path Abs Dir -> Location
+ Path.Extended: fromAbsFile :: Path Abs File -> Location
+ Path.Extended: instance GHC.Classes.Eq Path.Extended.Location
+ Path.Extended: instance GHC.Classes.Ord Path.Extended.Location
+ Path.Extended: instance GHC.Generics.Generic Path.Extended.Location
+ Path.Extended: locationParser :: Parser Location
+ Path.Extended: prepend :: Path Abs Dir -> Location -> Location
+ Path.Extended: printLocation :: Location -> Text
- Path.Extended: (<#>) :: Location b t -> String -> Location b t
+ Path.Extended: (<#>) :: Location -> String -> Location
- Path.Extended: (<&>) :: Location b t -> QueryParam -> Location b t
+ Path.Extended: (<&>) :: Location -> QueryParam -> Location
- Path.Extended: Location :: Int -> Path b t -> Maybe String -> [QueryParam] -> Maybe String -> Location b t
+ Path.Extended: Location :: Either (Path Abs Dir) (Path Abs File) -> [QueryParam] -> Maybe String -> Location
- Path.Extended: [locFragment] :: Location b t -> Maybe String
+ Path.Extended: [locFragment] :: Location -> Maybe String
- Path.Extended: [locPath] :: Location b t -> Path b t
+ Path.Extended: [locPath] :: Location -> Either (Path Abs Dir) (Path Abs File)
- Path.Extended: [locQueryParams] :: Location b t -> [QueryParam]
+ Path.Extended: [locQueryParams] :: Location -> [QueryParam]
- Path.Extended: addFragment :: String -> Location b t -> Location b t
+ Path.Extended: addFragment :: String -> Location -> Location
- Path.Extended: addQueries :: [QueryParam] -> Location b t -> Location b t
+ Path.Extended: addQueries :: [QueryParam] -> Location -> Location
- Path.Extended: addQuery :: QueryParam -> Location b t -> Location b t
+ Path.Extended: addQuery :: QueryParam -> Location -> Location
- Path.Extended: class FromLocation sym base type' | sym -> base type'
+ Path.Extended: class FromLocation sym
- Path.Extended: class ToLocation sym base type' | sym -> base type'
+ Path.Extended: class ToLocation sym
- Path.Extended: data Location b t
+ Path.Extended: data Location
- Path.Extended: delFragment :: Location b t -> Location b t
+ Path.Extended: delFragment :: Location -> Location
- Path.Extended: delQuery :: Location b t -> Location b t
+ Path.Extended: delQuery :: Location -> Location
- Path.Extended: getFragment :: Location b t -> Maybe String
+ Path.Extended: getFragment :: Location -> Maybe String
- Path.Extended: getQuery :: Location b t -> [QueryParam]
+ Path.Extended: getQuery :: Location -> [QueryParam]
- Path.Extended: parseLocation :: FromLocation sym base type' => Location base type' -> Either String sym
+ Path.Extended: parseLocation :: FromLocation sym => Location -> Either String sym
- Path.Extended: setFragment :: Maybe String -> Location b t -> Location b t
+ Path.Extended: setFragment :: Maybe String -> Location -> Location
- Path.Extended: setQuery :: [QueryParam] -> Location b t -> Location b t
+ Path.Extended: setQuery :: [QueryParam] -> Location -> Location
- Path.Extended: toLocation :: ToLocation sym base type' => sym -> Location base type'
+ Path.Extended: toLocation :: ToLocation sym => sym -> Location

Files

path-extra.cabal view
@@ -2,11 +2,11 @@ -- -- see: https://github.com/sol/hpack ----- hash: ef6199423093f720df1ad58097710e484ee8d805792c0f83655265f54fd65ded+-- hash: 4604482be921c24c141cd64233a1fb7ef12012a76e45a51aacdfb5726aef5367  name:           path-extra-version:        0.1.2-synopsis:       Some extensions to Chris Done's path library, for use with urlpath and attoparsec-uri.+version:        0.2.0+synopsis:       URLs without host information description:    Please see the README on Github at <https://github.com/githubuser/localcooking-db#readme> category:       System, Filesystem, Web homepage:       https://github.com/athanclark/path-extra#readme
src/Path/Extended.hs view
@@ -4,6 +4,8 @@   , NamedFieldPuns   , ScopedTypeVariables   , OverloadedStrings+  , QuasiQuotes+  , DeriveGeneric   #-}  module Path.Extended@@ -16,18 +18,10 @@   , FromPath (..)   , FromLocation (..)   , -- * Combinators-    -- ** Append-    PathAppend (..)-  , -- ** Parent Accessors-    addParent-  , delParent-  , -- ** Path-    fromPath-  , -- ** File Extensions-    setFileExt-  , addFileExt-  , delFileExt-  , getFileExt+    -- ** Path+    fromAbsDir+  , fromAbsFile+  , prepend   , -- ** Query Parameters     setQuery   , addQuery@@ -41,28 +35,26 @@   , (<#>)   , delFragment   , getFragment-  , -- ** Parsers-    locationAbsDirParser-  , locationAbsFileParser+  , -- ** Parser & Printer+    locationParser+  , printLocation   ) where -import Path as P hiding ((</>))-import qualified Path as P ((</>))+-- import Path as P hiding ((</>))+import Path (Path, Abs, Dir, File, (</>), toFilePath, parseAbsFile, parseAbsDir, stripProperPrefix, absdir)  import Prelude hiding (takeWhile) import Data.List (intercalate)-import Data.Attoparsec.Text (Parser, char, takeWhile, takeWhile1, sepBy, sepBy1)+import Data.Attoparsec.Text (Parser, char, takeWhile, takeWhile1, sepBy, sepBy1, many1) import qualified Data.Text as T import Data.Monoid ((<>))-import Control.Applicative (Alternative (many), optional)+import Control.Applicative (Alternative (many), (<|>), optional) import Control.Exception (SomeException) import Control.Monad (void)+import GHC.Generics (Generic)  -class PathAppend right base type' where-  (</>) :: Path base Dir -> right Rel type' -> right base type' - -- | Convenience typeclass for symbolic, stringless routes - make an instance -- for your own data type to use your constructors as route-referencing symbols. class ToPath sym base type' | sym -> base type' where@@ -70,75 +62,59 @@  -- | Convenience typeclass for symbolic, stringless routes - make an instance -- for your own data type to use your constructors as route-referencing symbols.-class ToLocation sym base type' | sym -> base type' where-  toLocation :: sym -> Location base type'+class ToLocation sym where+  toLocation :: sym -> Location  class FromPath sym base type' | sym -> base type' where   parsePath :: Path base type' -> Either String sym -class FromLocation sym base type' | sym -> base type' where-  parseLocation :: Location base type' -> Either String sym+class FromLocation sym where+  parseLocation :: Location -> Either String sym    -- | A location for some base and type - internally uses @Path@.-data Location b t = Location-  { locParentJumps :: Int -- ^ only when b ~ Rel-  , locPath        :: Path b t-  , locFileExt     :: Maybe String -- ^ only when t ~ File+data Location = Location+  { locPath        :: Either (Path Abs Dir) (Path Abs File)   , locQueryParams :: [QueryParam]   , locFragment    :: Maybe String-  } deriving (Eq, Ord)+  } deriving (Eq, Ord, Generic)   +fromAbsDir :: Path Abs Dir -> Location+fromAbsDir path = Location+  { locPath = Left path+  , locQueryParams = []+  , locFragment = Nothing+  } -locationAbsDirParser :: Parser (Location Abs Dir)-locationAbsDirParser = do-  locPath <- absDir-  locQueryParams <- do-    xs <- optional $ do-      let val = T.unpack <$> takeWhile (`notElem` ['=','&','#'])-      void (char '?')-      let kv = do-            k <- val-            mV <- optional $ do-              void (char '=')-              val-            pure (k,mV)-      kv `sepBy` void (char '&')-    case xs of-      Nothing -> pure []-      Just xs' -> pure xs'-  locFragment <- optional $ do-    void (char '#')-    xs <- takeWhile (const True)-    pure (T.unpack xs)-  pure Location-    { locParentJumps = 0-    , locPath-    , locFileExt = Nothing-    , locQueryParams-    , locFragment-    }-  where-    divider = void (char '/')-    chunk = takeWhile1 (`notElem` ['?','&','/','#'])-    absDir :: Parser (Path Abs Dir)-    absDir = do-      divider-      xs <- many (chunk <* divider)-      case parseAbsDir ( case xs of-                           [] -> "/"-                           _  -> T.unpack ("/" <> T.intercalate "/" xs <> "/")-                       ) of-        Left (e :: SomeException) -> fail (show e)-        Right x -> pure x+fromAbsFile :: Path Abs File -> Location+fromAbsFile path = Location+  { locPath = Right path+  , locQueryParams = []+  , locFragment = Nothing+  }  -locationAbsFileParser :: Parser (Location Abs File)-locationAbsFileParser = do-  (locPath, locFileExt) <- absFile+locationParser :: Parser Location+locationParser = do+  divider+  locPath <- do+    xs <- chunk `sepBy` divider+    case xs of+      [] -> pure (Left [absdir|/|])+      _ -> do+        let dir = do+              divider+              case parseAbsDir (T.unpack ("/" <> T.intercalate "/" xs <> "/")) of+                Left (e :: SomeException) -> fail (show e)+                Right x -> pure (Left x)+            file =+              case parseAbsFile (T.unpack ("/" <> T.intercalate "/" xs)) of+                Left (e :: SomeException) -> fail (show e)+                Right x -> pure (Right x)+        dir <|> file   locQueryParams <- do     xs <- optional $ do       let val = T.unpack <$> takeWhile (`notElem` ['=','&','#'])@@ -158,148 +134,82 @@     xs <- takeWhile (const True)     pure (T.unpack xs)   pure Location-    { locParentJumps = 0-    , locPath-    , locFileExt+    { locPath     , locQueryParams     , locFragment     }   where     divider = void (char '/')     chunk = takeWhile1 (`notElem` ['?','&','/','#'])-    absFile :: Parser (Path Abs File, Maybe String)-    absFile = do-      divider-      xs <- chunk `sepBy1` divider-      let (withoutFE,withFE) = T.breakOn "." (last xs)-          xs' = init xs <> [withoutFE]-      path <- case parseAbsFile (T.unpack ("/" <> T.intercalate "/" xs')) of-        Left (e :: SomeException) -> fail (show e)-        Right x -> pure x-      pure-        ( path-        , if T.null withFE-          then Nothing-          else Just $ T.unpack $ T.drop 1 withFE-        )  -instance PathAppend Path Abs Dir where-  (</>) = (P.</>)+prepend :: Path Abs Dir -> Location -> Location+prepend path l@Location{locPath} = l+  { locPath = case locPath of+      Left d -> case stripProperPrefix [absdir|/|] d of+        Nothing -> error "impossible state"+        Just d' -> Left (path </> d')+      Right f -> case stripProperPrefix [absdir|/|] f of+        Nothing -> error "impossible state"+        Just f' -> Right (path </> f')+  } -instance PathAppend Path Abs File where-  (</>) = (P.</>) -instance PathAppend Path Rel Dir where-  (</>) = (P.</>) -instance PathAppend Path Rel File where-  (</>) = (P.</>)--instance PathAppend Location Abs Dir where-  l </> (Location ps pa fe qp fr) =-    Location ps ((P.</>) l pa) fe qp fr--instance PathAppend Location Abs File where-  l </> (Location ps pa fe qp fr) =-    Location ps ((P.</>) l pa) fe qp fr--instance PathAppend Location Rel Dir where-  l </> (Location ps pa fe qp fr) =-    Location ps ((P.</>) l pa) fe qp fr--instance PathAppend Location Rel File where-  l </> (Location ps pa fe qp fr) =-    Location ps ((P.</>) l pa) fe qp fr---instance Show (Location b t) where-  show (Location js pa fe qp fr) =-    let loc = concat (replicate js "../")-           ++ toFilePath pa-           ++ maybe "" (\f -> "." ++ f) fe-        query = case qp of-                  [] -> ""-                  qs -> "?" ++ intercalate "&" (map go qs)-          where-            go (k,mv) = k ++ maybe "" (\v -> "=" ++ v) mv-    in loc ++ query ++ maybe "" (\f -> "#" ++ f) fr+printLocation :: Location -> T.Text+printLocation (Location pa qp fr) =+  let loc = either toFilePath toFilePath pa+      query = case qp of+                [] -> ""+                qs -> "?" <> T.intercalate "&" (go <$> qs)+        where+          go (k,mv) = T.pack k <> maybe "" (\v -> "=" <> T.pack v) mv+  in T.pack loc <> query <> maybe "" (\f -> "#" <> T.pack f) fr  type QueryParam = (String, Maybe String)   --- | Prepend a parental accessor path - @../@-addParent :: Location Rel t -> Location Rel t-addParent (Location j pa fe qp fr) =-  Location (j+1) pa fe qp fr--delParent :: Location Rel t -> Location Rel t-delParent l@(Location j pa fe qp fr)-  | j <= 0    = l-  | otherwise = Location (j-1) pa fe qp fr----- | This should be your entry point for creating a @Location@.-fromPath :: Path b t -> Location b t-fromPath pa = Location 0 pa Nothing [] Nothing---setFileExt :: Maybe String -> Location b File -> Location b File-setFileExt fe (Location js pa _ qp fr) =-  Location js pa fe qp fr--addFileExt :: String -> Location b File -> Location b File-addFileExt fe = setFileExt (Just fe)--delFileExt :: Location b File -> Location b File-delFileExt = setFileExt Nothing--getFileExt :: Location b File -> Maybe String-getFileExt (Location _ _ fe _ _) =-  fe---setQuery :: [QueryParam] -> Location b t -> Location b t-setQuery qp (Location js pa fe _ fr) =-  Location js pa fe qp fr+setQuery :: [QueryParam] -> Location -> Location+setQuery qp (Location pa _ fr) =+  Location pa qp fr  -- | Appends a query parameter-addQuery :: QueryParam -> Location b t -> Location b t-addQuery q (Location js pa fe qp fr) =-  Location js pa fe (qp ++ [q]) fr+addQuery :: QueryParam -> Location -> Location+addQuery q (Location pa qp fr) =+  Location pa (qp ++ [q]) fr -(<&>) :: Location b t -> QueryParam -> Location b t+(<&>) :: Location -> QueryParam -> Location (<&>) = flip addQuery  infixl 7 <&> -addQueries :: [QueryParam] -> Location b t -> Location b t-addQueries qs (Location js pa fe qs' fr) =-  Location js pa fe (qs' ++ qs) fr+addQueries :: [QueryParam] -> Location -> Location+addQueries qs (Location pa qs' fr) =+  Location pa (qs' ++ qs) fr -delQuery :: Location b t -> Location b t+delQuery :: Location -> Location delQuery = setQuery [] -getQuery :: Location b t -> [QueryParam]-getQuery (Location _ _ _ qp _) =+getQuery :: Location -> [QueryParam]+getQuery (Location _ qp _) =   qp  -setFragment :: Maybe String -> Location b t -> Location b t-setFragment fr (Location js pa fe qp _) =-  Location js pa fe qp fr+setFragment :: Maybe String -> Location -> Location+setFragment fr (Location pa qp _) =+  Location pa qp fr -addFragment :: String -> Location b t -> Location b t+addFragment :: String -> Location -> Location addFragment fr = setFragment (Just fr) -(<#>) :: Location b t -> String -> Location b t+(<#>) :: Location -> String -> Location (<#>) = flip addFragment  infixl 8 <#> -delFragment :: Location b t -> Location b t+delFragment :: Location -> Location delFragment = setFragment Nothing -getFragment :: Location b t -> Maybe String-getFragment (Location _ _ _ _ x) = x+getFragment :: Location -> Maybe String+getFragment (Location _ _ x) = x
test/Spec.hs view
@@ -2,12 +2,13 @@     NamedFieldPuns   , OverloadedStrings   , ScopedTypeVariables+  , StandaloneDeriving   #-}  module Main where  import Path (parseAbsDir, parseAbsFile, Path, Abs, Dir, File)-import Path.Extended (Location (..), QueryParam, locationAbsDirParser, locationAbsFileParser)+import Path.Extended (Location (..), QueryParam, locationParser, printLocation)  import qualified Data.Text as T import Data.Monoid ((<>))@@ -18,35 +19,35 @@ import Test.Tasty (defaultMain, testGroup) import qualified Test.Tasty.QuickCheck as QC import Test.QuickCheck (Arbitrary (..), suchThat)-import Test.QuickCheck.Gen (Gen, choose, elements, listOf)+import Test.QuickCheck.Gen (Gen, choose, elements, listOf, oneof) import Test.QuickCheck.Instances ()   -newtype ArbitraryLocationAbsDir = ArbitraryLocationAbsDir-  { getArbitraryLocationAbsDir :: Location Abs Dir+newtype ArbitraryLocation = ArbitraryLocation+  { getArbitraryLocation :: Location   } deriving (Eq, Show) -instance Arbitrary ArbitraryLocationAbsDir where+instance Arbitrary ArbitraryLocation where   arbitrary = do-    locPath <- arbitraryPath+    locPath <- oneof [Left <$> arbitraryAbsDir, Right <$> arbitraryAbsFile]     locQueryParams <- arbitraryQueryParams     locFragment <- arbitraryFragment-    pure $ ArbitraryLocationAbsDir Location-      { locParentJumps = 0-      , locPath-      , locFileExt = Nothing+    pure $ ArbitraryLocation Location+      { locPath       , locQueryParams       , locFragment       }     where+      arbitraryWord :: Gen String+      arbitraryWord = listOf (elements (['A'..'Z']++['a'..'z'])) `suchThat` (not . null)+       arbitraryFragment :: Gen (Maybe String)       arbitraryFragment = do         build <- arbitrary         if not build           then pure Nothing-          else-            fmap Just $ listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)+          else fmap Just arbitraryWord        arbitraryQueryParams :: Gen [QueryParam]       arbitraryQueryParams = do@@ -54,25 +55,22 @@         if not build           then pure []           else do-            let arbitraryVal :: Gen String-                arbitraryVal =-                  listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)             n <- choose (1,4)             let arbitraryKV :: Gen QueryParam                 arbitraryKV = do-                  k <- arbitraryVal+                  k <- arbitraryWord                   buildVal <- arbitrary                   mV <-                     if buildVal-                    then Just <$> arbitraryVal+                    then Just <$> arbitraryWord                     else pure Nothing                   pure (k,mV)             replicateM n arbitraryKV -      arbitraryPath :: Gen (Path Abs Dir)-      arbitraryPath = do+      arbitraryAbsDir :: Gen (Path Abs Dir)+      arbitraryAbsDir = do         n <- choose (0,5)-        xs <- replicateM n arbitraryChunk+        xs <- replicateM n (T.pack <$> arbitraryWord)         pure $ case parseAbsDir ( case xs of                                     [] -> "/"                                     _ -> T.unpack ("/" <> T.intercalate "/" xs <> "/")@@ -81,97 +79,27 @@                    error $ "Can't parse abs dir! " <> show e                  Right path -> path -      arbitraryChunk :: Gen T.Text-      arbitraryChunk = fmap T.pack $-        listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)---newtype ArbitraryLocationAbsFile = ArbitraryLocationAbsFile-  { getArbitraryLocationAbsFile :: Location Abs File-  } deriving (Eq, Show)--instance Arbitrary ArbitraryLocationAbsFile where-  arbitrary = do-    locPath <- arbitraryPath-    locFileExt <- arbitraryFileExt-    locQueryParams <- arbitraryQueryParams-    locFragment <- arbitraryFragment-    pure $ ArbitraryLocationAbsFile Location-      { locParentJumps = 0-      , locPath-      , locFileExt-      , locQueryParams-      , locFragment-      }-    where-      arbitraryFragment :: Gen (Maybe String)-      arbitraryFragment = do-        build <- arbitrary-        if not build-          then pure Nothing-          else-            fmap Just $ listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)--      arbitraryQueryParams :: Gen [QueryParam]-      arbitraryQueryParams = do-        build <- arbitrary-        if not build-          then pure []-          else do-            let arbitraryVal :: Gen String-                arbitraryVal =-                  listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)-            n <- choose (1,4)-            let arbitraryKV :: Gen QueryParam-                arbitraryKV = do-                  k <- arbitraryVal-                  buildVal <- arbitrary-                  mV <--                    if buildVal-                    then Just <$> arbitraryVal-                    else pure Nothing-                  pure (k,mV)-            replicateM n arbitraryKV--      arbitraryPath :: Gen (Path Abs File)-      arbitraryPath = do+      arbitraryAbsFile :: Gen (Path Abs File)+      arbitraryAbsFile = do         n <- choose (1,5)-        xs <- replicateM n arbitraryChunk-        pure $ case parseAbsFile ( case xs of-                                    [] -> "/"-                                    _ -> T.unpack ("/" <> T.intercalate "/" xs)-                                 ) of+        xs <- replicateM n (T.pack <$> arbitraryWord)+        pure $ case parseAbsFile (T.unpack ("/" <> T.intercalate "/" xs)) of                  Left (e :: SomeException) ->                    error $ "Can't parse abs file! " <> show e                  Right path -> path -      arbitraryFileExt :: Gen (Maybe String)-      arbitraryFileExt = do-        build <- arbitrary-        if not build-          then pure Nothing-          else-            Just <$> listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null) -      arbitraryChunk :: Gen T.Text-      arbitraryChunk = fmap T.pack $-        listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)-+deriving instance Show Location  -printParseIsoAbsDir :: ArbitraryLocationAbsDir -> Bool-printParseIsoAbsDir (ArbitraryLocationAbsDir loc) =-  Right loc == parseOnly locationAbsDirParser (T.pack (show loc))--printParseIsoAbsFile :: ArbitraryLocationAbsFile -> Bool-printParseIsoAbsFile (ArbitraryLocationAbsFile loc) =-  Right loc == parseOnly locationAbsFileParser (T.pack (show loc))+printParseIso :: ArbitraryLocation -> Bool+printParseIso (ArbitraryLocation loc) =+  Right loc == parseOnly locationParser (printLocation loc)    main :: IO () main = defaultMain $   testGroup "Path.Extended"-    [ QC.testProperty "Print / Parse AbsDir Iso" printParseIsoAbsDir-    , QC.testProperty "Print / Parse AbsFile Iso" printParseIsoAbsFile+    [ QC.testProperty "Print / Parse Iso" printParseIso     ]