openSUSE Commits
Threads by month
- ----- 2024 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
August 2017
- 1 participants
- 2097 discussions
Hello community,
here is the log from the commit of package ghc-github for openSUSE:Factory checked in at 2017-08-31 20:47:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-github (Old)
and /work/SRC/openSUSE:Factory/.ghc-github.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-github"
Thu Aug 31 20:47:16 2017 rev:3 rq:513253 version:0.16.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-github/ghc-github.changes 2017-05-10 20:49:30.439400258 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-github.new/ghc-github.changes 2017-08-31 20:47:16.704806348 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:07:55 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.16.0.
+
+-------------------------------------------------------------------
Old:
----
github-0.15.0.tar.gz
github.cabal
New:
----
github-0.16.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-github.spec ++++++
--- /var/tmp/diff_new_pack.109juq/_old 2017-08-31 20:47:17.496695195 +0200
+++ /var/tmp/diff_new_pack.109juq/_new 2017-08-31 20:47:17.500694634 +0200
@@ -19,14 +19,13 @@
%global pkg_name github
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.15.0
+Version: 0.16.0
Release: 0
Summary: Access to the GitHub API, v3
License: BSD-3-Clause
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/3.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-aeson-compat-devel
BuildRequires: ghc-aeson-devel
@@ -92,7 +91,6 @@
%prep
%setup -q -n %{pkg_name}-%{version}
-cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
++++++ github-0.15.0.tar.gz -> github-0.16.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/CHANGELOG.md new/github-0.16.0/CHANGELOG.md
--- old/github-0.15.0/CHANGELOG.md 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/CHANGELOG.md 2017-07-24 17:00:33.000000000 +0200
@@ -1,3 +1,11 @@
+Changes for 0.16.0
+- Add support for `mergeable_state = "blocked".`
+- Fix HTTP status code of merge PR
+- Supports newest versions of dependencies
+- user events
+- release endpoints
+- forkExistingRepo
+
Changes for 0.15.0
- Reworked `PullRequest` (notably `pullRequestsFor`)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/github.cabal new/github-0.16.0/github.cabal
--- old/github-0.15.0/github.cabal 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/github.cabal 2017-07-24 17:00:33.000000000 +0200
@@ -1,5 +1,5 @@
name: github
-version: 0.15.0
+version: 0.16.0
synopsis: Access to the GitHub API, v3.
description:
The GitHub API provides programmatic access to the full
@@ -25,7 +25,7 @@
copyright: Copyright 2012-2013 Mike Burns, Copyright 2013-2015 John Wiegley, Copyright 2016 Oleg Grenrus
category: Network
build-type: Simple
-tested-with: GHC==7.8.4, GHC==7.10.3, GHC==8.0.1
+tested-with: GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.1
cabal-version: >=1.10
extra-source-files:
README.md,
@@ -81,6 +81,7 @@
GitHub.Data.Name
GitHub.Data.Options
GitHub.Data.PullRequests
+ GitHub.Data.Releases
GitHub.Data.Repos
GitHub.Data.Request
GitHub.Data.Search
@@ -111,20 +112,21 @@
GitHub.Endpoints.Repos.Collaborators
GitHub.Endpoints.Repos.Comments
GitHub.Endpoints.Repos.Commits
+ GitHub.Endpoints.Repos.DeployKeys
GitHub.Endpoints.Repos.Forks
+ GitHub.Endpoints.Repos.Releases
GitHub.Endpoints.Repos.Webhooks
- GitHub.Endpoints.Repos.DeployKeys
GitHub.Endpoints.Search
GitHub.Endpoints.Users
GitHub.Endpoints.Users.Followers
GitHub.Request
-- Packages needed in order to build this package.
- build-depends: base >=4.7 && <4.10,
- aeson >=0.7.0.6 && <1.1,
+ build-depends: base >=4.7 && <4.11,
+ aeson >=0.7.0.6 && <1.3,
base-compat >=0.9.1 && <0.10,
base16-bytestring >=0.1.1.6 && <0.2,
- binary >=0.7.1.0 && <0.9,
+ binary >=0.7.1.0 && <0.10,
binary-orphans >=0.1.0.0 && <0.2,
byteable >=0.1.1 && <0.2,
bytestring >=0.10.4.0 && <0.11,
@@ -143,12 +145,12 @@
network-uri >=2.6.0.3 && <2.7,
semigroups >=0.16.2.2 && <0.19,
text >=1.2.0.6 && <1.3,
- time >=1.4 && <1.7,
+ time >=1.4 && <1.9,
transformers >=0.3.0.0 && <0.6,
transformers-compat >=0.4.0.3 && <0.6,
unordered-containers >=0.2 && <0.3,
- vector >=0.10.12.3 && <0.12,
- vector-instances >=3.3.0.1 && <3.4,
+ vector >=0.10.12.3 && <0.13,
+ vector-instances >=3.3.0.1 && <3.5,
tls >=1.3.5
@@ -169,9 +171,11 @@
GitHub.OrganizationsSpec
GitHub.IssuesSpec
GitHub.PullRequestsSpec
+ GitHub.ReleasesSpec
GitHub.ReposSpec
GitHub.SearchSpec
GitHub.UsersSpec
+ GitHub.EventsSpec
main-is: Spec.hs
ghc-options: -Wall
build-depends: base,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/spec/GitHub/EventsSpec.hs new/github-0.16.0/spec/GitHub/EventsSpec.hs
--- old/github-0.15.0/spec/GitHub/EventsSpec.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/github-0.16.0/spec/GitHub/EventsSpec.hs 2017-07-24 17:00:33.000000000 +0200
@@ -0,0 +1,36 @@
+{-# LANGUAGE OverloadedStrings #-}
+module GitHub.EventsSpec where
+
+import Data.Either (isRight)
+import Data.String (fromString)
+import Prelude ()
+import Prelude.Compat
+import System.Environment (lookupEnv)
+import Test.Hspec (Spec, describe, it, shouldSatisfy,
+ pendingWith)
+
+import qualified GitHub
+import GitHub.Data (Auth(..))
+
+fromRightS :: Show a => Either a b -> b
+fromRightS (Left xs) = error $ "Should be Right" ++ show xs
+fromRightS (Right xs) = xs
+
+withAuth :: (Auth -> IO ()) -> IO ()
+withAuth action = do
+ mtoken <- lookupEnv "GITHUB_TOKEN"
+ case mtoken of
+ Nothing -> pendingWith "no GITHUB_TOKEN"
+ Just token -> action (OAuth $ fromString token)
+
+spec :: Spec
+spec = do
+ describe "repositoryEventsR" $ do
+ it "returns non empty list of events" $ shouldSucceed $
+ GitHub.repositoryEventsR "phadej" "github" 1
+ describe "userEventsR" $ do
+ it "returns non empty list of events" $ shouldSucceed $ GitHub.userEventsR "phadej" 1
+ where shouldSucceed f = withAuth $ \auth -> do
+ cs <- GitHub.executeRequest auth $ f
+ cs `shouldSatisfy` isRight
+ length (fromRightS cs) `shouldSatisfy` (> 1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/spec/GitHub/ReleasesSpec.hs new/github-0.16.0/spec/GitHub/ReleasesSpec.hs
--- old/github-0.15.0/spec/GitHub/ReleasesSpec.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/github-0.16.0/spec/GitHub/ReleasesSpec.hs 2017-07-24 17:00:33.000000000 +0200
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
+module GitHub.ReleasesSpec where
+
+import qualified GitHub
+
+import GitHub.Auth (Auth (..))
+import GitHub.Endpoints.Repos.Releases
+ (Release (..), latestReleaseR, releaseByTagNameR, releaseR, releasesR)
+import GitHub.Request (executeRequest)
+
+import Data.Either.Compat (isRight)
+import Data.Proxy (Proxy (..))
+import Data.String (fromString)
+import System.Environment (lookupEnv)
+import Test.Hspec
+ (Spec, describe, it, pendingWith, shouldBe, shouldSatisfy)
+
+import qualified Data.Vector as V
+
+fromRightS :: Show a => Either a b -> b
+fromRightS (Right b) = b
+fromRightS (Left a) = error $ "Expected a Right and got a Left" ++ show a
+
+withAuth :: (Auth -> IO ()) -> IO ()
+withAuth action = do
+ mtoken <- lookupEnv "GITHUB_TOKEN"
+ case mtoken of
+ Nothing -> pendingWith "no GITHUB_TOKEN"
+ Just token -> action (OAuth $ fromString token)
+
+spec :: Spec
+spec = do
+ let v154Id = GitHub.mkId (Proxy :: Proxy Release) 5254449
+ v154Text = "v1.5.4"
+ describe "releasesR" $ do
+ it "works" $ withAuth $ \auth -> do
+ rs <- executeRequest auth $ releasesR "calleerlandsson" "pick" GitHub.FetchAll
+ rs `shouldSatisfy` isRight
+ V.length (fromRightS rs) `shouldSatisfy` (> 14)
+ describe "releaseR" $ do
+ it "works" $ withAuth $ \auth -> do
+ rs <- executeRequest auth $ releaseR "calleerlandsson" "pick" v154Id
+ rs `shouldSatisfy` isRight
+ releaseTagName (fromRightS rs)`shouldBe` v154Text
+ describe "latestReleaseR" $ do
+ it "works" $ withAuth $ \auth -> do
+ rs <- executeRequest auth $ latestReleaseR "calleerlandsson" "pick"
+ rs `shouldSatisfy` isRight
+ describe "releaseByTagNameR" $ do
+ it "works" $ withAuth $ \auth -> do
+ rs <- executeRequest auth $ releaseByTagNameR "calleerlandsson" "pick" v154Text
+ rs `shouldSatisfy` isRight
+ releaseId (fromRightS rs)`shouldBe` v154Id
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Data/Options.hs new/github-0.16.0/src/GitHub/Data/Options.hs
--- old/github-0.15.0/src/GitHub/Data/Options.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Data/Options.hs 2017-07-24 17:00:33.000000000 +0200
@@ -95,6 +95,7 @@
| StateClean
| StateDirty
| StateUnstable
+ | StateBlocked
deriving
(Eq, Ord, Show, Enum, Bounded, Generic, Typeable, Data)
@@ -103,13 +104,15 @@
toJSON StateClean = String "clean"
toJSON StateDirty = String "dirty"
toJSON StateUnstable = String "unstable"
+ toJSON StateBlocked = String "blocked"
instance FromJSON MergeableState where
parseJSON (String "unknown") = pure StateUnknown
parseJSON (String "clean") = pure StateClean
parseJSON (String "dirty") = pure StateDirty
parseJSON (String "unstable") = pure StateUnstable
- parseJSON v = typeMismatch "MergeableState" v
+ parseJSON (String "blocked") = pure StateBlocked
+ parseJSON v = typeMismatch "MergeableState" v
instance NFData MergeableState where rnf = genericRnf
instance Binary MergeableState
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Data/PullRequests.hs new/github-0.16.0/src/GitHub/Data/PullRequests.hs
--- old/github-0.15.0/src/GitHub/Data/PullRequests.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Data/PullRequests.hs 2017-07-24 17:00:33.000000000 +0200
@@ -90,6 +90,9 @@
{ editPullRequestTitle :: !(Maybe Text)
, editPullRequestBody :: !(Maybe Text)
, editPullRequestState :: !(Maybe IssueState)
+ , editPullRequestBase :: !(Maybe Text)
+ , editPullRequestMaintainerCanModify
+ :: !(Maybe Bool)
}
deriving (Show, Generic)
@@ -198,8 +201,15 @@
<*> o .: "id"
instance ToJSON EditPullRequest where
- toJSON (EditPullRequest t b s) =
- object $ filter notNull [ "title" .= t, "body" .= b, "state" .= s ]
+ toJSON (EditPullRequest t b s base mcm) =
+ object $ filter notNull
+ [ "title" .= t
+ , "body" .= b
+ , "state" .= s
+ , "base" .= base
+ , "maintainer_can_modify"
+ .= mcm
+ ]
where
notNull (_, Null) = False
notNull (_, _) = True
@@ -299,7 +309,7 @@
statusMerge :: StatusMap MergeResult
statusMerge =
- [ (204, MergeSuccessful)
+ [ (200, MergeSuccessful)
, (405, MergeCannotPerform)
, (409, MergeConflict)
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Data/Releases.hs new/github-0.16.0/src/GitHub/Data/Releases.hs
--- old/github-0.15.0/src/GitHub/Data/Releases.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Data/Releases.hs 2017-07-24 17:00:33.000000000 +0200
@@ -0,0 +1,85 @@
+module GitHub.Data.Releases where
+
+import GitHub.Data.Definitions
+import GitHub.Data.Id (Id)
+import GitHub.Data.URL (URL)
+import GitHub.Internal.Prelude
+import Prelude ()
+
+data Release = Release
+ { releaseUrl :: !URL
+ , releaseHtmlUrl :: !URL
+ , releaseAssetsurl :: !URL
+ , releaseUploadUrl :: !URL
+ , releaseTarballUrl :: !URL
+ , releaseZipballUrl :: !URL
+ , releaseId :: !(Id Release)
+ , releaseTagName :: !Text
+ , releaseTargetCommitish :: !Text
+ , releaseName :: !Text
+ , releaseBody :: !Text
+ , releaseDraft :: !Bool
+ , releasePrerelease :: !Bool
+ , releaseCreatedAt :: !UTCTime
+ , releasePublishedAt :: !(Maybe UTCTime)
+ , releaseAuthor :: !SimpleUser
+ , releaseAssets :: !(Vector ReleaseAsset)
+ }
+ deriving (Show, Data, Typeable, Eq, Ord, Generic)
+
+instance FromJSON Release where
+ parseJSON = withObject "Event" $ \o -> Release
+ <$> o .: "url"
+ <*> o .: "html_url"
+ <*> o .: "assets_url"
+ <*> o .: "upload_url"
+ <*> o .: "tarball_url"
+ <*> o .: "zipball_url"
+ <*> o .: "id"
+ <*> o .: "tag_name"
+ <*> o .: "target_commitish"
+ <*> o .: "name"
+ <*> o .: "body"
+ <*> o .: "draft"
+ <*> o .: "prerelease"
+ <*> o .: "created_at"
+ <*> o .:? "published_at"
+ <*> o .: "author"
+ <*> o .: "assets"
+
+instance NFData Release where rnf = genericRnf
+instance Binary Release
+
+data ReleaseAsset = ReleaseAsset
+ { releaseAssetUrl :: !URL
+ , releaseAssetBrowserDownloadUrl :: !Text
+ , releaseAssetId :: !(Id ReleaseAsset)
+ , releaseAssetName :: !Text
+ , releaseAssetLabel :: !(Maybe Text)
+ , releaseAssetState :: !Text
+ , releaseAssetContentType :: !Text
+ , releaseAssetSize :: !Int
+ , releaseAssetDownloadCount :: !Int
+ , releaseAssetCreatedAt :: !UTCTime
+ , releaseAssetUpdatedAt :: !UTCTime
+ , releaseAssetUploader :: !SimpleUser
+ }
+ deriving (Show, Data, Typeable, Eq, Ord, Generic)
+
+instance FromJSON ReleaseAsset where
+ parseJSON = withObject "Event" $ \o -> ReleaseAsset
+ <$> o .: "url"
+ <*> o .: "browser_download_url"
+ <*> o .: "id"
+ <*> o .: "name"
+ <*> o .:? "label"
+ <*> o .: "state"
+ <*> o .: "content_type"
+ <*> o .: "size"
+ <*> o .: "download_count"
+ <*> o .: "created_at"
+ <*> o .: "updated_at"
+ <*> o .: "uploader"
+
+instance NFData ReleaseAsset where rnf = genericRnf
+instance Binary ReleaseAsset
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Data.hs new/github-0.16.0/src/GitHub/Data.hs
--- old/github-0.15.0/src/GitHub/Data.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Data.hs 2017-07-24 17:00:33.000000000 +0200
@@ -43,6 +43,7 @@
module GitHub.Data.Milestone,
module GitHub.Data.Options,
module GitHub.Data.PullRequests,
+ module GitHub.Data.Releases,
module GitHub.Data.Repos,
module GitHub.Data.Request,
module GitHub.Data.Search,
@@ -69,6 +70,7 @@
import GitHub.Data.Name
import GitHub.Data.Options
import GitHub.Data.PullRequests
+import GitHub.Data.Releases
import GitHub.Data.Repos
import GitHub.Data.Request
import GitHub.Data.Search
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Endpoints/Activity/Events.hs new/github-0.16.0/src/GitHub/Endpoints/Activity/Events.hs
--- old/github-0.15.0/src/GitHub/Endpoints/Activity/Events.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Endpoints/Activity/Events.hs 2017-07-24 17:00:33.000000000 +0200
@@ -7,6 +7,7 @@
module GitHub.Endpoints.Activity.Events (
-- * Events
repositoryEventsR,
+ userEventsR,
module GitHub.Data,
) where
@@ -19,3 +20,9 @@
repositoryEventsR :: Name Owner -> Name Repo -> FetchCount -> Request 'RO (Vector Event)
repositoryEventsR user repo =
pagedQuery ["repos", toPathPart user, toPathPart repo, "events"] []
+
+-- | List user public events.
+-- See <https://developer.github.com/v3/activity/events/#list-public-events-perform…>
+userEventsR :: Name User -> FetchCount -> Request 'RO (Vector Event)
+userEventsR user =
+ pagedQuery ["users", toPathPart user, "events", "public"] []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Endpoints/PullRequests.hs new/github-0.16.0/src/GitHub/Endpoints/PullRequests.hs
--- old/github-0.15.0/src/GitHub/Endpoints/PullRequests.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Endpoints/PullRequests.hs 2017-07-24 17:00:33.000000000 +0200
@@ -7,6 +7,7 @@
-- <http://developer.github.com/v3/pulls/>.
module GitHub.Endpoints.PullRequests (
pullRequestsFor,
+ pullRequestsFor',
pullRequestsForR,
pullRequest',
pullRequest,
@@ -40,6 +41,13 @@
pullRequestsFor user repo =
executeRequest' $ pullRequestsForR user repo mempty FetchAll
+-- | All open pull requests for the repo, by owner and repo name.
+--
+-- > pullRequestsFor "rails" "rails"
+pullRequestsFor' :: Maybe Auth -> Name Owner -> Name Repo -> IO (Either Error (Vector SimplePullRequest))
+pullRequestsFor' auth user repo =
+ executeRequestMaybe auth $ pullRequestsForR user repo mempty FetchAll
+
-- | List pull requests.
-- See <https://developer.github.com/v3/pulls/#list-pull-requests>
pullRequestsForR
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Endpoints/Repos/Releases.hs new/github-0.16.0/src/GitHub/Endpoints/Repos/Releases.hs
--- old/github-0.15.0/src/GitHub/Endpoints/Repos/Releases.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Endpoints/Repos/Releases.hs 2017-07-24 17:00:33.000000000 +0200
@@ -0,0 +1,110 @@
+-- The Release API, as described at
+-- <https://developer.github.com/v3/repos/releases/>.
+module GitHub.Endpoints.Repos.Releases (
+ releases,
+ releases',
+ releasesR,
+ release,
+ release',
+ releaseR,
+ latestRelease,
+ latestRelease',
+ latestReleaseR,
+ releaseByTagName,
+ releaseByTagName',
+ releaseByTagNameR,
+ module GitHub.Data,
+ ) where
+
+import GitHub.Data
+import GitHub.Internal.Prelude
+import GitHub.Request
+import Prelude ()
+
+-- | All releases for the given repo.
+--
+-- > releases "calleerlandsson" "pick"
+releases :: Name Owner -> Name Repo -> IO (Either Error (Vector Release))
+releases = releases' Nothing
+
+-- | All releases for the given repo with authentication.
+--
+-- > releases' (Just (User (user, password))) "calleerlandsson" "pick"
+releases' :: Maybe Auth -> Name Owner -> Name Repo -> IO (Either Error (Vector Release))
+releases' auth user repo =
+ executeRequestMaybe auth $ releasesR user repo FetchAll
+
+-- | List releases for a repository.
+-- See <https://developer.github.com/v3/repos/releases/#list-releases-for-a-reposit…>
+releasesR :: Name Owner -> Name Repo -> FetchCount -> Request k (Vector Release)
+releasesR user repo =
+ pagedQuery ["repos", toPathPart user, toPathPart repo, "releases"] []
+
+-- | Query a single release.
+--
+-- > release "calleerlandsson" "pick"
+release :: Name Owner -> Name Repo -> Id Release -> IO (Either Error Release)
+release = release' Nothing
+
+-- | Query a single release with authentication.
+--
+-- > release' (Just (User (user, password))) "calleerlandsson" "pick"
+release' :: Maybe Auth -> Name Owner -> Name Repo -> Id Release -> IO (Either Error Release)
+release' auth user repo reqReleaseId =
+ executeRequestMaybe auth $ releaseR user repo reqReleaseId
+
+-- | Get a single release.
+-- See <https://developer.github.com/v3/repos/releases/#get-a-single-release>
+releaseR :: Name Owner -> Name Repo -> Id Release -> Request k Release
+releaseR user repo reqReleaseId =
+ query ["repos", toPathPart user, toPathPart repo, "releases", toPathPart reqReleaseId ] []
+
+-- | Query latest release.
+--
+-- > latestRelease "calleerlandsson" "pick"
+latestRelease :: Name Owner -> Name Repo -> IO (Either Error Release)
+latestRelease = latestRelease' Nothing
+
+-- | Query latest release with authentication.
+--
+-- > latestRelease' (Just (User (user, password))) "calleerlandsson" "pick"
+latestRelease' :: Maybe Auth -> Name Owner -> Name Repo -> IO (Either Error Release)
+latestRelease' auth user repo =
+ executeRequestMaybe auth $ latestReleaseR user repo
+
+-- | Get the latest release.
+-- See <https://developer.github.com/v3/repos/releases/#get-the-latest-release>
+latestReleaseR :: Name Owner -> Name Repo -> Request k Release
+latestReleaseR user repo =
+ query ["repos", toPathPart user, toPathPart repo, "releases", "latest" ] []
+
+-- | Query release by tag name.
+--
+-- > releaseByTagName "calleerlandsson" "pick"
+releaseByTagName :: Name Owner -> Name Repo -> Text -> IO (Either Error Release)
+releaseByTagName = releaseByTagName' Nothing
+
+-- | Query release by tag name with authentication.
+--
+-- > releaseByTagName' (Just (User (user, password))) "calleerlandsson" "pick"
+releaseByTagName' :: Maybe Auth -> Name Owner -> Name Repo -> Text -> IO (Either Error Release)
+releaseByTagName' auth user repo reqTagName =
+ executeRequestMaybe auth $ releaseByTagNameR user repo reqTagName
+
+-- | Get a release by tag name
+-- See <https://developer.github.com/v3/repos/releases/#get-a-release-by-tag-name>
+releaseByTagNameR :: Name Owner -> Name Repo -> Text -> Request k Release
+releaseByTagNameR user repo reqTagName =
+ query ["repos", toPathPart user, toPathPart repo, "releases", "tags" , reqTagName ] []
+
+{-
+-- TODO: implement the following:
+ https://developer.github.com/v3/repos/releases/#create-a-release
+ https://developer.github.com/v3/repos/releases/#edit-a-release
+ https://developer.github.com/v3/repos/releases/#delete-a-release
+ https://developer.github.com/v3/repos/releases/#list-assets-for-a-release
+ https://developer.github.com/v3/repos/releases/#upload-a-release-asset
+ https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
+ https://developer.github.com/v3/repos/releases/#edit-a-release-asset
+ https://developer.github.com/v3/repos/releases/#delete-a-release-asset
+-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub/Endpoints/Repos.hs new/github-0.16.0/src/GitHub/Endpoints/Repos.hs
--- old/github-0.15.0/src/GitHub/Endpoints/Repos.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub/Endpoints/Repos.hs 2017-07-24 17:00:33.000000000 +0200
@@ -42,6 +42,7 @@
createRepoR,
createOrganizationRepo',
createOrganizationRepoR,
+ forkExistingRepoR,
-- ** Edit
editRepo,
@@ -172,6 +173,13 @@
createRepoR nrepo =
command Post ["user", "repos"] (encode nrepo)
+-- | Fork an existing repository.
+-- See <https://developer.github.com/v3/repos/forks/#create-a-fork>
+-- TODO: The third paramater (an optional Organisation) is not used yet.
+forkExistingRepoR :: Name Owner -> Name Repo -> Maybe (Name Owner) -> Request 'RW Repo
+forkExistingRepoR owner repo _morg =
+ command Post ["repos", toPathPart owner, toPathPart repo, "forks" ] mempty
+
-- | Create a new repository for an organization.
--
-- > createOrganizationRepo (BasicAuth (user, password)) "thoughtbot" (newRepo "some_repo") {newRepoHasIssues = Just False}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/github-0.15.0/src/GitHub.hs new/github-0.16.0/src/GitHub.hs
--- old/github-0.15.0/src/GitHub.hs 2016-11-04 19:15:15.000000000 +0100
+++ new/github-0.16.0/src/GitHub.hs 2017-07-24 17:00:33.000000000 +0200
@@ -18,7 +18,7 @@
-- ** Events
-- | See https://developer.github.com/v3/activity/events/#events
repositoryEventsR,
-
+ userEventsR,
-- ** Starring
-- | See <https://developer.github.com/v3/activity/starring/>
--
@@ -270,6 +270,12 @@
pingRepoWebhookR,
deleteRepoWebhookR,
+ -- * Releases
+ releasesR,
+ releaseR,
+ latestReleaseR,
+ releaseByTagNameR,
+
-- * Search
-- | See <https://developer.github.com/v3/search/>
--
@@ -334,6 +340,7 @@
import GitHub.Endpoints.Repos.Comments
import GitHub.Endpoints.Repos.Commits
import GitHub.Endpoints.Repos.Forks
+import GitHub.Endpoints.Repos.Releases
import GitHub.Endpoints.Repos.Webhooks
import GitHub.Endpoints.Search
import GitHub.Endpoints.Users
1
0
Hello community,
here is the log from the commit of package ghc-ghc-events for openSUSE:Factory checked in at 2017-08-31 20:47:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-ghc-events (Old)
and /work/SRC/openSUSE:Factory/.ghc-ghc-events.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-ghc-events"
Thu Aug 31 20:47:14 2017 rev:2 rq:513248 version:0.6.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-ghc-events/ghc-ghc-events.changes 2017-03-24 01:56:31.385478822 +0100
+++ /work/SRC/openSUSE:Factory/.ghc-ghc-events.new/ghc-ghc-events.changes 2017-08-31 20:47:15.560966903 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:07:49 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.6.0.
+
+-------------------------------------------------------------------
Old:
----
1.cabal
ghc-events-0.4.4.0.tar.gz
New:
----
ghc-events-0.6.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-ghc-events.spec ++++++
--- /var/tmp/diff_new_pack.cpa6Mx/_old 2017-08-31 20:47:16.360854627 +0200
+++ /var/tmp/diff_new_pack.cpa6Mx/_new 2017-08-31 20:47:16.364854066 +0200
@@ -1,7 +1,7 @@
#
# spec file for package ghc-ghc-events
#
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,20 +19,19 @@
%global pkg_name ghc-events
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.4.4.0
+Version: 0.6.0
Release: 0
Summary: Library and tool for parsing .eventlog files from GHC
License: BSD-3-Clause
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal
+BuildRequires: chrpath
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-array-devel
BuildRequires: ghc-binary-devel
BuildRequires: ghc-bytestring-devel
BuildRequires: ghc-containers-devel
-BuildRequires: ghc-mtl-devel
BuildRequires: ghc-rpm-macros
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -53,13 +52,13 @@
%prep
%setup -q -n %{pkg_name}-%{version}
-cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
%install
%ghc_lib_install
+%ghc_fix_rpath %{pkg_name}-%{version}
%check
%cabal_test
@@ -77,5 +76,6 @@
%files devel -f %{name}-devel.files
%defattr(-,root,root,-)
+%doc CHANGELOG.md README.md
%changelog
++++++ ghc-events-0.4.4.0.tar.gz -> ghc-events-0.6.0.tar.gz ++++++
++++ 15821 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package ghc-generic-xmlpickler for openSUSE:Factory checked in at 2017-08-31 20:47:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-generic-xmlpickler (Old)
and /work/SRC/openSUSE:Factory/.ghc-generic-xmlpickler.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-generic-xmlpickler"
Thu Aug 31 20:47:10 2017 rev:2 rq:513246 version:0.1.0.5
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-generic-xmlpickler/ghc-generic-xmlpickler.changes 2017-03-08 01:02:39.590748229 +0100
+++ /work/SRC/openSUSE:Factory/.ghc-generic-xmlpickler.new/ghc-generic-xmlpickler.changes 2017-08-31 20:47:12.349417693 +0200
@@ -1,0 +2,5 @@
+Fri Jul 28 03:01:26 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.1.0.5 revision 2.
+
+-------------------------------------------------------------------
Old:
----
1.cabal
New:
----
generic-xmlpickler.cabal
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-generic-xmlpickler.spec ++++++
--- /var/tmp/diff_new_pack.fVO1iY/_old 2017-08-31 20:47:14.229153843 +0200
+++ /var/tmp/diff_new_pack.fVO1iY/_new 2017-08-31 20:47:14.233153282 +0200
@@ -1,7 +1,7 @@
#
# spec file for package ghc-generic-xmlpickler
#
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -26,7 +26,7 @@
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal
+Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/2.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-generic-deriving-devel
BuildRequires: ghc-hxt-devel
++++++ generic-xmlpickler.cabal ++++++
name: generic-xmlpickler
version: 0.1.0.5
x-revision: 2
description: Generic generation of HXT XmlPickler instances using GHC Generics.
synopsis: Generic generation of HXT XmlPickler instances using GHC Generics.
category: XML, Data
cabal-version: >= 1.8
author: Silk
copyright: (c) 2015, Silk
maintainer: code(a)silk.co
homepage: http://github.com/silkapp/generic-xmlpickler
license: BSD3
license-file: LICENSE
build-type: Simple
extra-source-files:
CHANGELOG.md
LICENSE
README.md
source-repository head
type: git
location: https://github.com/silkapp/regular-xmlpickler.git
library
ghc-options: -Wall
hs-source-dirs: src
exposed-modules: Generics.XmlPickler
build-depends:
base >= 4.5 && < 4.11
, generic-deriving >= 1.6 && < 1.12
, hxt >= 9.2 && < 9.4
, text
if impl(ghc < 7.6)
build-depends: ghc-prim >= 0.2 && < 0.5
test-suite tests
ghc-options: -Wall
hs-source-dirs: tests
main-is: Main.hs
type: exitcode-stdio-1.0
build-depends:
base >= 4.5 && < 5
, generic-xmlpickler
, hxt >= 9.2 && < 9.4
, hxt-pickle-utils == 0.1.*
, tasty >= 0.10 && < 0.12
, tasty-hunit == 0.9.*
, tasty-th == 0.1.*
if impl(ghc < 7.6)
build-depends: ghc-prim >= 0.2 && < 0.5
1
0
Hello community,
here is the log from the commit of package ghc-generic-random for openSUSE:Factory checked in at 2017-08-31 20:47:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-generic-random (Old)
and /work/SRC/openSUSE:Factory/.ghc-generic-random.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-generic-random"
Thu Aug 31 20:47:08 2017 rev:2 rq:513245 version:0.5.0.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-generic-random/ghc-generic-random.changes 2017-06-12 15:27:52.366938725 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-generic-random.new/ghc-generic-random.changes 2017-08-31 20:47:09.777778660 +0200
@@ -1,0 +2,10 @@
+Fri Jul 28 03:01:23 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.5.0.0 revision 2.
+
+-------------------------------------------------------------------
+Thu Jul 27 14:06:57 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.5.0.0 revision 1.
+
+-------------------------------------------------------------------
Old:
----
generic-random-0.4.1.0.tar.gz
New:
----
generic-random-0.5.0.0.tar.gz
generic-random.cabal
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-generic-random.spec ++++++
--- /var/tmp/diff_new_pack.Sa7dhr/_old 2017-08-31 20:47:10.721646174 +0200
+++ /var/tmp/diff_new_pack.Sa7dhr/_new 2017-08-31 20:47:10.725645614 +0200
@@ -18,16 +18,16 @@
%global pkg_name generic-random
Name: ghc-%{pkg_name}
-Version: 0.4.1.0
+Version: 0.5.0.0
Release: 0
Summary: Generic random generators
License: MIT
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
+Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/2.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-QuickCheck-devel
-BuildRequires: ghc-boltzmann-samplers-devel
BuildRequires: ghc-rpm-macros
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -47,6 +47,7 @@
%prep
%setup -q -n %{pkg_name}-%{version}
+cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
++++++ generic-random-0.4.1.0.tar.gz -> generic-random-0.5.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generic-random-0.4.1.0/CHANGELOG.md new/generic-random-0.5.0.0/CHANGELOG.md
--- old/generic-random-0.4.1.0/CHANGELOG.md 2017-03-05 21:30:37.000000000 +0100
+++ new/generic-random-0.5.0.0/CHANGELOG.md 2017-04-10 17:25:58.000000000 +0200
@@ -1,3 +1,9 @@
+# 0.5.0.0
+
+- Turn off dependency on boltzmann-samplers by default
+- Add genericArbitraryU, genericArbitraryU0 and genericArbitraryU1
+- Compatible with GHC 7.8.4 and GHC 7.10.3
+
# 0.4.1.0
- Move Boltzmann sampler modules to another package: boltzmann-samplers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generic-random-0.4.1.0/generic-random.cabal new/generic-random-0.5.0.0/generic-random.cabal
--- old/generic-random-0.4.1.0/generic-random.cabal 2017-03-05 21:30:37.000000000 +0100
+++ new/generic-random-0.5.0.0/generic-random.cabal 2017-04-10 17:25:58.000000000 +0200
@@ -1,5 +1,5 @@
name: generic-random
-version: 0.4.1.0
+version: 0.5.0.0
synopsis: Generic random generators
description: Please see the README.
homepage: http://github.com/lysxia/generic-random
@@ -18,7 +18,7 @@
Description:
Dependency on boltzmann-samplers for backwards compatibility.
Manual: False
- Default: True
+ Default: False
library
hs-source-dirs: src
@@ -26,7 +26,7 @@
Generic.Random.Generic
Generic.Random.Internal.Generic
build-depends:
- base >= 4.9 && < 4.10,
+ base >= 4.7 && < 4.10,
QuickCheck
if flag(boltzmann)
exposed-modules:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generic-random-0.4.1.0/src/Generic/Random/Generic.hs new/generic-random-0.5.0.0/src/Generic/Random/Generic.hs
--- old/generic-random-0.4.1.0/src/Generic/Random/Generic.hs 2017-03-05 21:30:37.000000000 +0100
+++ new/generic-random-0.5.0.0/src/Generic/Random/Generic.hs 2017-04-10 17:25:58.000000000 +0200
@@ -27,7 +27,9 @@
--
-- The list of weights is built up with the @('%')@ operator as a cons, and using
-- the unit @()@ as the empty list, in the order corresponding to the data type
--- definition.
+-- definition. The uniform distribution can be obtained with 'uniform'.
+--
+-- === Example
--
-- For @Tree@, 'genericArbitrary' produces code equivalent to the following:
--
@@ -40,6 +42,20 @@
-- ]
-- @
--
+-- === Uniform distribution
+--
+-- You can specify the uniform distribution (all weights equal) with 'uniform'.
+-- 'genericArbitraryU' is available as a shorthand for
+-- @'genericArbitrary' 'uniform'@.
+--
+-- Note that for many types, a uniform distribution tends to produce big
+-- values. For instance for @Tree a@, generated values are finite but the
+-- __average__ number of @Leaf@ and @Node@ constructors is __infinite__.
+--
+-- === Checked weights
+--
+-- /GHC 8.0.1 and above only./
+--
-- The weights actually have type @'W' \"ConstructorName\"@ (just a newtype
-- around 'Int'), so that you can annotate a weight with its corresponding
-- constructor, and it will be checked that you got the order right.
@@ -60,26 +76,6 @@
-- 'weighted' (x '%' y '%' z '%' ()) :: 'Weights' (Tree a)
-- @
--
--- === Uniform distribution
---
--- You can specify the uniform distribution with 'uniform'.
---
--- For @Tree@, @'genericArbitrary' 'uniform'@ produces code equivalent to the
--- following:
---
--- @
--- 'genericArbitrary' 'uniform' :: Arbitrary a => Gen (Tree a)
--- 'genericArbitrary' 'uniform' =
--- oneof
--- [ Leaf \<$\> arbitrary -- Uses Arbitrary a
--- , Node \<$\> arbitrary \<*\> arbitrary -- Uses Arbitrary (Tree a)
--- ]
--- @
---
--- Note that for many types, a uniform distribution tends to produce big
--- values. For instance for @Tree a@, generated values are finite but the
--- __average__ number of @Leaf@ and @Node@ constructors is __infinite__.
---
-- == Ensuring termination
--
-- As was just mentioned, one must be careful with recursive types
@@ -191,7 +187,10 @@
(
-- * Arbitrary implementations
genericArbitrary
+ , genericArbitraryU
, genericArbitrary'
+ , genericArbitraryU0
+ , genericArbitraryU1
-- * Specifying finite distributions
, Weights
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generic-random-0.4.1.0/src/Generic/Random/Internal/Generic.hs new/generic-random-0.5.0.0/src/Generic/Random/Internal/Generic.hs
--- old/generic-random-0.4.1.0/src/Generic/Random/Internal/Generic.hs 2017-03-05 21:30:37.000000000 +0100
+++ new/generic-random-0.5.0.0/src/Generic/Random/Internal/Generic.hs 2017-04-10 17:25:58.000000000 +0200
@@ -1,4 +1,5 @@
{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
@@ -15,8 +16,8 @@
import Control.Applicative
import Data.Coerce
-import GHC.Exts (Proxy#, proxy#)
-import GHC.Generics hiding ( S )
+import Data.Proxy
+import GHC.Generics hiding (S, Arity)
import GHC.TypeLits
import Test.QuickCheck
@@ -27,12 +28,19 @@
genericArbitrary
:: forall a
. (Generic a, GA Unsized (Rep a))
- => Weights a
+ => Weights a -- ^ List of weights for every constructor
-> Gen a
genericArbitrary (Weights w n) = (unGen' . fmap to) (ga w n :: Gen' Unsized (Rep a p))
--- | Like 'genericArbitrary'', with bounded size to ensure termination for
--- recursive types.
+-- | Shorthand for @'genericArbitrary' 'uniform'@.
+genericArbitraryU
+ :: forall a
+ . (Generic a, GA Unsized (Rep a), UniformWeight (Weights_ (Rep a)))
+ => Gen a
+genericArbitraryU = genericArbitrary uniform
+
+-- | Like 'genericArbitrary'', with decreasing size to ensure termination for
+-- recursive types, looking for base cases once the size reaches 0.
genericArbitrary'
:: forall n a
. (Generic a, GA (Sized n) (Rep a))
@@ -42,13 +50,32 @@
genericArbitrary' _ (Weights w n) =
(unGen' . fmap to) (ga w n :: Gen' (Sized n) (Rep a p))
+-- | Shorthand for @'genericArbitrary'' 'Z' 'uniform'@, using nullary
+-- constructors as the base cases.
+genericArbitraryU0
+ :: forall n a
+ . (Generic a, GA (Sized Z) (Rep a), UniformWeight (Weights_ (Rep a)))
+ => Gen a
+genericArbitraryU0 = genericArbitrary' Z uniform
+
+-- | Shorthand for @'genericArbitrary'' ('S' 'Z') 'uniform'@, using nullary
+-- constructors and constructors whose fields are all nullary as base cases.
+genericArbitraryU1
+ :: forall n a
+ . (Generic a, GA (Sized (S Z)) (Rep a), UniformWeight (Weights_ (Rep a)))
+ => Gen a
+genericArbitraryU1 = genericArbitrary' (S Z) uniform
-- * Internal
type family Weights_ (f :: * -> *) :: * where
Weights_ (f :+: g) = Weights_ f :| Weights_ g
Weights_ (M1 D _c f) = Weights_ f
+#if __GLASGOW_HASKELL__ >= 800
Weights_ (M1 C ('MetaCons c _i _j) _f) = L c
+#else
+ Weights_ (M1 C _c _f) = ()
+#endif
data a :| b = N a Int b
data L (c :: Symbol) = L
@@ -110,6 +137,10 @@
type Prec (L c) r = r
W m % prec = (L, m, prec)
+instance WeightBuilder () where
+ type Prec () r = r
+ W m % prec = ((), m, prec)
+
class UniformWeight a where
uniformWeight :: (a, Int)
@@ -124,6 +155,9 @@
instance UniformWeight (L c) where
uniformWeight = (L, 1)
+instance UniformWeight () where
+ uniformWeight = ((), 1)
+
newtype Gen' sized a = Gen' { unGen' :: Gen a }
deriving (Functor, Applicative, Monad)
@@ -144,9 +178,9 @@
ga _ _ = (Gen' . fmap M1) gaProduct
instance (GAProduct f, KnownNat (Arity f)) => GA (Sized n) (M1 C c f) where
- ga _ _ = Gen' (scale (`div` arity) gaProduct)
+ ga _ _ = Gen' (sized $ \n -> resize (n `div` arity) gaProduct)
where
- arity = fromInteger (natVal' (proxy# :: Proxy# (Arity f)))
+ arity = fromInteger (natVal (Proxy :: Proxy (Arity f)))
instance (GASum (Sized n) f, GASum (Sized n) g, BaseCases n f, BaseCases n g)
=> GA (Sized n) (f :+: g) where
++++++ generic-random.cabal ++++++
name: generic-random
version: 0.5.0.0
x-revision: 2
synopsis: Generic random generators
description:
Please see the README.
Note: this package no longer exports Boltzmann samplers by default although they appear below.
("Generic.Random.Data", "Generic.Random.Boltzmann")
homepage: http://github.com/lysxia/generic-random
license: MIT
license-file: LICENSE
stability: Experimental
author: Li-yao Xia
maintainer: lysxia(a)gmail.com
category: Generics, Testing
build-type: Simple
extra-source-files: README.md CHANGELOG.md
cabal-version: >=1.10
tested-with: GHC == 8.0.1
flag boltzmann
Description:
Dependency on boltzmann-samplers for backwards compatibility.
Manual: False
Default: False
library
hs-source-dirs: src
exposed-modules:
Generic.Random.Generic
Generic.Random.Internal.Generic
build-depends:
base >= 4.7 && < 4.11,
QuickCheck
if flag(boltzmann)
exposed-modules:
Generic.Random.Boltzmann
Generic.Random.Data
build-depends:
boltzmann-samplers <= 0.2
default-language: Haskell2010
ghc-options: -Wall -fno-warn-name-shadowing
source-repository head
type: git
location: https://github.com/lysxia/generic-random
1
0
Hello community,
here is the log from the commit of package ghc-generic-aeson for openSUSE:Factory checked in at 2017-08-31 20:47:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-generic-aeson (Old)
and /work/SRC/openSUSE:Factory/.ghc-generic-aeson.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-generic-aeson"
Thu Aug 31 20:47:06 2017 rev:4 rq:513244 version:0.2.0.9
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-generic-aeson/ghc-generic-aeson.changes 2017-06-04 01:53:23.186811955 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-generic-aeson.new/ghc-generic-aeson.changes 2017-08-31 20:47:06.994169381 +0200
@@ -1,0 +2,5 @@
+Fri Jul 28 03:01:25 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.2.0.9 revision 1.
+
+-------------------------------------------------------------------
New:
----
generic-aeson.cabal
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-generic-aeson.spec ++++++
--- /var/tmp/diff_new_pack.1JNqqU/_old 2017-08-31 20:47:07.958034089 +0200
+++ /var/tmp/diff_new_pack.1JNqqU/_new 2017-08-31 20:47:07.970032405 +0200
@@ -25,6 +25,7 @@
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
+Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-aeson-devel
BuildRequires: ghc-attoparsec-devel
@@ -53,6 +54,7 @@
%prep
%setup -q -n %{pkg_name}-%{version}
+cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
++++++ generic-aeson.cabal ++++++
name: generic-aeson
version: 0.2.0.9
x-revision: 1
synopsis: Derivation of Aeson instances using GHC generics.
description: Derivation of Aeson instances using GHC generics.
author: Silk
maintainer: code(a)silk.co
license: BSD3
license-file: LICENSE
category: Data
build-type: Simple
cabal-version: >=1.8
extra-source-files:
CHANGELOG.md
LICENSE
README.md
source-repository head
type: git
location: https://github.com/silkapp/generic-aeson.git
library
ghc-options: -Wall
hs-source-dirs: src
exposed-modules:
Generics.Generic.Aeson
Generics.Generic.Aeson.Util
Generics.Generic.IsEnum
build-depends:
base >= 4.4 && < 4.11
, aeson >= 0.6 && < 1.3
, attoparsec >= 0.11 && < 0.14
, generic-deriving >= 1.6 && < 1.12
, mtl >= 2.0 && < 2.3
, tagged >= 0.2 && < 0.9
, text >= 0.11 && < 1.3
, unordered-containers == 0.2.*
, vector >= 0.10 && < 0.13
if impl(ghc < 7.6)
build-depends: ghc-prim
1
0
Hello community,
here is the log from the commit of package ghc-friendly-time for openSUSE:Factory checked in at 2017-08-31 20:47:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-friendly-time (Old)
and /work/SRC/openSUSE:Factory/.ghc-friendly-time.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-friendly-time"
Thu Aug 31 20:47:03 2017 rev:2 rq:513243 version:0.4.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-friendly-time/ghc-friendly-time.changes 2017-04-12 18:06:29.232498637 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-friendly-time.new/ghc-friendly-time.changes 2017-08-31 20:47:05.474382706 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:06:50 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.4.1 revision 1.
+
+-------------------------------------------------------------------
Old:
----
friendly-time-0.4.tar.gz
New:
----
friendly-time-0.4.1.tar.gz
friendly-time.cabal
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-friendly-time.spec ++++++
--- /var/tmp/diff_new_pack.OuvUKc/_old 2017-08-31 20:47:06.586226642 +0200
+++ /var/tmp/diff_new_pack.OuvUKc/_new 2017-08-31 20:47:06.590226080 +0200
@@ -19,13 +19,14 @@
%global pkg_name friendly-time
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.4
+Version: 0.4.1
Release: 0
Summary: Print time information in friendly ways
License: BSD-3-Clause
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
+Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal…
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-old-locale-devel
BuildRequires: ghc-rpm-macros
@@ -51,6 +52,7 @@
%prep
%setup -q -n %{pkg_name}-%{version}
+cp -p %{SOURCE1} %{pkg_name}.cabal
%build
%ghc_lib_build
++++++ friendly-time-0.4.tar.gz -> friendly-time-0.4.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/friendly-time-0.4/friendly-time.cabal new/friendly-time-0.4.1/friendly-time.cabal
--- old/friendly-time-0.4/friendly-time.cabal 2015-05-04 18:58:31.000000000 +0200
+++ new/friendly-time-0.4.1/friendly-time.cabal 2017-07-21 19:29:16.000000000 +0200
@@ -1,36 +1,49 @@
-name: friendly-time
-version: 0.4
-author: Pat Brisbin <pbrisbin(a)gmail.com>
-maintainer: Pat Brisbin <pbrisbin(a)gmail.com>
-category: Web, Yesod
-license: BSD3
-license-file: LICENSE
-synopsis: Print time information in friendly ways
-description: Print time information in friendly ways
-build-type: Simple
-cabal-version: >= 1.10
-build-type: Simple
+-- This file has been generated from package.yaml by hpack version 0.17.0.
+--
+-- see: https://github.com/sol/hpack
+
+name: friendly-time
+version: 0.4.1
+synopsis: Print time information in friendly ways
+description: Print time information in friendly ways
+category: Web, Yesod
+author: Pat Brisbin <pbrisbin(a)gmail.com>
+maintainer: Pat Brisbin <pbrisbin(a)gmail.com>
+license: BSD3
+license-file: LICENSE
+build-type: Simple
+cabal-version: >= 1.10
+
+source-repository head
+ type: git
+ location: git://github.com/pbrisbin/friendly-time.git
library
- default-language: Haskell2010
- hs-source-dirs: src
- ghc-options: -Wall
- exposed-modules: Data.Time.Format.Human
- build-depends: base >= 4 && < 5
- , time >= 1.4
- , old-locale
+ hs-source-dirs:
+ src
+ ghc-options: -Wall
+ build-depends:
+ time >=1.4
+ , old-locale
+ , base >=4 && <5
+ exposed-modules:
+ Data.Time.Format.Human
+ Data.Time.Format.Human.Locales
+ other-modules:
+ Paths_friendly_time
+ default-language: Haskell2010
test-suite spec
- type: exitcode-stdio-1.0
- default-language: Haskell2010
- hs-source-dirs: test
- main-is: Spec.hs
- build-depends: base
- , hspec
- , friendly-time
- , time >= 1.4
- , old-locale
-
-source-repository head
- type: git
- location: git://github.com/pbrisbin/friendly-time.git
+ type: exitcode-stdio-1.0
+ main-is: Spec.hs
+ hs-source-dirs:
+ test
+ build-depends:
+ time >=1.4
+ , old-locale
+ , base
+ , hspec
+ , friendly-time
+ other-modules:
+ Data.Time.Format.HumanSpec
+ default-language: Haskell2010
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/friendly-time-0.4/src/Data/Time/Format/Human/Locales.hs new/friendly-time-0.4.1/src/Data/Time/Format/Human/Locales.hs
--- old/friendly-time-0.4/src/Data/Time/Format/Human/Locales.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/friendly-time-0.4.1/src/Data/Time/Format/Human/Locales.hs 2017-07-21 19:19:48.000000000 +0200
@@ -0,0 +1,62 @@
+module Data.Time.Format.Human.Locales
+ ( spanishHumanTimeLocale
+ ) where
+
+import Data.Time
+import Data.Time.Format.Human
+
+-- | Spanish human time locale.
+spanishHumanTimeLocale :: HumanTimeLocale
+spanishHumanTimeLocale = HumanTimeLocale
+ { justNow = "Justo ahora"
+ , secondsAgo = \f x -> (dir f ++ " " ++ x ++ " segundos")
+ , oneMinuteAgo = \f -> dir f ++ " un minuto"
+ , minutesAgo = \f x -> (dir f ++ " " ++ x ++ " minutos")
+ , oneHourAgo = \f -> dir f ++ " una hora"
+ , aboutHoursAgo = \f x -> dir f ++ " aproximadamente " ++ x ++ " horas"
+ , at = \_ -> ("El " ++)
+ , daysAgo = \f x -> (dir f ++ " " ++ x ++ " dias")
+ , weekAgo = \f x -> (dir f ++ " " ++ x ++ " semana")
+ , weeksAgo = \f x -> (dir f ++ " " ++ x ++ " semanas")
+ , onYear = ("En " ++)
+ , locale = spanishTimeLocale
+ , timeZone = utc
+ , dayOfWeekFmt = "%A a las %l:%M %p"
+ , thisYearFmt = "%b/%e"
+ , prevYearFmt = "%Y/%b/%e"
+ }
+ where
+ dir True = "Dentro de"
+ dir False = "Hace"
+ spanishTimeLocale = TimeLocale {
+ wDays = [("Domingo", "Dom"), ("Lunes", "Lun"),
+ ("Martes", "Mar"), ("Miercoles", "Mie"),
+ ("Jueves", "Jue"), ("Viernes", "Vie"),
+ ("Sabado", "Sab")],
+
+ months = [("Enero", "Ene"), ("Febrero", "Feb"),
+ ("Marzo", "Mar"), ("Abril", "Abr"),
+ ("Mayo", "May"), ("Junio", "Jun"),
+ ("Julio", "Jul"), ("Agosto", "Ago"),
+ ("Septiembre", "Sep"), ("Octubre", "Oct"),
+ ("Noviembre", "Nov"), ("Diciembre", "Dec")],
+
+ amPm = ("AM", "PM"),
+ dateTimeFmt = "%a %b %e %H:%M:%S %Z %Y",
+ dateFmt = "%y/%m/%d",
+ timeFmt = "%H:%M:%S",
+ time12Fmt = "%I:%M:%S %p",
+ knownTimeZones =
+ [
+ TimeZone 0 False "UT",
+ TimeZone 0 False "GMT",
+ TimeZone (-5 * 60) False "EST",
+ TimeZone (-4 * 60) True "EDT",
+ TimeZone (-6 * 60) False "CST",
+ TimeZone (-5 * 60) True "CDT",
+ TimeZone (-7 * 60) False "MST",
+ TimeZone (-6 * 60) True "MDT",
+ TimeZone (-8 * 60) False "PST",
+ TimeZone (-7 * 60) True "PDT"
+ ]
+ }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/friendly-time-0.4/test/Data/Time/Format/HumanSpec.hs new/friendly-time-0.4.1/test/Data/Time/Format/HumanSpec.hs
--- old/friendly-time-0.4/test/Data/Time/Format/HumanSpec.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/friendly-time-0.4.1/test/Data/Time/Format/HumanSpec.hs 2017-07-21 19:19:48.000000000 +0200
@@ -0,0 +1,98 @@
+{-# LANGUAGE CPP #-}
+
+module Data.Time.Format.HumanSpec
+ ( main
+ , spec
+ ) where
+
+import Test.Hspec
+import Data.Time.Format.Human
+
+import Data.Maybe (fromJust)
+import Data.Time
+
+#if !MIN_VERSION_time(1,5,0)
+import System.Locale (defaultTimeLocale)
+parseTimeM _ = parseTime
+#endif
+
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = describe "humanReadableTime'" $ do
+ it "returns just now for near times" $ do
+ let n = parseTime' "2015-01-01 01:00:00.1"
+ t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "just now"
+ humanReadableTime' t n `shouldBe` "just now"
+
+ it "returns seconds for times less than a minute" $ do
+ let n = parseTime' "2015-01-01 01:00:59"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "59 seconds ago"
+ humanReadableTime' t n `shouldBe` "59 seconds from now"
+
+ it "returns minutes for times less than an hour" $ do
+ let n = parseTime' "2015-01-01 01:59:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "59 minutes ago"
+ humanReadableTime' t n `shouldBe` "59 minutes from now"
+
+ it "returns hours for times less than a day" $ do
+ let n = parseTime' "2015-01-01 23:59:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "about 22 hours ago"
+ humanReadableTime' t n `shouldBe` "about 22 hours from now"
+
+ context "when less than 5 days " $ do
+ let n = parseTime' "2015-01-04 01:00:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ it "returns day of week in EDT" $ do
+ let l = defaultHumanTimeLocale { timeZone = read "EDT" }
+
+ humanReadableTimeI18N' l n t `shouldBe` "at 9:00 PM on Wednesday"
+ humanReadableTimeI18N' l t n `shouldBe` "at 9:00 PM on Saturday"
+
+ it "returns day of week in India" $ do
+ let l = defaultHumanTimeLocale { timeZone = read "+0530" }
+
+ humanReadableTimeI18N' l n t `shouldBe` "at 6:30 AM on Thursday"
+ humanReadableTimeI18N' l t n `shouldBe` "at 6:30 AM on Sunday"
+
+ it "returns days for times less than 10 days" $ do
+ let n = parseTime' "2015-01-10 01:00:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "9 days ago"
+ humanReadableTime' t n `shouldBe` "9 days from now"
+
+ it "returns weeks for times less than 5 weeks" $ do
+ let n = parseTime' "2015-01-29 01:00:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "4 weeks ago"
+ humanReadableTime' t n `shouldBe` "4 weeks from now"
+
+ it "returns a date string without year for this year" $ do
+ let n = parseTime' "2015-12-30 01:00:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "on Jan 1" -- TODO: spacing
+ humanReadableTime' t n `shouldBe` "on Dec 30"
+
+ it "returns a date string including the year for previous years" $ do
+ let n = parseTime' "2025-12-30 01:00:00"
+ let t = parseTime' "2015-01-01 01:00:00"
+
+ humanReadableTime' n t `shouldBe` "on Jan 1, 2015" -- TODO: spacing
+ humanReadableTime' t n `shouldBe` "on Dec 30, 2025"
+
+parseTime' :: String -> UTCTime
+parseTime' = fromJust . parseTimeM True defaultTimeLocale "%F %T%Q"
++++++ friendly-time.cabal ++++++
-- This file has been generated from package.yaml by hpack version 0.17.0.
--
-- see: https://github.com/sol/hpack
name: friendly-time
version: 0.4.1
x-revision: 1
synopsis: Print time information in friendly ways
description: Print time information in friendly ways
category: Web, Yesod
author: Pat Brisbin <pbrisbin(a)gmail.com>
maintainer: Pat Brisbin <pbrisbin(a)gmail.com>
license: BSD3
license-file: LICENSE
build-type: Simple
cabal-version: >= 1.10
source-repository head
type: git
location: git://github.com/pbrisbin/friendly-time.git
library
hs-source-dirs:
src
ghc-options: -Wall
build-depends:
time >=1.5
, old-locale
, base >=4 && <5
exposed-modules:
Data.Time.Format.Human
Data.Time.Format.Human.Locales
other-modules:
Paths_friendly_time
default-language: Haskell2010
test-suite spec
type: exitcode-stdio-1.0
main-is: Spec.hs
hs-source-dirs:
test
build-depends:
time >=1.4
, old-locale
, base
, hspec
, friendly-time
other-modules:
Data.Time.Format.HumanSpec
default-language: Haskell2010
1
0
Hello community,
here is the log from the commit of package ghc-fay for openSUSE:Factory checked in at 2017-08-31 20:46:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-fay (Old)
and /work/SRC/openSUSE:Factory/.ghc-fay.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-fay"
Thu Aug 31 20:46:58 2017 rev:3 rq:513241 version:0.23.1.16
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-fay/ghc-fay.changes 2017-06-21 13:55:18.643289374 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-fay.new/ghc-fay.changes 2017-08-31 20:47:00.863029976 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 03:01:32 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.23.1.16 revision 8.
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-fay.spec ++++++
--- /var/tmp/diff_new_pack.Upvwtr/_old 2017-08-31 20:47:03.266692587 +0200
+++ /var/tmp/diff_new_pack.Upvwtr/_new 2017-08-31 20:47:03.270692026 +0200
@@ -25,7 +25,7 @@
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
-Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/7.cabal…
+Source1: https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/8.cabal…
BuildRequires: chrpath
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-aeson-devel
++++++ fay.cabal ++++++
--- /var/tmp/diff_new_pack.Upvwtr/_old 2017-08-31 20:47:03.346681360 +0200
+++ /var/tmp/diff_new_pack.Upvwtr/_new 2017-08-31 20:47:03.350680799 +0200
@@ -1,6 +1,6 @@
name: fay
version: 0.23.1.16
-x-revision: 7
+x-revision: 8
synopsis: A compiler for Fay, a Haskell subset that compiles to JavaScript.
description: Fay is a proper subset of Haskell which is type-checked
with GHC, and compiled to JavaScript. It is lazy, pure, has a Fay monad,
@@ -136,7 +136,7 @@
Paths_fay
build-depends:
- base >= 4.5 && < 4.10
+ base >= 4.5 && < 4.11
, base-compat >= 0.8 && < 0.10
, aeson > 0.6 && < 1.3
, bytestring >= 0.9 && < 0.11
1
0
Hello community,
here is the log from the commit of package ghc-extensible for openSUSE:Factory checked in at 2017-08-31 20:46:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-extensible (Old)
and /work/SRC/openSUSE:Factory/.ghc-extensible.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-extensible"
Thu Aug 31 20:46:56 2017 rev:2 rq:513240 version:0.4.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-extensible/ghc-extensible.changes 2017-04-12 18:06:18.314042444 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-extensible.new/ghc-extensible.changes 2017-08-31 20:46:58.095418451 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:02:33 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.4.2.
+
+-------------------------------------------------------------------
Old:
----
extensible-0.3.7.tar.gz
New:
----
extensible-0.4.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-extensible.spec ++++++
--- /var/tmp/diff_new_pack.vxNewE/_old 2017-08-31 20:46:58.951298316 +0200
+++ /var/tmp/diff_new_pack.vxNewE/_new 2017-08-31 20:46:58.959297193 +0200
@@ -18,25 +18,30 @@
%global pkg_name extensible
Name: ghc-%{pkg_name}
-Version: 0.3.7
+Version: 0.4.2
Release: 0
-Summary: Extensible, efficient, optics-friendly data types
+Summary: Extensible, efficient, optics-friendly data types and effects
License: BSD-3-Clause
Group: Development/Languages/Other
Url: https://hackage.haskell.org/package/%{pkg_name}
Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{ve…
BuildRequires: ghc-Cabal-devel
+BuildRequires: ghc-comonad-devel
BuildRequires: ghc-constraints-devel
+BuildRequires: ghc-deepseq-devel
BuildRequires: ghc-monad-skeleton-devel
+BuildRequires: ghc-mtl-devel
+BuildRequires: ghc-primitive-devel
BuildRequires: ghc-profunctors-devel
BuildRequires: ghc-rpm-macros
+BuildRequires: ghc-semigroups-devel
BuildRequires: ghc-tagged-devel
BuildRequires: ghc-template-haskell-devel
BuildRequires: ghc-transformers-devel
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%description
-Poly-kinded extensible records and variants.
+Poly-kinded extensible records, variants, effects, tangles.
%package devel
Summary: Haskell %{pkg_name} library development files
++++++ extensible-0.3.7.tar.gz -> extensible-0.4.2.tar.gz ++++++
++++ 4227 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package ghc-ersatz for openSUSE:Factory checked in at 2017-08-31 20:46:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-ersatz (Old)
and /work/SRC/openSUSE:Factory/.ghc-ersatz.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-ersatz"
Thu Aug 31 20:46:54 2017 rev:2 rq:513237 version:0.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-ersatz/ghc-ersatz.changes 2017-04-12 18:06:14.654559873 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-ersatz.new/ghc-ersatz.changes 2017-08-31 20:46:55.779743490 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:05:54 UTC 2017 - psimons(a)suse.com
+
+- Update to version 0.4.
+
+-------------------------------------------------------------------
Old:
----
ersatz-0.3.1.tar.gz
New:
----
ersatz-0.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-ersatz.spec ++++++
--- /var/tmp/diff_new_pack.pSLY3R/_old 2017-08-31 20:46:56.727610443 +0200
+++ /var/tmp/diff_new_pack.pSLY3R/_new 2017-08-31 20:46:56.731609882 +0200
@@ -19,7 +19,7 @@
%global pkg_name ersatz
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 0.3.1
+Version: 0.4
Release: 0
Summary: A monad for expressing SAT or QSAT problems using observable sharing
License: BSD-3-Clause
@@ -29,7 +29,9 @@
BuildRequires: chrpath
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-array-devel
+BuildRequires: ghc-attoparsec-devel
BuildRequires: ghc-bytestring-devel
+BuildRequires: ghc-cabal-doctest-devel
BuildRequires: ghc-containers-devel
BuildRequires: ghc-data-default-devel
BuildRequires: ghc-lens-devel
@@ -79,8 +81,9 @@
'ersatz-regexp-grid'
-This solves the "regular crossword puzzle" (<grid.pdf>) from the 2013 MIT
-mystery hunt.
+This solves the "regular crossword puzzle"
+(<https://github.com/ekmett/ersatz/raw/master/notes/grid.pdf grid.pdf>) from
+the 2013 MIT mystery hunt.
> % time ersatz-regexp-grid
++++++ ersatz-0.3.1.tar.gz -> ersatz-0.4.tar.gz ++++++
++++ 1675 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package ghc-email-validate for openSUSE:Factory checked in at 2017-08-31 20:46:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-email-validate (Old)
and /work/SRC/openSUSE:Factory/.ghc-email-validate.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-email-validate"
Thu Aug 31 20:46:52 2017 rev:4 rq:513234 version:2.3
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-email-validate/ghc-email-validate.changes 2017-07-11 08:26:12.156424440 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-email-validate.new/ghc-email-validate.changes 2017-08-31 20:46:53.372081440 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:07:12 UTC 2017 - psimons(a)suse.com
+
+- Update to version 2.3.
+
+-------------------------------------------------------------------
Old:
----
email-validate-2.2.1.1.tar.gz
New:
----
email-validate-2.3.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-email-validate.spec ++++++
--- /var/tmp/diff_new_pack.4ua4mI/_old 2017-08-31 20:46:54.183967480 +0200
+++ /var/tmp/diff_new_pack.4ua4mI/_new 2017-08-31 20:46:54.187966919 +0200
@@ -19,7 +19,7 @@
%global pkg_name email-validate
%bcond_with tests
Name: ghc-%{pkg_name}
-Version: 2.2.1.1
+Version: 2.3
Release: 0
Summary: Email address validation
License: BSD-3-Clause
@@ -30,13 +30,12 @@
BuildRequires: ghc-attoparsec-devel
BuildRequires: ghc-bytestring-devel
BuildRequires: ghc-rpm-macros
+BuildRequires: ghc-template-haskell-devel
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%if %{with tests}
-BuildRequires: ghc-HUnit-devel
BuildRequires: ghc-QuickCheck-devel
-BuildRequires: ghc-test-framework-devel
-BuildRequires: ghc-test-framework-hunit-devel
-BuildRequires: ghc-test-framework-quickcheck2-devel
+BuildRequires: ghc-doctest-devel
+BuildRequires: ghc-hspec-devel
%endif
%description
++++++ email-validate-2.2.1.1.tar.gz -> email-validate-2.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/email-validate.cabal new/email-validate-2.3/email-validate.cabal
--- old/email-validate-2.2.1.1/email-validate.cabal 2017-06-26 01:32:54.000000000 +0200
+++ new/email-validate-2.3/email-validate.cabal 2017-06-26 08:49:19.000000000 +0200
@@ -1,5 +1,5 @@
name: email-validate
-version: 2.2.1.1
+version: 2.3
cabal-version: >=1.10
build-type: Simple
license: BSD3
@@ -20,17 +20,18 @@
source-repository this
type: git
location: git://github.com/Porges/email-validate-hs.git
- tag: v2.2.1.1
+ tag: v2.3
library
exposed-modules:
- Text.Domain.Parser
+ Text.Email.QuasiQuotation
Text.Email.Validate
Text.Email.Parser
build-depends:
base >=4.4 && <5,
attoparsec >=0.10.0 && <0.14,
- bytestring >=0.9 && <0.11
+ bytestring >=0.9 && <0.11,
+ template-haskell >=2.11.1.0 && <2.12
default-language: Haskell2010
hs-source-dirs: src
ghc-options: -Wall
@@ -39,13 +40,20 @@
type: exitcode-stdio-1.0
main-is: Main.hs
build-depends:
+ email-validate ==2.3.*,
base ==4.*,
- HUnit >=1.2 && <2,
- email-validate >=2.2.1.1 && <2.3,
+ hspec >=2.4.3 && <2.5,
QuickCheck >=2.4 && <2.11,
- test-framework >=0.4.1 && <0.9,
- test-framework-quickcheck2 >=0.3.0.4 && <0.4,
- test-framework-hunit >=0.3.0.2 && <0.4,
bytestring >=0.9 && <0.11
default-language: Haskell2010
hs-source-dirs: tests
+ ghc-options: -threaded
+test-suite doctests
+ type: exitcode-stdio-1.0
+ main-is: doctests.hs
+ build-depends:
+ base >=4.9.1.0 && <4.10,
+ doctest >=0.8 && <0.12
+ default-language: Haskell2010
+ hs-source-dirs: tests
+ ghc-options: -threaded
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/src/Text/Domain/Parser.hs new/email-validate-2.3/src/Text/Domain/Parser.hs
--- old/email-validate-2.2.1.1/src/Text/Domain/Parser.hs 2017-06-26 01:25:25.000000000 +0200
+++ new/email-validate-2.3/src/Text/Domain/Parser.hs 1970-01-01 01:00:00.000000000 +0100
@@ -1,41 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
-
-module Text.Domain.Parser
- ( domainParser
- )
-where
-
-import Control.Applicative
-import Control.Monad (guard)
-import Data.Attoparsec.ByteString.Char8
-import qualified Data.ByteString.Char8 as BS
-import Data.ByteString (ByteString)
-
-domainParser :: Parser ByteString
-domainParser = do
- domain <- fst <$> match (label `sepBy1` char '.' >> optional (char '.'))
-
- -- trim off the excess '.' if it is there
- let trimmed =
- case BS.last domain of
- '.' -> BS.init domain
- _ -> domain
-
- -- domain name must be no greater than 253 chars
- guard (BS.length trimmed <= 253)
- return trimmed
-
-label :: Parser ByteString
-label = do
- lbl <- fst <$> match (alphaNum >> skipWhile isAlphaNumHyphen)
-
- -- label must be no greater than 63 chars and cannot end with '-'
- guard (BS.length lbl <= 63 && BS.last lbl /= '-')
- return lbl
-
-alphaNum :: Parser Char
-alphaNum = satisfy isAlphaNum
- where isAlphaNum x = isDigit x || isAlpha_ascii x
-
-isAlphaNumHyphen :: Char -> Bool
-isAlphaNumHyphen x = isDigit x || isAlpha_ascii x || x == '-'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/src/Text/Email/Parser.hs new/email-validate-2.3/src/Text/Email/Parser.hs
--- old/email-validate-2.2.1.1/src/Text/Email/Parser.hs 2017-06-26 01:25:25.000000000 +0200
+++ new/email-validate-2.3/src/Text/Email/Parser.hs 2017-06-26 08:45:38.000000000 +0200
@@ -11,7 +11,7 @@
where
import Control.Applicative
-import Control.Monad (void)
+import Control.Monad (guard, void, when)
import Data.Attoparsec.ByteString.Char8
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS
@@ -19,8 +19,6 @@
import GHC.Generics (Generic)
import qualified Text.Read as Read
-import Text.Domain.Parser (domainParser)
-
-- | Represents an email address.
data EmailAddress = EmailAddress ByteString ByteString
deriving (Eq, Ord, Data, Typeable, Generic)
@@ -57,7 +55,19 @@
-- | A parser for email addresses.
addrSpec :: Parser EmailAddress
-addrSpec = unsafeEmailAddress <$> local <* char '@' <*> domain
+addrSpec = do
+ l <- local
+
+ -- Maximum length of local-part is 64, per RFC3696
+ when (BS.length l > 64) (fail "local-part of email is too long (more than 64 octets)")
+
+ _ <- char '@' <?> "at sign"
+ d <- domain
+
+ -- Maximum length is 254, per Erratum 1690 on RFC3696
+ when (BS.length l + BS.length d + 1 > 254) (fail "email address is too long (more than 254 octets)")
+
+ return (unsafeEmailAddress l d)
local :: Parser ByteString
local = dottedAtoms
@@ -67,10 +77,28 @@
domainName :: Parser ByteString
domainName = do
- raw <- BS.append <$> dottedAtoms <*> option BS.empty (string (BS.pack "."))
- case parseOnly (domainParser <* endOfInput) raw of
- Left err -> fail err
- Right result -> return result
+ parsedDomain <- BS.intercalate (BS.singleton '.') <$>
+ domainLabel `sepBy1` char '.' <* optional (char '.')
+
+ -- Domain name must be no greater than 253 chars, per RFC1035
+ guard (BS.length parsedDomain <= 253)
+ return parsedDomain
+
+domainLabel :: Parser ByteString
+domainLabel = do
+ content <- between1 (optional cfws) (fst <$> match (alphaNum >> skipWhile isAlphaNumHyphen))
+
+ -- Per RFC1035:
+ -- label must be no greater than 63 chars and cannot end with '-'
+ -- (we already enforced that it does not start with '-')
+ guard (BS.length content <= 63 && BS.last content /= '-')
+ return content
+
+alphaNum :: Parser Char
+alphaNum = satisfy isAlphaNum
+
+isAlphaNumHyphen :: Char -> Bool
+isAlphaNumHyphen x = isDigit x || isAlpha_ascii x || x == '-'
dottedAtoms :: Parser ByteString
dottedAtoms = BS.intercalate (BS.singleton '.') <$>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/src/Text/Email/QuasiQuotation.hs new/email-validate-2.3/src/Text/Email/QuasiQuotation.hs
--- old/email-validate-2.2.1.1/src/Text/Email/QuasiQuotation.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/email-validate-2.3/src/Text/Email/QuasiQuotation.hs 2017-06-26 08:45:38.000000000 +0200
@@ -0,0 +1,42 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# LANGUAGE TemplateHaskellQuotes #-}
+#else
+{-# LANGUAGE TemplateHaskell #-}
+#endif
+
+module Text.Email.QuasiQuotation
+ ( email
+ ) where
+
+import qualified Data.ByteString.Char8 as BS8
+
+import Language.Haskell.TH.Quote (QuasiQuoter(..))
+
+import Text.Email.Validate (validate, localPart, domainPart, unsafeEmailAddress)
+
+-- | A QuasiQuoter for email addresses.
+--
+-- Use it like this:
+--
+-- >>> :set -XQuasiQuotes
+-- >>> [email|someone(a)example.com|]
+-- "someone(a)example.com"
+email :: QuasiQuoter
+email = QuasiQuoter
+ { quoteExp = quoteEmail emailToExp
+ , quotePat = error "email is not supported as a pattern"
+ , quoteDec = error "email is not supported at top-level"
+ , quoteType = error "email is not supported as a type"
+ }
+ where
+
+ quoteEmail p s =
+ case validate (BS8.pack s) of
+ Left err -> error ("Invalid quasi-quoted email address: " ++ err)
+ Right e -> p e
+
+ emailToExp e =
+ let lp = BS8.unpack (localPart e) in
+ let dp = BS8.unpack (domainPart e) in
+ [| unsafeEmailAddress (BS8.pack lp) (BS8.pack dp) |]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/src/Text/Email/Validate.hs new/email-validate-2.3/src/Text/Email/Validate.hs
--- old/email-validate-2.2.1.1/src/Text/Email/Validate.hs 2017-06-26 01:25:25.000000000 +0200
+++ new/email-validate-2.3/src/Text/Email/Validate.hs 2017-06-26 08:45:38.000000000 +0200
@@ -1,21 +1,32 @@
module Text.Email.Validate
- ( isValid
- , validate
- , emailAddress
- , canonicalizeEmail
- , EmailAddress -- re-exported
- , unsafeEmailAddress
- , localPart
- , domainPart
- , toByteString
- )
+ ( isValid
+ , validate
+ , emailAddress
+ , canonicalizeEmail
+
+ -- Re-exports:
+ , EmailAddress
+ , domainPart
+ , localPart
+ , toByteString
+ , unsafeEmailAddress
+ )
where
-import Data.Attoparsec.ByteString (endOfInput, parseOnly)
-import Data.ByteString (ByteString)
+import Data.Attoparsec.ByteString (endOfInput, parseOnly)
+import Data.ByteString (ByteString)
-import Text.Email.Parser (EmailAddress, addrSpec, domainPart,
- localPart, toByteString, unsafeEmailAddress)
+import Text.Email.Parser
+ ( EmailAddress
+ , addrSpec
+ , domainPart
+ , localPart
+ , toByteString
+ , unsafeEmailAddress)
+
+-- $setup
+-- This is required for all examples:
+-- >>> :set -XOverloadedStrings
-- | Smart constructor for an email address
emailAddress :: ByteString -> Maybe EmailAddress
@@ -23,6 +34,10 @@
-- | Checks that an email is valid and returns a version of it
-- where comments and whitespace have been removed.
+--
+-- Example:
+-- >>> canonicalizeEmail "spaces. are. allowed(a)example.com"
+-- Just "spaces.are.allowed(a)example.com"
canonicalizeEmail :: ByteString -> Maybe ByteString
canonicalizeEmail = fmap toByteString . emailAddress
@@ -33,5 +48,12 @@
-- | If you want to find out *why* a particular string is not
-- an email address, use this.
+--
+-- Examples:
+-- >>> validate "example(a)example.com"
+-- Right "example(a)example.com"
+-- >>> validate "not.good"
+-- Left "at sign > @: not enough input"
validate :: ByteString -> Either String EmailAddress
validate = parseOnly (addrSpec >>= \r -> endOfInput >> return r)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/tests/Main.hs new/email-validate-2.3/tests/Main.hs
--- old/email-validate-2.2.1.1/tests/Main.hs 2017-06-26 01:25:25.000000000 +0200
+++ new/email-validate-2.3/tests/Main.hs 2017-06-26 08:45:39.000000000 +0200
@@ -1,19 +1,21 @@
{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
+import Control.Exception (evaluate)
+import Control.Monad (forM_)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS
-import Data.Maybe (Maybe(..), isNothing)
+import Data.List (isInfixOf)
+import Data.Maybe (Maybe(..), isNothing, fromJust)
+import Data.Monoid ((<>))
-import Test.Framework as TF (defaultMain, testGroup, Test)
-import Test.Framework.Providers.HUnit (testCase)
-import Test.Framework.Providers.QuickCheck2 (testProperty)
-
-import Test.HUnit ((@?=), assert)
-import Test.QuickCheck (Arbitrary(..), suchThat)
+import Test.Hspec (hspec, context, describe, errorCall, it, parallel, shouldBe, shouldSatisfy)
+import Test.QuickCheck (Arbitrary(..), suchThat, property)
+import Text.Email.QuasiQuotation (email)
import Text.Email.Validate
( EmailAddress
, canonicalizeEmail
@@ -27,56 +29,78 @@
)
main :: IO ()
-main = defaultMain testGroups
-
-{- Tests -}
+main = hspec $ parallel $ do
-testGroups :: [Test]
-testGroups =
- [ showAndRead
- , canonicalization
- , exampleTests
- , specificFailures
- , simpleAccessors
- ]
+ showAndRead
+ canonicalization
+ exampleTests
+ specificFailures
+ simpleAccessors
+ quasiQuotationTests
canonicalization =
- testGroup "QuickCheck Text.Email.Validate"
- [ testProperty "doubleCanonicalize" prop_doubleCanonicalize
- ]
+ describe "emailAddress" $ do
+ it "is idempotent" $
+ property prop_doubleCanonicalize
exampleTests =
- testGroup "Unit tests Text.Email.Validate" (concatMap exampleTest examples)
- where
- exampleTest Example{example, valid, reason} =
- if valid
- then
- [ testCase ("Ensure valid " ++ name) (assert (isValid example))
- , testCase ("doubleCanonicalize test " ++ name) (assert (case emailAddress example of { Just ok -> prop_doubleCanonicalize ok; Nothing -> False }))
- ]
- else
- [ testCase ("Ensure invalid " ++ name) (assert (not (isValid example))) ]
-
- where name = show example ++ (if null reason then "" else " (" ++ reason ++ ")")
+ describe "Examples" $ do
+ forM_ examples $ \Example{example, exampleValid, exampleWhy, errorContains} -> do
+ context (show example ++ (if null exampleWhy then "" else " (" ++ exampleWhy ++ ")")) $ do
+ if exampleValid
+ then do
+ it "should be valid" $
+ isValid example `shouldBe` True
+
+ it "passes double-canonicalization test" $
+ prop_doubleCanonicalize (fromJust (emailAddress example))
+
+ else do
+ it "should be invalid" $
+ isValid example `shouldBe` False
+
+ case (errorContains, validate example) of
+ (Just err, Left errMessage) ->
+ it "should have correct error message" $
+ errMessage `shouldSatisfy` (err `isInfixOf`)
+ (_, _) -> return ()
showAndRead =
- testGroup "EmailAddress Show/Read instances"
- [ testProperty "showLikeByteString" prop_showLikeByteString
- , testProperty "showAndReadBackWithoutQuoteFails" prop_showAndReadBackWithoutQuoteFails
- , testProperty "showAndReadBack" prop_showAndReadBack
- ]
+ describe "show/read instances" $ do
-specificFailures =
- testGroup "Specifics"
- [ testCase "Issue #12" (let (Right em) = validate (BS.pack "\"\"@1") in em @?= read (show em))
- , testCase "Check canonicalization of trailing dot" (canonicalizeEmail "foo(a)bar.com." @?= Just "foo(a)bar.com")
- ]
+ it "can roundtrip" $
+ property prop_showAndReadBack
-simpleAccessors =
- testGroup "Simple accessors"
- [ testCase "local-part" (localPart (unsafeEmailAddress "local" undefined) @?= "local")
- , testCase "domain-part" (domainPart (unsafeEmailAddress undefined "domain") @?= "domain")
- ]
+ it "shows in the same way as ByteString" $
+ property prop_showLikeByteString
+
+ it "should fail if read back without a quote" $
+ property prop_showAndReadBackWithoutQuoteFails
+
+specificFailures = do
+ describe "GitHub issue #12" $ do
+ it "is fixed" $
+ let (Right em) = validate (BS.pack "\"\"@1") in
+ em `shouldBe` read (show em)
+
+ describe "Trailing dot" $ do
+ it "is canonicalized" $
+ canonicalizeEmail "foo(a)bar.com." `shouldBe` Just "foo(a)bar.com"
+
+simpleAccessors = do
+ describe "localPart" $
+ it "extracts local part" $
+ localPart (unsafeEmailAddress "local" undefined) `shouldBe` "local"
+
+
+ describe "domainPart" $
+ it "extracts domain part" $
+ domainPart (unsafeEmailAddress undefined "domain") `shouldBe` "domain"
+
+quasiQuotationTests =
+ describe "QuasiQuoter" $ do
+ it "works as expected" $
+ [email|local(a)domain.com|] `shouldBe` unsafeEmailAddress "local" "domain.com"
instance Arbitrary ByteString where
arbitrary = fmap BS.pack arbitrary
@@ -115,241 +139,262 @@
{- Examples -}
-data Example = Example { example :: ByteString, valid :: Bool, reason :: String }
+data Example = Example
+ { example :: ByteString
+ , exampleValid :: Bool
+ , exampleWhy :: String
+ , errorContains :: Maybe String }
+
+valid, invalid :: ByteString -> Example
+valid e = Example e True "" Nothing
+invalid e = Example e False "" Nothing
+
+why :: Example -> String -> Example
+why ex str = ex { exampleWhy = str }
+
+errorShouldContain :: Example -> String -> Example
+errorShouldContain ex str = ex { errorContains = Just str }
+
examples :: [Example]
examples =
- map (\(e, v, r) -> Example e v r)
- [ ("first.last(a)example.com", True, "")
- , ("first.last(a)example.com.", True, "Dot allowed on end of domain")
- , ("local(a)exam_ple.com", False, "Underscore not permitted in domain")
- , ("1234567890123456789012345678901234567890123456789012345678901234(a)example.com", True, "")
- , ("\"first last\"@example.com", True, "")
- , ("\"first\\\"last\"@example.com", True, "")
- , ("first\\@last@example.com", False, "Escaping can only happen within a quoted string")
- , ("\"first@last\"@example.com", True, "")
- , ("\"first\\\\last\"@example.com", True, "")
- , ("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23", True, "Max length is 253")
- , ("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23.", True, "Trailing dot doesn't increase length")
- , ("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x234", False, "Max length is 253")
- , ("123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.123456789012345678901234567890123456789012345678901234567890123.example.com", True, "")
- , ("first.last(a)[12.34.56.78]", True, "")
- , ("first.last@[IPv6:::12.34.56.78]", True, "")
- , ("first.last@[IPv6:1111:2222:3333::4444:12.34.56.78]", True, "")
- , ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.56.78]", True, "")
- , ("first.last@[IPv6:::1111:2222:3333:4444:5555:6666]", True, "")
- , ("first.last@[IPv6:1111:2222:3333::4444:5555:6666]", True, "")
- , ("first.last@[IPv6:1111:2222:3333:4444:5555:6666::]", True, "")
- , ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]", True, "")
- , ("first.last@x23456789012345678901234567890123456789012345678901234567890123.example.com", True, "")
- , ("first.last(a)1xample.com", True, "")
- , ("first.last(a)123.example.com", True, "")
- , ("first.last", False, "No @")
- , (".first.last(a)example.com", False, "Local part starts with a dot")
- , ("first.last.(a)example.com", False, "Local part ends with a dot")
- , ("first..last(a)example.com", False, "Local part has consecutive dots")
- , ("\"first\"last\"@example.com", False, "Local part contains unescaped excluded characters")
- , ("\"first\\last\"@example.com", True, "Any character can be escaped in a quoted string")
- , ("\"\"\"@example.com", False, "Local part contains unescaped excluded characters")
- , ("\"\\\"@example.com", False, "Local part cannot end with a backslash")
- , ("first\\\\@last@example.com", False, "Local part contains unescaped excluded characters")
- , ("first.last@", False, "No domain")
- , ("\"Abc\\@def\"@example.com", True, "")
- , ("\"Fred\\ Bloggs\"@example.com", True, "")
- , ("\"Joe.\\\\Blow\"@example.com", True, "")
- , ("\"Abc@def\"@example.com", True, "")
- , ("\"Fred Bloggs\"@example.com", True, "")
- , ("user+mailbox(a)example.com", True, "")
- , ("customer/department=shipping(a)example.com", True, "")
- , ("$A12345(a)example.com", True, "")
- , ("!def!xyz%abc(a)example.com", True, "")
- , ("_somename(a)example.com", True, "")
- , ("dclo(a)us.ibm.com", True, "")
- , ("abc\\@def@example.com", False, "This example from RFC3696 was corrected in an erratum")
- , ("abc\\\\(a)example.com", False, "This example from RFC3696 was corrected in an erratum")
- , ("peter.piper(a)example.com", True, "")
- , ("Doug\\ \\\"Ace\\\"\\ Lovell(a)example.com", False, "Escaping can only happen in a quoted string")
- , ("\"Doug \\\"Ace\\\" L.\"@example.com", True, "")
- , ("abc@def@example.com", False, "Doug Lovell says this should fail")
- , ("abc\\\\@def@example.com", False, "Doug Lovell says this should fail")
- , ("abc\\(a)example.com", False, "Doug Lovell says this should fail")
- , ("@example.com", False, "No local part")
- , ("doug@", False, "Doug Lovell says this should fail")
- , ("\"qu(a)example.com", False, "Doug Lovell says this should fail")
- , ("ote\"@example.com", False, "Doug Lovell says this should fail")
- , (".dot(a)example.com", False, "Doug Lovell says this should fail")
- , ("dot.(a)example.com", False, "Doug Lovell says this should fail")
- , ("two..dot(a)example.com", False, "Doug Lovell says this should fail")
- , ("\"Doug \"Ace\" L.\"@example.com", False, "Doug Lovell says this should fail")
- , ("Doug\\ \\\"Ace\\\"\\ L\\.(a)example.com", False, "Doug Lovell says this should fail")
- , ("hello world(a)example.com", False, "Doug Lovell says this should fail")
- , ("gatsby(a)f.sc.ot.t.f.i.tzg.era.l.d.", True, "")
- , ("test(a)example.com", True, "")
- , ("TEST(a)example.com", True, "")
- , ("1234567890(a)example.com", True, "")
- , ("test+test(a)example.com", True, "")
- , ("test-test(a)example.com", True, "")
- , ("t*est(a)example.com", True, "")
- , ("+1~1+(a)example.com", True, "")
- , ("{_test_}(a)example.com", True, "")
- , ("\"[[ test ]]\"@example.com", True, "")
- , ("test.test(a)example.com", True, "")
- , ("\"test.test\"@example.com", True, "")
- , ("test.\"test\"@example.com", True, "Obsolete form, but documented in RFC2822")
- , ("\"test@test\"@example.com", True, "")
- , ("test(a)123.123.123.x123", True, "")
- , ("test(a)[123.123.123.123]", True, "")
- , ("test(a)example.example.com", True, "")
- , ("test(a)example.example.example.com", True, "")
- , ("test.example.com", False, "")
- , ("test.(a)example.com", False, "")
- , ("test..test(a)example.com", False, "")
- , (".test(a)example.com", False, "")
- , ("test@test@example.com", False, "")
- , ("test@@example.com", False, "")
- , ("-- test --(a)example.com", False, "No spaces allowed in local part")
- , ("[test](a)example.com", False, "Square brackets only allowed within quotes")
- , ("\"test\\test\"@example.com", True, "Any character can be escaped in a quoted string")
- , ("\"test\"test\"@example.com", False, "Quotes cannot be nested")
- , ("()[]\\;:,><@example.com", False, "Disallowed Characters")
- , ("test@.", False, "Dave Child says so")
- , ("test@example.", True, "")
- , ("test@.org", False, "Dave Child says so")
- , ("test(a)[123.123.123.123", False, "Dave Child says so")
- , ("test(a)123.123.123.123]", False, "Dave Child says so")
- , ("NotAnEmail", False, "Phil Haack says so")
- , ("@NotAnEmail", False, "Phil Haack says so")
- , ("\"test\\\\blah\"@example.com", True, "")
- , ("\"test\\blah\"@example.com", True, "Any character can be escaped in a quoted string")
- , ("\"test\\\rblah\"@example.com", True, "Quoted string specifically excludes carriage returns unless escaped")
- , ("\"test\rblah\"@example.com", False, "Quoted string specifically excludes carriage returns")
- , ("\"test\\\"blah\"@example.com", True, "")
- , ("\"test\"blah\"@example.com", False, "Phil Haack says so")
- , ("customer/department(a)example.com", True, "")
- , ("_Yosemite.Sam(a)example.com", True, "")
- , ("~(a)example.com", True, "")
- , (".wooly(a)example.com", False, "Phil Haack says so")
- , ("wo..oly(a)example.com", False, "Phil Haack says so")
- , ("pootietang.(a)example.com", False, "Phil Haack says so")
- , (".(a)example.com", False, "Phil Haack says so")
- , ("\"Austin@Powers\"@example.com", True, "")
- , ("Ima.Fool(a)example.com", True, "")
- , ("\"Ima.Fool\"@example.com", True, "")
- , ("\"Ima Fool\"@example.com", True, "")
- , ("Ima Fool(a)example.com", False, "Phil Haack says so")
- , ("phil.h\\@\\@ck@haacked.com", False, "Escaping can only happen in a quoted string")
- , ("\"first\".\"last\"@example.com", True, "")
- , ("\"first\".middle.\"last\"@example.com", True, "")
- , ("\"first\\\\\"last\"@example.com", False, "Contains an unescaped quote")
- , ("\"first\".last(a)example.com", True, "obs-local-part form as described in RFC 2822")
- , ("first.\"last\"@example.com", True, "obs-local-part form as described in RFC 2822")
- , ("\"first\".\"middle\".\"last\"@example.com", True, "obs-local-part form as described in RFC 2822")
- , ("\"first.middle\".\"last\"@example.com", True, "obs-local-part form as described in RFC 2822")
- , ("\"first.middle.last\"@example.com", True, "obs-local-part form as described in RFC 2822")
- , ("\"first..last\"@example.com", True, "obs-local-part form as described in RFC 2822")
- , ("foo(a)[\\1.2.3.4]", False, "RFC 5321 specifies the syntax for address-literal and does not allow escaping")
- , ("\"first\\\\\\\"last\"@example.com", True, "")
- , ("first.\"mid\\dle\".\"last\"@example.com", True, "Backslash can escape anything but must escape something")
- , ("Test.\r\n Folding.\r\n Whitespace(a)example.com", True, "")
- , ("first\\last(a)example.com", False, "Unquoted string must be an atom")
- , ("Abc\\@def@example.com", False, "Was incorrectly given as a valid address in the original RFC3696")
- , ("Fred\\ Bloggs(a)example.com", False, "Was incorrectly given as a valid address in the original RFC3696")
- , ("Joe.\\\\Blow(a)example.com", False, "Was incorrectly given as a valid address in the original RFC3696")
- , ("\"test\\\r\n blah\"@example.com", False, "Folding white space can\'t appear within a quoted pair")
- , ("\"test\r\n blah\"@example.com", True, "This is a valid quoted string with folding white space")
- , ("{^c\\@**Dog^}@cartoon.com", False, "This is a throwaway example from Doug Lovell\'s article. Actually it\'s not a valid address.")
- , ("(foo)cal(bar)(a)(baz)iamcal.com(quux)", True, "A valid address containing comments")
- , ("cal(a)iamcal(woo).(yay)com", True, "A valid address containing comments")
- , ("cal(woo(yay)hoopla)(a)iamcal.com", True, "A valid address containing comments")
- , ("cal(foo\\@bar)@iamcal.com", True, "A valid address containing comments")
- , ("cal(foo\\)bar)(a)iamcal.com", True, "A valid address containing comments and an escaped parenthesis")
- , ("cal(foo(bar)(a)iamcal.com", False, "Unclosed parenthesis in comment")
- , ("cal(foo)bar)(a)iamcal.com", False, "Too many closing parentheses")
- , ("cal(foo\\)(a)iamcal.com", False, "Backslash at end of comment has nothing to escape")
- , ("first().last(a)example.com", True, "A valid address containing an empty comment")
- , ("first.(\r\n middle\r\n )last(a)example.com", True, "Comment with folding white space")
- , ("first(12345678901234567890123456789012345678901234567890)last@(1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890)example.com", False, "Too long with comments, not too long without")
- , ("first(Welcome to\r\n the (\"wonderful\" (!)) world\r\n of email)(a)example.com", True, "Silly example from my blog post")
- , ("pete(his account)(a)silly.test(his host)", True, "Canonical example from RFC5322")
- , ("c@(Chris\'s host.)public.example", True, "Canonical example from RFC5322")
- , ("jdoe@machine(comment). example", True, "Canonical example from RFC5322")
- , ("1234 @ local(blah) .machine .example", True, "Canonical example from RFC5322")
- , ("first(middle)last(a)example.com", False, "Can\'t have a comment or white space except at an element boundary")
- , ("first(abc.def).last(a)example.com", True, "Comment can contain a dot")
- , ("first(a\"bc.def).last(a)example.com", True, "Comment can contain double quote")
- , ("first.(\")middle.last(\")(a)example.com", True, "Comment can contain a quote")
- , ("first(abc(\"def\".ghi).mno)middle(abc(\"def\".ghi).mno).last@(abc(\"def\".ghi).mno)example(abc(\"def\".ghi).mno).(abc(\"def\".ghi).mno)com(abc(\"def\".ghi).mno)", False, "Can\'t have comments or white space except at an element boundary")
- , ("first(abc\\(def)(a)example.com", True, "Comment can contain quoted-pair")
- , ("first.last@x(1234567890123456789012345678901234567890123456789012345678901234567890).com", True, "Label is longer than 63 octets, but not with comment removed")
- , ("a(a(b(c)d(e(f))g)h(i)j)(a)example.com", True, "")
- , ("a(a(b(c)d(e(f))g)(h(i)j)(a)example.com", False, "Braces are not properly matched")
- , ("name.lastname(a)domain.com", True, "")
- , (".@", False, "")
- , ("@bar.com", False, "")
- , ("@@bar.com", False, "")
- , ("a(a)bar.com", True, "")
- , ("aaa.com", False, "")
- , ("aaa@.com", False, "")
- , ("aaa@.123", False, "")
- , ("aaa(a)[123.123.123.123]", True, "")
- , ("aaa(a)[123.123.123.123]a", False, "extra data outside ip")
- , ("a(a)bar.com.", True, "")
- , ("a-b(a)bar.com", True, "")
- , ("+(a)b.c", True, "TLDs can be any length")
- , ("+(a)b.com", True, "")
- , ("-@..com", False, "")
- , ("-@a..com", False, "")
- , ("a(a)b.co-foo.uk", True, "")
- , ("\"hello my name is\"@stutter.com", True, "")
- , ("\"Test \\\"Fail\\\" Ing\"@example.com", True, "")
- , ("valid(a)special.museum", True, "")
- , ("shaitan(a)my-domain.thisisminekthx", True, "Disagree with Paul Gregg here")
- , ("test@...........com", False, "......")
- , ("\"Joe\\\\Blow\"@example.com", True, "")
- , ("Invalid \\\n Folding \\\n Whitespace(a)example.com", False, "This isn\'t FWS so Dominic Sayers says it\'s invalid")
- , ("HM2Kinsists@(that comments are allowed)this.is.ok", True, "")
- , ("user%uucp!path(a)somehost.edu", True, "")
- , ("\"first(last)\"@example.com", True, "")
- , (" \r\n (\r\n x \r\n ) \r\n first\r\n ( \r\n x\r\n ) \r\n .\r\n ( \r\n x) \r\n last \r\n ( x \r\n ) \r\n @example.com", True, "")
- , ("test.\r\n \r\n obs(a)syntax.com", True, "obs-fws allows multiple lines")
- , ("test. \r\n \r\n obs(a)syntax.com", True, "obs-fws allows multiple lines (test 2: space before break)")
- , ("test.\r\n\r\n obs(a)syntax.com", False, "obs-fws must have at least one WSP per line")
- , ("\"null \\\0\"@char.com", True, "can have escaped null character")
- , ("\"null \0\"@char.com", False, "cannot have unescaped null character")
+ let domain249 = BS.intercalate "." (take 25 (repeat (BS.replicate 9 'x'))) in
+ [ valid "first.last(a)example.com"
+ , valid "first.last(a)example.com." `why` "Dot allowed on end of domain"
+ , invalid "local(a)exam_ple.com" `why` "Underscore not permitted in domain"
+ , valid "1234567890123456789012345678901234567890123456789012345678901234(a)example.com"
+ , valid "\"first last\"@example.com" `why` "Contains quoted spaces"
+ , valid "\"first\\\"last\"@example.com" `why` "Contains quoted escaped quote"
+ , invalid "first\\@last@example.com" `why` "Escaping can only happen within a quoted string"
+ , valid "\"first@last\"@example.com" `why` "Contains quoted at-sign"
+ , valid "\"first\\\\last\"@example.com" `why` "Contains quoted escaped backslash"
+ , valid ("1234@" <> domain249)
+ `why` "Maximum length is 254, this is 254 exactly"
+ , valid ("1234@" <> domain249 <> ".")
+ `why` "Trailing dot doesn't increase length"
+ , invalid ("12345@" <> domain249)
+ `why` "Maximum length is 254, this is 255"
+ `errorShouldContain` "too long"
+ , valid "first.last(a)[12.34.56.78]" `why` "IP address"
+ , valid "first.last@[IPv6:::12.34.56.78]" `why` "IPv6 address"
+ , valid "first.last@[IPv6:1111:2222:3333::4444:12.34.56.78]"
+ , valid "first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.56.78]"
+ , valid "first.last@[IPv6:::1111:2222:3333:4444:5555:6666]"
+ , valid "first.last@[IPv6:1111:2222:3333::4444:5555:6666]"
+ , valid "first.last@[IPv6:1111:2222:3333:4444:5555:6666::]"
+ , valid "first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]"
+ , valid "first.last@x23456789012345678901234567890123456789012345678901234567890123.example.com"
+ , valid "first.last(a)1xample.com"
+ , valid "first.last(a)123.example.com"
+ , invalid "first.last" `why` "no at sign" `errorShouldContain` "at sign"
+ , invalid ".first.last(a)example.com" `why` "Local part starts with a dot"
+ , invalid "first.last.(a)example.com" `why` "Local part ends with a dot"
+ , invalid "first..last(a)example.com" `why` "Local part has consecutive dots"
+ , invalid "\"first\"last\"@example.com" `why` "Local part contains unescaped excluded characters"
+ , valid "\"first\\last\"@example.com" `why` "Any character can be escaped in a quoted string"
+ , invalid "\"\"\"@example.com" `why` "Local part contains unescaped excluded characters"
+ , invalid "\"\\\"@example.com" `why` "Local part cannot end with a backslash"
+ , invalid "first\\\\@last@example.com" `why` "Local part contains unescaped excluded characters"
+ , invalid "first.last@" `why` "No domain"
+ , valid "\"Abc\\@def\"@example.com"
+ , valid "\"Fred\\ Bloggs\"@example.com"
+ , valid "\"Joe.\\\\Blow\"@example.com"
+ , valid "\"Abc@def\"@example.com"
+ , valid "\"Fred Bloggs\"@example.com"
+ , valid "user+mailbox(a)example.com"
+ , valid "customer/department=shipping(a)example.com"
+ , valid "$A12345(a)example.com"
+ , valid "!def!xyz%abc(a)example.com"
+ , valid "_somename(a)example.com"
+ , valid "dclo(a)us.ibm.com"
+ , invalid "abc\\@def@example.com" `why` "This example from RFC3696 was corrected in an erratum"
+ , invalid "abc\\\\(a)example.com" `why` "This example from RFC3696 was corrected in an erratum"
+ , valid "peter.piper(a)example.com"
+ , invalid "Doug\\ \\\"Ace\\\"\\ Lovell(a)example.com" `why` "Escaping can only happen in a quoted string"
+ , valid "\"Doug \\\"Ace\\\" L.\"@example.com"
+ , invalid "abc@def@example.com" `why` "Doug Lovell says this should fail"
+ , invalid "abc\\\\@def@example.com" `why` "Doug Lovell says this should fail"
+ , invalid "abc\\(a)example.com" `why` "Doug Lovell says this should fail"
+ , invalid "@example.com" `why` "no local part"
+ , invalid "doug@" `why` "no domain part"
+ , invalid "\"qu(a)example.com" `why` "Doug Lovell says this should fail"
+ , invalid "ote\"@example.com" `why` "Doug Lovell says this should fail"
+ , invalid ".dot(a)example.com" `why` "Doug Lovell says this should fail"
+ , invalid "dot.(a)example.com" `why` "Doug Lovell says this should fail"
+ , invalid "two..dot(a)example.com" `why` "Doug Lovell says this should fail"
+ , invalid "\"Doug \"Ace\" L.\"@example.com" `why` "Doug Lovell says this should fail"
+ , invalid "Doug\\ \\\"Ace\\\"\\ L\\.(a)example.com" `why` "Doug Lovell says this should fail"
+ , invalid "hello world(a)example.com" `why` "Doug Lovell says this should fail"
+ , valid "gatsby(a)f.sc.ot.t.f.i.tzg.era.l.d."
+ , valid "test(a)example.com"
+ , valid "TEST(a)example.com"
+ , valid "1234567890(a)example.com"
+ , valid "test+test(a)example.com"
+ , valid "test-test(a)example.com"
+ , valid "t*est(a)example.com"
+ , valid "+1~1+(a)example.com"
+ , valid "{_test_}(a)example.com"
+ , valid "\"[[ test ]]\"@example.com"
+ , valid "test.test(a)example.com"
+ , valid "\"test.test\"@example.com"
+ , valid "test.\"test\"@example.com" `why` "Obsolete form, but documented in RFC2822"
+ , valid "\"test@test\"@example.com"
+ , valid "test(a)123.123.123.x123"
+ , valid "test(a)[123.123.123.123]"
+ , valid "test(a)example.example.com"
+ , valid "test(a)example.example.example.com"
+ , invalid "test.example.com"
+ , invalid "test.(a)example.com"
+ , invalid "test..test(a)example.com"
+ , invalid ".test(a)example.com"
+ , invalid "test@test@example.com"
+ , invalid "test@@example.com"
+ , invalid "-- test --(a)example.com" `why` "No spaces allowed in local part"
+ , invalid "[test](a)example.com" `why` "Square brackets only allowed within quotes"
+ , valid "\"test\\test\"@example.com" `why` "Any character can be escaped in a quoted string"
+ , invalid "\"test\"test\"@example.com" `why` "Quotes cannot be nested"
+ , invalid "()[]\\;:,><@example.com" `why` "Disallowed Characters"
+ , invalid "test@." `why` "Dave Child says so"
+ , valid "test@example."
+ , invalid "test@.org" `why` "Dave Child says so"
+ , invalid "test(a)[123.123.123.123" `why` "Dave Child says so"
+ , invalid "test(a)123.123.123.123]" `why` "Dave Child says so"
+ , invalid "NotAnEmail" `why` "Phil Haack says so"
+ , invalid "@NotAnEmail" `why` "Phil Haack says so"
+ , valid "\"test\\\\blah\"@example.com"
+ , valid "\"test\\blah\"@example.com" `why` "Any character can be escaped in a quoted string"
+ , valid "\"test\\\rblah\"@example.com" `why` "Quoted string specifically excludes carriage returns unless escaped"
+ , invalid "\"test\rblah\"@example.com" `why` "Quoted string specifically excludes carriage returns"
+ , valid "\"test\\\"blah\"@example.com"
+ , invalid "\"test\"blah\"@example.com" `why` "Phil Haack says so"
+ , valid "customer/department(a)example.com"
+ , valid "_Yosemite.Sam(a)example.com"
+ , valid "~(a)example.com"
+ , invalid ".wooly(a)example.com" `why` "Phil Haack says so"
+ , invalid "wo..oly(a)example.com" `why` "Phil Haack says so"
+ , invalid "pootietang.(a)example.com" `why` "Phil Haack says so"
+ , invalid ".(a)example.com" `why` "Phil Haack says so"
+ , valid "\"Austin@Powers\"@example.com"
+ , valid "Ima.Fool(a)example.com"
+ , valid "\"Ima.Fool\"@example.com"
+ , valid "\"Ima Fool\"@example.com"
+ , invalid "Ima Fool(a)example.com" `why` "Phil Haack says so"
+ , invalid "phil.h\\@\\@ck@haacked.com" `why` "Escaping can only happen in a quoted string"
+ , valid "\"first\".\"last\"@example.com"
+ , valid "\"first\".middle.\"last\"@example.com"
+ , invalid "\"first\\\\\"last\"@example.com" `why` "Contains an unescaped quote"
+ , valid "\"first\".last(a)example.com" `why` "obs-local-part form as described in RFC 2822"
+ , valid "first.\"last\"@example.com" `why` "obs-local-part form as described in RFC 2822"
+ , valid "\"first\".\"middle\".\"last\"@example.com" `why` "obs-local-part form as described in RFC 2822"
+ , valid "\"first.middle\".\"last\"@example.com" `why` "obs-local-part form as described in RFC 2822"
+ , valid "\"first.middle.last\"@example.com" `why` "obs-local-part form as described in RFC 2822"
+ , valid "\"first..last\"@example.com" `why` "obs-local-part form as described in RFC 2822"
+ , invalid "foo(a)[\\1.2.3.4]" `why` "RFC 5321 specifies the syntax for address-literal and does not allow escaping"
+ , valid "\"first\\\\\\\"last\"@example.com"
+ , valid "first.\"mid\\dle\".\"last\"@example.com" `why` "Backslash can escape anything but must escape something"
+ , valid "Test.\r\n Folding.\r\n Whitespace(a)example.com"
+ , invalid "first\\last(a)example.com" `why` "Unquoted string must be an atom"
+ , invalid "Abc\\@def@example.com" `why` "Was incorrectly given as a valid address in the original RFC3696"
+ , invalid "Fred\\ Bloggs(a)example.com" `why` "Was incorrectly given as a valid address in the original RFC3696"
+ , invalid "Joe.\\\\Blow(a)example.com" `why` "Was incorrectly given as a valid address in the original RFC3696"
+ , invalid "\"test\\\r\n blah\"@example.com" `why` "Folding white space can\'t appear within a quoted pair"
+ , valid "\"test\r\n blah\"@example.com" `why` "This is a valid quoted string with folding white space"
+ , invalid "{^c\\@**Dog^}@cartoon.com" `why` "This is a throwaway example from Doug Lovell\'s article. Actually it\'s not a valid address."
+ , valid "(foo)cal(bar)(a)(baz)iamcal.com(quux)" `why` "A valid address containing comments"
+ , valid "cal(a)iamcal(woo).(yay)com" `why` "A valid address containing comments"
+ , valid "cal(woo(yay)hoopla)(a)iamcal.com" `why` "A valid address containing comments"
+ , valid "cal(foo\\@bar)@iamcal.com" `why` "A valid address containing comments"
+ , valid "cal(foo\\)bar)(a)iamcal.com" `why` "A valid address containing comments and an escaped parenthesis"
+ , invalid "cal(foo(bar)(a)iamcal.com" `why` "Unclosed parenthesis in comment"
+ , invalid "cal(foo)bar)(a)iamcal.com" `why` "Too many closing parentheses"
+ , invalid "cal(foo\\)(a)iamcal.com" `why` "Backslash at end of comment has nothing to escape"
+ , valid "first().last(a)example.com" `why` "A valid address containing an empty comment"
+ , valid "first.(\r\n middle\r\n )last(a)example.com" `why` "Comment with folding white space"
+ , invalid "first(12345678901234567890123456789012345678901234567890)last@(1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890)example.com" `why` "Too long with comments, not too long without"
+ , valid "first(Welcome to\r\n the (\"wonderful\" (!)) world\r\n of email)(a)example.com" `why` "Silly example from my blog post"
+ , valid "pete(his account)(a)silly.test(his host)" `why` "Canonical example from RFC5322"
+ , valid "c@(Chris\'s host.)public.example" `why` "Canonical example from RFC5322"
+ , valid "jdoe@machine(comment). example" `why` "Canonical example from RFC5322"
+ , valid "1234 @ local(blah) .machine .example" `why` "Canonical example from RFC5322"
+ , invalid "first(middle)last(a)example.com" `why` "Can\'t have a comment or white space except at an element boundary"
+ , valid "first(abc.def).last(a)example.com" `why` "Comment can contain a dot"
+ , valid "first(a\"bc.def).last(a)example.com" `why` "Comment can contain double quote"
+ , valid "first.(\")middle.last(\")(a)example.com" `why` "Comment can contain a quote"
+ , invalid "first(abc(\"def\".ghi).mno)middle(abc(\"def\".ghi).mno).last@(abc(\"def\".ghi).mno)example(abc(\"def\".ghi).mno).(abc(\"def\".ghi).mno)com(abc(\"def\".ghi).mno)" `why` "Can\'t have comments or white space except at an element boundary"
+ , valid "first(abc\\(def)(a)example.com" `why` "Comment can contain quoted-pair"
+ , valid "first.last@x(1234567890123456789012345678901234567890123456789012345678901234567890).com" `why` "Label is longer than 63 octets, but not with comment removed"
+ , valid "a(a(b(c)d(e(f))g)h(i)j)(a)example.com"
+ , invalid "a(a(b(c)d(e(f))g)(h(i)j)(a)example.com" `why` "Braces are not properly matched"
+ , valid "name.lastname(a)domain.com"
+ , invalid ".@"
+ , invalid "@bar.com"
+ , invalid "@@bar.com"
+ , valid "a(a)bar.com"
+ , invalid "aaa.com"
+ , invalid "aaa@.com"
+ , invalid "aaa@.123"
+ , valid "aaa(a)[123.123.123.123]"
+ , invalid "aaa(a)[123.123.123.123]a" `why` "extra data outside ip"
+ , valid "a(a)bar.com."
+ , valid "a-b(a)bar.com"
+ , valid "+(a)b.c" `why` "TLDs can be any length"
+ , valid "+(a)b.com"
+ , invalid "-@..com"
+ , invalid "-@a..com"
+ , valid "a(a)b.co-foo.uk"
+ , valid "\"hello my name is\"@stutter.com"
+ , valid "\"Test \\\"Fail\\\" Ing\"@example.com"
+ , valid "valid(a)special.museum"
+ , valid "shaitan(a)my-domain.thisisminekthx" `why` "Disagree with Paul Gregg here"
+ , invalid "test@...........com" `why` "......"
+ , valid "\"Joe\\\\Blow\"@example.com"
+ , invalid "Invalid \\\n Folding \\\n Whitespace(a)example.com" `why` "This isn\'t FWS so Dominic Sayers says it\'s invalid"
+ , valid "HM2Kinsists@(that comments are allowed)this.is.ok"
+ , valid "user%uucp!path(a)somehost.edu"
+ , valid "\"first(last)\"@example.com"
+ , valid " \r\n (\r\n x \r\n ) \r\n first\r\n ( \r\n x\r\n ) \r\n .\r\n ( \r\n x) \r\n last \r\n ( x \r\n ) \r\n @example.com"
+ , valid "test.\r\n \r\n obs(a)syntax.com" `why` "obs-fws allows multiple lines"
+ , valid "test. \r\n \r\n obs(a)syntax.com" `why` "obs-fws allows multiple lines (test 2: space before break)"
+ , invalid "test.\r\n\r\n obs(a)syntax.com" `why` "obs-fws must have at least one WSP per line"
+ , valid "\"null \\\0\"@char.com" `why` "can have escaped null character"
+ , invalid "\"null \0\"@char.com" `why` "cannot have unescaped null character"
-- items below here are invalid according to other RFCs (or opinions)
- --, ("\"\"@example.com", False, "Local part is effectively empty")
- --, ("foobar(a)192.168.0.1", False, "ip need to be []")
- --, ("first.last(a)[.12.34.56.78]", False, "Only char that can precede IPv4 address is \':\'")
- --, ("first.last(a)[12.34.56.789]", False, "Can\'t be interpreted as IPv4 so IPv6 tag is missing")
- --, ("first.last@[::12.34.56.78]", False, "IPv6 tag is missing")
- --, ("first.last@[IPv5:::12.34.56.78]", False, "IPv6 tag is wrong")
- --, ("first.last@[IPv6:1111:2222:3333::4444:5555:12.34.56.78]", False, "Too many IPv6 groups (4 max)")
- --, ("first.last@[IPv6:1111:2222:3333:4444:5555:12.34.56.78]", False, "Not enough IPv6 groups")
- --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:12.34.56.78]", False, "Too many IPv6 groups (6 max)")
- --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777]", False, "Not enough IPv6 groups")
- --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]", False, "Too many IPv6 groups (8 max)")
- --, ("first.last@[IPv6:1111:2222::3333::4444:5555:6666]", False, "Too many \'::\' (can be none or one)")
- --, ("first.last@[IPv6:1111:2222:3333::4444:5555:6666:7777]", False, "Too many IPv6 groups (6 max)")
- --, ("first.last@[IPv6:1111:2222:333x::4444:5555]", False, "x is not valid in an IPv6 address")
- --, ("first.last@[IPv6:1111:2222:33333::4444:5555]", False, "33333 is not a valid group in an IPv6 address")
- --, ("first.last(a)example.123", False, "TLD can\'t be all digits")
- --, ("aaa(a)[123.123.123.333]", False, "not a valid IP")
- --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.567.89]", False, "IPv4 part contains an invalid octet")
- --, ("a@b", False, "")
- --, ("a@bar", False, "")
- , ("invalid(a)special.museum-", False, "")
- , ("a(a)-b.com", False, "")
- , ("a(a)b-.com", False, "")
- --, ("\"foo\"(yay)(a)(hoopla)[1.2.3.4]", False, "Address literal can\'t be commented (RFC5321)")
- --, ("first.\"\".last(a)example.com", False, "Contains a zero-length element")
- --, ("test@example", False, "Dave Child says so")
- --, ("12345678901234567890123456789012345678901234567890123456789012345(a)example.com", False, "Local part more than 64 characters")
- , ("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456", False, "Domain exceeds 255 chars")
- , ("test@123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012.com", False, "255 characters is maximum length for domain. This is 256.")
- --, ("123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.1234.example.com", False, "Entire address is longer than 256 characters")
- --, ("test(a)123.123.123.123", False, "Top Level Domain won\'t be all-numeric (see RFC3696 Section 2). I disagree with Dave Child on this one.")
- , ("first.last@x234567890123456789012345678901234567890123456789012345678901234.example.com", False, "Label can\'t be longer than 63 octets")
- --, ("first.last@com", False, "Mail host must be second- or lower level")
- , ("first.last(a)-xample.com", False, "Label can\'t begin with a hyphen")
- , ("first.last(a)exampl-.com", False, "Label can\'t end with a hyphen")
+ --, invalid "\"\"@example.com" `why` "Local part is effectively empty"
+ --, invalid "foobar(a)192.168.0.1" `why` "ip need to be []"
+ --, invalid "first.last(a)[.12.34.56.78]" `why` "Only char that can precede IPv4 address is \':\'"
+ --, invalid "first.last(a)[12.34.56.789]" `why` "Can\'t be interpreted as IPv4 so IPv6 tag is missing"
+ --, invalid "first.last@[::12.34.56.78]" `why` "IPv6 tag is missing"
+ --, invalid "first.last@[IPv5:::12.34.56.78]" `why` "IPv6 tag is wrong"
+ --, invalid "first.last@[IPv6:1111:2222:3333::4444:5555:12.34.56.78]" `why` "Too many IPv6 groups (4 max)"
+ --, invalid "first.last@[IPv6:1111:2222:3333:4444:5555:12.34.56.78]" `why` "Not enough IPv6 groups"
+ --, invalid "first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:12.34.56.78]" `why` "Too many IPv6 groups (6 max)"
+ --, invalid "first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777]" `why` "Not enough IPv6 groups"
+ --, invalid "first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]" `why` "Too many IPv6 groups (8 max)"
+ --, invalid "first.last@[IPv6:1111:2222::3333::4444:5555:6666]" `why` "Too many \'::\' (can be none or one)"
+ --, invalid "first.last@[IPv6:1111:2222:3333::4444:5555:6666:7777]" `why` "Too many IPv6 groups (6 max)"
+ --, invalid "first.last@[IPv6:1111:2222:333x::4444:5555]" `why` "x is not valid in an IPv6 address"
+ --, invalid "first.last@[IPv6:1111:2222:33333::4444:5555]" `why` "33333 is not a valid group in an IPv6 address"
+ --, invalid "first.last(a)example.123" `why` "TLD can\'t be all digits"
+ --, invalid "aaa(a)[123.123.123.333]" `why` "not a valid IP"
+ --, invalid "first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.567.89]" `why` "IPv4 part contains an invalid octet"
+ , valid "a@b"
+ , valid "a@bar"
+ , invalid "invalid(a)special.museum-" `why` "domain can't end with hyphen"
+ , invalid "a(a)-b.com" `why` "domain can't start with hyphen"
+ , invalid "a(a)b-.com" `why` "domain label can't end with hyphen"
+ --, invalid "\"foo\"(yay)(a)(hoopla)[1.2.3.4]" `why` "Address literal can\'t be commented (RFC5321)"
+ --, invalid "first.\"\".last(a)example.com" `why` "Contains a zero-length element"
+ --, invalid "test@example" `why` "Dave Child says so"
+ , invalid (BS.replicate 65 'x' <> "@x") `why` "local-part longer than 64 octets" `errorShouldContain` "too long"
+ , invalid "x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456" `why` "Domain exceeds 255 chars"
+ , invalid "test@123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012.com" `why` "255 characters is maximum length for domain. This is 256."
+ , invalid "123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.1234.example.com" `why` "Entire address is longer than 254 characters (this is 257)"
+ , invalid "123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.123.example.com" `why` "Entire address is longer than 254 characters (this is 256)"
+ , invalid "123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12.example.com" `why` "Entire address is longer than 254 characters (this is 255)"
+ , valid "123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.1.example.com" `why` "Entire address is 254 characters"
+ --, invalid "test(a)123.123.123.123" `why` "Top Level Domain won\'t be all-numeric (see RFC3696 Section 2). I disagree with Dave Child on this one."
+ , invalid "first.last@x234567890123456789012345678901234567890123456789012345678901234.example.com" `why` "Label can\'t be longer than 63 octets"
+ --, invalid "first.last@com" `why` "Mail host must be second- or lower level"
+ , invalid "first.last(a)e.-xample.com" `why` "Label can\'t begin with a hyphen"
+ , invalid "first.last(a)exampl-.e.com" `why` "Label can\'t end with a hyphen"
]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/email-validate-2.2.1.1/tests/doctests.hs new/email-validate-2.3/tests/doctests.hs
--- old/email-validate-2.2.1.1/tests/doctests.hs 1970-01-01 01:00:00.000000000 +0100
+++ new/email-validate-2.3/tests/doctests.hs 2017-06-26 08:45:39.000000000 +0200
@@ -0,0 +1,7 @@
+import Test.DocTest
+
+main = doctest
+ [ "-isrc"
+ , "src/Text/Email/QuasiQuotation.hs"
+ , "src/Text/Email/Validate.hs"
+ ]
1
0