-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #530 Introduce HpackError
type, for Hpack errors
#531
Conversation
I see this proposed change interferes with the test suite. I'll have a look at that. |
ea2e375
to
b981526
Compare
@sol, I have made - I hope - the changes you requested. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The next question is, (in pantry
) do you ever look at HpackException
, or do you just convert it to a String
? If the latter is true, then we could return Either String Result
instead of Either HpackException Result
, and leave the rest of Hpack unchanged.
Now, you already went through the trouble of changing the error type, and there are certainly aspects of this that I like and that I think are cleaner than what we currently have. Sticking with String
would just give us the biggest bang for the buck + it does not introduce any breaking changes to the API.
If we decide to go with HpackException
, then this are the things I want you to look into:
- Do we need to retain
ParseException
, or can we useString
instead? This will allow us to retain theEq
instance. I think the current approach is also problematic forhpack-dhall
. I left some comments regarding this point (all the comments that are preceded by(1)
). - When I originally looked at this code I had the Impression that we use
HpackException
too liberal instead of types that more accurately represent the domain. But looking at it again, I only see one place where we might want to change things (the comment preceded with(2)
). - Is
ProgramName
used for anything else but putting it intoHpackException
? If not, I think we can makeHpack.Config
agnostic toProgramName
by:- Remove the
Exception
instance and renameHpackException
toHpackError
- Have
renderHpackError :: ProgramName -> HpackError -> String
instead ofdisplayException
- Remove the
Please also try to minimize the diff of your changes; avoid any code reformatting. This will help me a lot when reviewing your changes.
src/Hpack.hs
Outdated
@@ -131,7 +134,7 @@ setProgramName :: ProgramName -> Options -> Options | |||
setProgramName name options@Options{..} = | |||
options {optionsDecodeOptions = optionsDecodeOptions {decodeOptionsProgramName = name}} | |||
|
|||
setDecode :: (FilePath -> IO (Either String ([String], Value))) -> Options -> Options | |||
setDecode :: (FilePath -> IO (Either HpackException ([String], Value))) -> Options -> Options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(1) can we leave this as String
? The reason that this is configurable in the first place is so that it can be used with other things than yaml
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll address this in a comment below.
src/Hpack/Exception.hs
Outdated
| DefaultsFileNotFound !FilePath | ||
| DefaultsFileUrlNotFound !URL | ||
| DownloadingFileFailed !URL !Status | ||
| HpackParseException !FilePath !ParseException |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(1) Can we use String
instead of ParseException
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll address this in a comment below, but the data constructors of type HpackError
(as it now is) now only use values of types that are instances of Eq
, so that HpackError
can be an instance of Eq
.
src/Hpack/Yaml.hs
Outdated
formatWarning :: FilePath -> Warning -> String | ||
formatWarning file = \ case | ||
DuplicateKey path -> file ++ ": Duplicate field " ++ formatPath (fromAesonPath path) | ||
|
||
decodeYaml :: FilePath -> IO (Either String ([String], Value)) | ||
decodeYaml :: FilePath -> IO (Either HpackException ([String], Value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(1) Can we keep String
here and wrap it in HpackParseException
at the call site?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll address this in a comment below.
HpackException
type, for Hpack exceptionsHpackError
type, for Hpack errors
75a5e96
to
5d3211a
Compare
The `HpackError` type is an instance of `Eq`. Consequently, its data constructors involve only values of types that are instances of `Eq`. The `renderHpackError :: ProgramName -> HpackError -> String` function preserves the existing error messages of all existing Hpack errors. Moves `ProgramName` from `Hpack.Config` to new module `Hpack.Error` because `renderHpackError` makes use of the type. Defines, and applies, `hpackProgName :: ProgramName`, for convenience. The `DecodeOptions` constructor no longer needs its `decodeOptionsProgramName :: ProgramName` field (and `setProgramName` falls away). Its `decodeOptionsDecode` field is of type `FilePath -> IO (Either HpackError ([String], [Value]))`. The module "Hpack" exports new function `hpackResultWithError :: Options -> IO (Either HpackError Result)`. Updates tests accordingly. Some tests use `shouldSatisfy` rather than `shouldReturn`. Also bumps Hpack's `stack.yaml` to use lts-20.1 (GHC 9.2.5) rather than lts-15.11 (GHC 8.8.3).
@sol, I have:
I have retained I have looked at the package -- | A file decoder for hpack. This should evaluate to a single record with
-- hpack's top-level <https://github.com/sol/hpack#top-level-fields fields>.
fileToJson
:: FilePath -- ^ Path to a @.dhall@ file
-> IO (Either String ([String], Value))
fileToJson file =
liftIO (T.readFile file)
>>= textToJson (inputSettings file) If this pull request were accepted, I would raise a corresponding pull request to adapt -- | A file decoder for hpack. This should evaluate to a single record with
-- hpack's top-level <https://github.com/sol/hpack#top-level-fields fields>.
fileToJson
:: FilePath -- ^ Path to a @.dhall@ file
-> IO (Either HpackError ([String], Value))
fileToJson file =
liftIO (T.readFile file)
>>= textToJson (inputSettings file) >>= either (Left . HpackOtherException file) id |
@mpilgrem sorry for the delay on this. I hope I'll be able to get back to you soon. |
@mpilgrem again, sorry for the delay on this.
@mpilgrem if you're inclined to do (2), can you open a corresponding PR for |
I hinted at this before, from my perspective you want to avoid using types that do not accurately represent the domain. You wouldn't use You wouldn't use In the same way you wouldn't want to add constructors to |
@sol, at the moment, the PR in Pantry was this one (which is reflected in To take a step back and explain my original motivation for this: if somebody (say) accidently adds the line
The format of the 'following exception ...' above is that chosen by the (As an aside Error [S-6602] has been 'written up' at https://errors.haskell.org/messages/S-6602/index.html, which is why it has my attention.) Currently, if somebody accidently adds the line
The first line of the output is Hpack's output. The rest of the lines are Pantry 'handing' the Hpack exception as Pantry Error [S-305]. Stack does not currently 'handle' [S-305], but it could. My end objective was for a user of Stack to have a similar experience when something was wrong with |
OK, I have the feeling we are finally getting to the bottom of this. From what I understand you want to use The reason why
Are there any notable users of Instead of looking at what somebody might need, let's approach this lean. Let's identify what you want to change in
@mpilgrem technically, it's possible to customize the error formatting by using diff --git a/src/Pantry.hs b/src/Pantry.hs
index 9218969..432a624 100644
--- a/src/Pantry.hs
+++ b/src/Pantry.hs
@@ -2,6 +2,7 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE LambdaCase #-}
-- | Content addressable Haskell package management, providing for
-- secure, reproducible acquisition of Haskell package contents and
-- metadata.
@@ -227,6 +228,16 @@ import Pantry.HTTP
import Data.Char (isHexDigit)
import Data.Time (getCurrentTime, diffUTCTime)
+import Data.Yaml.Include (decodeFileWithWarnings)
+import Hpack.Yaml (formatWarning)
+import Hpack.Error (renderHpackError)
+
+decodeYaml :: FilePath -> IO (Either String ([String], Value))
+decodeYaml file = do
+ bimap displayException (first formatWarnings) <$> decodeFileWithWarnings file
+ where
+ formatWarnings = map (formatWarning file)
+
-- | Create a new 'PantryConfig' with the given settings.
--
-- For something easier to use in simple cases, see 'runPantryApp'.
@@ -741,15 +752,16 @@ hpack progName pkgDir = do
he <- view $ pantryConfigL.to pcHpackExecutable
case he of
- HpackBundled -> do
- r <- catchAny
+ HpackBundled ->
( liftIO
- $ Hpack.hpackResult
+ $ Hpack.hpackResultWithError
$ mHpackProgName
+ $ Hpack.setDecode decodeYaml
$ Hpack.setTarget
(toFilePath hpackFile) Hpack.defaultOptions
- )
- ( throwIO . HpackLibraryException hpackFile )
+ ) >>= \ case
+ Left err -> throwIO (HpackLibraryException hpackFile $ renderHpackError (fromMaybe "hpack" progName) err)
+ Right r -> do
forM_ (Hpack.resultWarnings r) (logWarn . fromString)
let cabalFile = fromString . Hpack.resultCabalFile $ r
case Hpack.resultStatus r of
diff --git a/src/Pantry/Types.hs b/src/Pantry/Types.hs
index 45fd914..9a904d2 100644
--- a/src/Pantry/Types.hs
+++ b/src/Pantry/Types.hs
@@ -970,7 +970,7 @@ data PantryException
| MigrationFailure !Text !(Path Abs File) !SomeException
| InvalidTreeFromCasa !BlobKey !ByteString
| ParseSnapNameException !Text
- | HpackLibraryException !(Path Abs File) !SomeException
+ | HpackLibraryException !(Path Abs File) !String
| HpackExeException !FilePath !(Path Abs Dir) !SomeException
deriving Typeable
@@ -1279,13 +1279,13 @@ instance Display PantryException where
"Error: [S-994]\n"
<> "Invalid snapshot name: "
<> display t
- display (HpackLibraryException file e) =
+ display (HpackLibraryException file err) =
"Error: [S-305]\n"
<> "Failed to generate a Cabal file using the Hpack library on file:\n"
<> fromString (toFilePath file)
<> "\n\n"
- <> "The exception encountered was:\n\n"
- <> fromString (show e)
+ <> "The error encountered was:\n\n"
+ <> fromString err
display (HpackExeException fp dir e) =
"Error: [S-720]\n"
<> "Failed to generate a Cabal file using the Hpack executable:\n"
diff --git a/stack.yaml b/stack.yaml
index 8094e22..0be8567 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -2,7 +2,8 @@
resolver: lts-18.28
extra-deps:
-- hpack-0.35.0
+- git: https://github.com/sol/hpack
+ commit: 1ecc4158bdfc03609c88d0b1908fa9f41fdfbf5c
ghc-options:
"$locals": -fhide-source-paths If this doesn't work out and you still need access to the |
@mpilgrem at the risk of stating the obvious (as you are on Window, I don't know how solid your UNIX foundations are), you can apply this patch by copy & pasting it into a file |
@sol, thanks. Due to other commitments, I can't turn to this immediately but I will look at it soon. Thanks also for the advice about the |
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For the context to this pull request, see see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). See also [Pantry PR #74](commercialhaskell/pantry#74) (on which this PR builds).
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For the context to this pull request, see see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). See also [Pantry PR #74](commercialhaskell/pantry#74) (on which this PR builds).
@sol, after a couple of false starts on my part:
The output from Pantry (and, consequently, Stack) is as I had originally hoped:
To answer your questions:
May I ask a question? Apologies if this is 'bike shedding'. My understanding of the use of 'error' v 'exception' terminology is informed principally by this Haskell Wiki page by Henning Thielemann: https://wiki.haskell.org/Error_vs._Exception, which ends with an acknowledgement that different people may use the terms differently, or not distinguish between them. I noted that you preferred (in the Pantry message) 'error' over 'exception' (which I had picked for consistency with other messages). My question is: what is your reasoning for the choice of terminology? |
@mpilgrem from my side #535 is good to go. Please take a final look and update your Regarding your question (and exceptions in general) there are several aspects, or let's say chapters, to this. Instead of writing a whole book, i'll write one chapter at a time (as time permits). That means each of my subsequent comments will deal with one specific aspect. If you want more details to a specific aspect then please quote-reply the comment in question. I am not sure into how much details I want to go, so ultimately we may still only end up with one or two chapters. |
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For some reason, the CI for Pantry is failing on macOS (only), and it looks to be Hpack-related (although not necessarily Hpack-caused). While building the Hpack dependency, the CI reports:
and, later, the build of
|
@mpilgrem I think most likely this is related to caching. I'll reply to your PR. |
I'm not inclined to make a verdict on whether this wiki article from 2009 is authoritative, or not. But I think when we talk about error messages that are presented to a user of a programming tool (say a compiler, or a build tool like If I, as a user of a compiler, feed a program that contains a syntax error into that compiler then I think it's natural that the compiler tells me "you have a syntax error here" as opposed to "syntax exception". In the same way, I think it's natural that a build tool (say I'm talking here about error messages that you show to users. How you name things internally and how you structure your program (read: build tool or compiler) is a different story. Now, coincidentally, this also fits somewhat into the narrative of that wiki article. A syntax error is an error from which a compiler cannot recover (at least not in the most common sense). Still, in the hypothetical case we had a compiler that uses an error correcting parser and hence could recover from syntax errors, then we would probably still call it "syntax error", not "syntax exception". As for |
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds).
@sol, looks good to me. Stack will now report (via Pantry) things like:
|
For the context to this pull request, see see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). See also [Pantry PR #74](commercialhaskell/pantry#74) (on which this PR builds).
Prettier Hpack error messages are enabled by hpack-0.35.1. For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). Also bumps from lts-20.0 to lts-20.4 (most recent GHC 9.2.5).
Prettier Hpack error messages are enabled by hpack-0.35.1. For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). Also conforms form of messages of Errors [S-305] and [S-720]. Also bumps from lts-20.0 to lts-20.4 (most recent GHC 9.2.5).
Prettier Hpack error messages are enabled by hpack-0.35.1. For the context to this pull request see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). Also conforms form of messages of Errors [S-305] and [S-720] and the naming of arguments (`err`) in the `PantryException` instance of `Display`. Also bumps from lts-20.0 to lts-20.4 (most recent GHC 9.2.5).
For the context to this pull request, see see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). See also [Pantry PR #74](commercialhaskell/pantry#74) (on which this PR builds).
For the context to this pull request, see see [Hpack issue #530](sol/hpack#530), the [Hpack PR #531](sol/hpack#531) and the alternative [Hpack PR #535](sol/hpack#535) (on which this PR builds). See also [Pantry PR #74](commercialhaskell/pantry#74) (on which this PR builds).
The
Show
instance forHpackException
preserves the existing error messages of all existing Hpack exceptions.Moves
ProgramName
fromHpack.Config
to new moduleHpack.ProgramName
becauseHpack.Exception
needs to import the type andHpack.Config
now importsHpack.Exception
.Also bumps Hpack's
stack.yaml
to use lts-20.0 (GHC 9.2.5) rather than lts-15.11 (GHC 8.8.3).