[Snowdrift-dev] [PATCH] Port Snowdrift tests from HSpec to Tasty

2017-07-08 Thread fr33domlover
From: fr33domlover 

---
 website/Snowdrift.cabal   | 12 +++-
 website/test/AlertsSpec.hs|  6 +++---
 website/test/AuthSiteSpec.hs  |  8 
 website/test/DiscourseSpec.hs | 35 ---
 website/test/HandlerSpec.hs   |  6 +++---
 website/test/SampleSpec.hs|  6 +++---
 website/test/Spec.hs  |  1 -
 website/test/StripeMock.hs|  2 +-
 website/test/Tasty.hs |  1 +
 website/test/TestImport.hs|  4 ++--
 10 files changed, 40 insertions(+), 41 deletions(-)
 delete mode 100644 website/test/Spec.hs
 create mode 100644 website/test/Tasty.hs

diff --git a/website/Snowdrift.cabal b/website/Snowdrift.cabal
index 1f1ffc5..c7be912 100644
--- a/website/Snowdrift.cabal
+++ b/website/Snowdrift.cabal
@@ -152,7 +152,7 @@ executable Snowdrift
 -- test-suite test {{{1
 test-suite test
 type:   exitcode-stdio-1.0
-main-is:Spec.hs
+main-is:Tasty.hs
 hs-source-dirs: test
 ghc-options:-Wall
 
@@ -178,24 +178,26 @@ test-suite test
 -- build-depends {{{2
 build-depends:
 Snowdrift
--- For htmlHasLink (should move upstream)
-, HUnit >= 1.3.1.1
 , base
 , bytestring
 , classy-prelude
 , classy-prelude-yesod
 , cryptonite
-, hspec >= 2.0.0
 , http-types
 , memory
 , persistent
 , persistent-postgresql
 , postgresql-simple
-, QuickCheck
 , quickcheck-text
 , shakespeare
 , stripe-core
 , stripe-haskell
+, tasty
+, tasty-discover
+-- For htmlHasLink (should move upstream)
+, tasty-hunit
+, tasty-hspec
+, tasty-quickcheck
 , text >= 1.2.2.1
 , wai-extra
 , yesod
diff --git a/website/test/AlertsSpec.hs b/website/test/AlertsSpec.hs
index 62235e8..cf0d9c5 100644
--- a/website/test/AlertsSpec.hs
+++ b/website/test/AlertsSpec.hs
@@ -1,4 +1,4 @@
-module AlertsSpec (spec) where
+module AlertsSpec (spec_alerts) where
 
 import TestImport
 import Alerts
@@ -20,8 +20,8 @@ alertSite = LiteApp go
 withAlertSite :: SpecWith (TestApp LiteApp) -> Spec
 withAlertSite = before $ pure (alertSite, id)
 
-spec :: Spec
-spec = withAlertSite $
+spec_alerts :: Spec
+spec_alerts = withAlertSite $
 it "adds an alert" $ do
 get getR
 htmlCount ".alert" 0
diff --git a/website/test/AuthSiteSpec.hs b/website/test/AuthSiteSpec.hs
index e962fce..a251a9e 100644
--- a/website/test/AuthSiteSpec.hs
+++ b/website/test/AuthSiteSpec.hs
@@ -4,13 +4,13 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE ViewPatterns #-}
 {-# OPTIONS_GHC -fno-warn-unused-binds #-}
-module AuthSiteSpec (spec) where
+module AuthSiteSpec (spec_authSite) where
 
 import TestImport hiding (Handler)
 import Database.Persist.Sql hiding (get)
 import Database.Persist.Postgresql (pgConnStr)
 import Network.Wai.Test (SResponse(..))
-import Test.HUnit (assertBool)
+import Test.Tasty.HUnit (assertBool)
 import Yesod hiding (get)
 import Yesod.Default.Config2 (ignoreEnv, loadYamlSettings)
 import qualified Data.Text as T
@@ -171,8 +171,8 @@ withBob = beforeWith makeBob
 
 -- ** The actual tests!
 
-spec :: Spec
-spec = mainSpecs >> authRouteSpec
+spec_authSite :: Spec
+spec_authSite = mainSpecs >> authRouteSpec
 
 -- | Having this defined separately is clumsy. It should be moved back into
 -- the right spot. The problem is that it needs a different value of
diff --git a/website/test/DiscourseSpec.hs b/website/test/DiscourseSpec.hs
index f00c084..e4cc0b0 100644
--- a/website/test/DiscourseSpec.hs
+++ b/website/test/DiscourseSpec.hs
@@ -13,30 +13,27 @@ import Crypto.MAC.HMAC (HMAC, hmac)
 import Data.ByteArray (ByteArray, ByteArrayAccess)
 import Data.ByteArray.Encoding (Base(Base16, Base64URLUnpadded), convertToBase)
 import Data.Text.Arbitrary ()
-import Test.Hspec.QuickCheck (prop)
-import Test.QuickCheck (Arbitrary, arbitrary, choose, oneof, vectorOf, 
NonEmptyList(..))
+import Test.Tasty.QuickCheck (Arbitrary, arbitrary, choose, oneof, vectorOf, 
NonEmptyList(..))
 
 import qualified Data.ByteString.Char8 as Char8
 
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
 
-spec :: Spec
-spec = do
-prop "validateSig" $ \(NonEmpty secret) (NonEmpty payload) -> do
-let secret' = pack secret
-payload' = pack payload
-
-validateSig (DiscourseSecret secret') payload'
-(base16 (hmac secret' payload' :: HMAC SHA256))
-
-prop "parsePayload" $ \(Nonce nonce) (Url url) -> do
-let payload = "nonce=" <> nonce <> "&return_sso_url=" <> encodeUtf8 url
-parsePayload (base64 payload)
-`shouldBe`
-Right DiscoursePayload
-{ dpNonce = nonce
-, dpUrl   = url
-}
+prop_validateSig (NonEmpty secret) (NonEmpty payload) = do
+let secret' = pack secret
+payload' = pack payload
+
+validateSi

Re: [Snowdrift-dev] [PATCH] Port Snowdrift tests from HSpec to Tasty

2017-07-08 Thread Aaron Wolf
On 07/08/2017 01:41 AM, fr33domlo...@riseup.net wrote:
> From: fr33domlover 
> 
> ---
>  website/Snowdrift.cabal   | 12 +++-
>  website/test/AlertsSpec.hs|  6 +++---
>  website/test/AuthSiteSpec.hs  |  8 
>  website/test/DiscourseSpec.hs | 35 ---
>  website/test/HandlerSpec.hs   |  6 +++---
>  website/test/SampleSpec.hs|  6 +++---
>  website/test/Spec.hs  |  1 -
>  website/test/StripeMock.hs|  2 +-
>  website/test/Tasty.hs |  1 +
>  website/test/TestImport.hs|  4 ++--
>  10 files changed, 40 insertions(+), 41 deletions(-)
>  delete mode 100644 website/test/Spec.hs
>  create mode 100644 website/test/Tasty.hs
> 
> diff --git a/website/Snowdrift.cabal b/website/Snowdrift.cabal
> index 1f1ffc5..c7be912 100644
> --- a/website/Snowdrift.cabal
> +++ b/website/Snowdrift.cabal
> @@ -152,7 +152,7 @@ executable Snowdrift
>  -- test-suite test {{{1
>  test-suite test
>  type:   exitcode-stdio-1.0
> -main-is:Spec.hs
> +main-is:Tasty.hs
>  hs-source-dirs: test
>  ghc-options:-Wall
>  
> @@ -178,24 +178,26 @@ test-suite test
>  -- build-depends {{{2
>  build-depends:
>  Snowdrift
> --- For htmlHasLink (should move upstream)
> -, HUnit >= 1.3.1.1
>  , base
>  , bytestring
>  , classy-prelude
>  , classy-prelude-yesod
>  , cryptonite
> -, hspec >= 2.0.0
>  , http-types
>  , memory
>  , persistent
>  , persistent-postgresql
>  , postgresql-simple
> -, QuickCheck
>  , quickcheck-text
>  , shakespeare
>  , stripe-core
>  , stripe-haskell
> +, tasty
> +, tasty-discover
> +-- For htmlHasLink (should move upstream)
> +, tasty-hunit
> +, tasty-hspec
> +, tasty-quickcheck
>  , text >= 1.2.2.1
>  , wai-extra
>  , yesod
> diff --git a/website/test/AlertsSpec.hs b/website/test/AlertsSpec.hs
> index 62235e8..cf0d9c5 100644
> --- a/website/test/AlertsSpec.hs
> +++ b/website/test/AlertsSpec.hs
> @@ -1,4 +1,4 @@
> -module AlertsSpec (spec) where
> +module AlertsSpec (spec_alerts) where
>  
>  import TestImport
>  import Alerts
> @@ -20,8 +20,8 @@ alertSite = LiteApp go
>  withAlertSite :: SpecWith (TestApp LiteApp) -> Spec
>  withAlertSite = before $ pure (alertSite, id)
>  
> -spec :: Spec
> -spec = withAlertSite $
> +spec_alerts :: Spec
> +spec_alerts = withAlertSite $
>  it "adds an alert" $ do
>  get getR
>  htmlCount ".alert" 0
> diff --git a/website/test/AuthSiteSpec.hs b/website/test/AuthSiteSpec.hs
> index e962fce..a251a9e 100644
> --- a/website/test/AuthSiteSpec.hs
> +++ b/website/test/AuthSiteSpec.hs
> @@ -4,13 +4,13 @@
>  {-# LANGUAGE ScopedTypeVariables #-}
>  {-# LANGUAGE ViewPatterns #-}
>  {-# OPTIONS_GHC -fno-warn-unused-binds #-}
> -module AuthSiteSpec (spec) where
> +module AuthSiteSpec (spec_authSite) where
>  
>  import TestImport hiding (Handler)
>  import Database.Persist.Sql hiding (get)
>  import Database.Persist.Postgresql (pgConnStr)
>  import Network.Wai.Test (SResponse(..))
> -import Test.HUnit (assertBool)
> +import Test.Tasty.HUnit (assertBool)
>  import Yesod hiding (get)
>  import Yesod.Default.Config2 (ignoreEnv, loadYamlSettings)
>  import qualified Data.Text as T
> @@ -171,8 +171,8 @@ withBob = beforeWith makeBob
>  
>  -- ** The actual tests!
>  
> -spec :: Spec
> -spec = mainSpecs >> authRouteSpec
> +spec_authSite :: Spec
> +spec_authSite = mainSpecs >> authRouteSpec
>  
>  -- | Having this defined separately is clumsy. It should be moved back into
>  -- the right spot. The problem is that it needs a different value of
> diff --git a/website/test/DiscourseSpec.hs b/website/test/DiscourseSpec.hs
> index f00c084..e4cc0b0 100644
> --- a/website/test/DiscourseSpec.hs
> +++ b/website/test/DiscourseSpec.hs
> @@ -13,30 +13,27 @@ import Crypto.MAC.HMAC (HMAC, hmac)
>  import Data.ByteArray (ByteArray, ByteArrayAccess)
>  import Data.ByteArray.Encoding (Base(Base16, Base64URLUnpadded), 
> convertToBase)
>  import Data.Text.Arbitrary ()
> -import Test.Hspec.QuickCheck (prop)
> -import Test.QuickCheck (Arbitrary, arbitrary, choose, oneof, vectorOf, 
> NonEmptyList(..))
> +import Test.Tasty.QuickCheck (Arbitrary, arbitrary, choose, oneof, vectorOf, 
> NonEmptyList(..))
>  
>  import qualified Data.ByteString.Char8 as Char8
>  
>  {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
>  
> -spec :: Spec
> -spec = do
> -prop "validateSig" $ \(NonEmpty secret) (NonEmpty payload) -> do
> -let secret' = pack secret
> -payload' = pack payload
> -
> -validateSig (DiscourseSecret secret') payload'
> -(base16 (hmac secret' payload' :: HMAC SHA256))
> -
> -prop "parsePayload" $ \(Nonce nonce) (Url url) -> do
> -let payload = "nonce=" <> nonce <> "&return_sso_url=" <> encodeUtf8 

Re: [Snowdrift-dev] [PATCH] Port Snowdrift tests from HSpec to Tasty

2017-07-08 Thread Aaron Wolf
On 07/08/2017 05:58 AM, Aaron Wolf wrote:
> On 07/08/2017 01:41 AM, fr33domlo...@riseup.net wrote:
>> From: fr33domlover 
>>
>> ---
>>  website/Snowdrift.cabal   | 12 +++-
>>  website/test/AlertsSpec.hs|  6 +++---
>>  website/test/AuthSiteSpec.hs  |  8 
>>  website/test/DiscourseSpec.hs | 35 ---
>>  website/test/HandlerSpec.hs   |  6 +++---
>>  website/test/SampleSpec.hs|  6 +++---
>>  website/test/Spec.hs  |  1 -
>>  website/test/StripeMock.hs|  2 +-
>>  website/test/Tasty.hs |  1 +
>>  website/test/TestImport.hs|  4 ++--
>>  10 files changed, 40 insertions(+), 41 deletions(-)
>>  delete mode 100644 website/test/Spec.hs
>>  create mode 100644 website/test/Tasty.hs
>>
>> diff --git a/website/Snowdrift.cabal b/website/Snowdrift.cabal
>> index 1f1ffc5..c7be912 100644
>> --- a/website/Snowdrift.cabal
>> +++ b/website/Snowdrift.cabal
>> @@ -152,7 +152,7 @@ executable Snowdrift
>>  -- test-suite test {{{1
>>  test-suite test
>>  type:   exitcode-stdio-1.0
>> -main-is:Spec.hs
>> +main-is:Tasty.hs
>>  hs-source-dirs: test
>>  ghc-options:-Wall
>>  
>> @@ -178,24 +178,26 @@ test-suite test
>>  -- build-depends {{{2
>>  build-depends:
>>  Snowdrift
>> --- For htmlHasLink (should move upstream)
>> -, HUnit >= 1.3.1.1
>>  , base
>>  , bytestring
>>  , classy-prelude
>>  , classy-prelude-yesod
>>  , cryptonite
>> -, hspec >= 2.0.0
>>  , http-types
>>  , memory
>>  , persistent
>>  , persistent-postgresql
>>  , postgresql-simple
>> -, QuickCheck
>>  , quickcheck-text
>>  , shakespeare
>>  , stripe-core
>>  , stripe-haskell
>> +, tasty
>> +, tasty-discover
>> +-- For htmlHasLink (should move upstream)
>> +, tasty-hunit
>> +, tasty-hspec
>> +, tasty-quickcheck
>>  , text >= 1.2.2.1
>>  , wai-extra
>>  , yesod
>> diff --git a/website/test/AlertsSpec.hs b/website/test/AlertsSpec.hs
>> index 62235e8..cf0d9c5 100644
>> --- a/website/test/AlertsSpec.hs
>> +++ b/website/test/AlertsSpec.hs
>> @@ -1,4 +1,4 @@
>> -module AlertsSpec (spec) where
>> +module AlertsSpec (spec_alerts) where
>>  
>>  import TestImport
>>  import Alerts
>> @@ -20,8 +20,8 @@ alertSite = LiteApp go
>>  withAlertSite :: SpecWith (TestApp LiteApp) -> Spec
>>  withAlertSite = before $ pure (alertSite, id)
>>  
>> -spec :: Spec
>> -spec = withAlertSite $
>> +spec_alerts :: Spec
>> +spec_alerts = withAlertSite $
>>  it "adds an alert" $ do
>>  get getR
>>  htmlCount ".alert" 0
>> diff --git a/website/test/AuthSiteSpec.hs b/website/test/AuthSiteSpec.hs
>> index e962fce..a251a9e 100644
>> --- a/website/test/AuthSiteSpec.hs
>> +++ b/website/test/AuthSiteSpec.hs
>> @@ -4,13 +4,13 @@
>>  {-# LANGUAGE ScopedTypeVariables #-}
>>  {-# LANGUAGE ViewPatterns #-}
>>  {-# OPTIONS_GHC -fno-warn-unused-binds #-}
>> -module AuthSiteSpec (spec) where
>> +module AuthSiteSpec (spec_authSite) where
>>  
>>  import TestImport hiding (Handler)
>>  import Database.Persist.Sql hiding (get)
>>  import Database.Persist.Postgresql (pgConnStr)
>>  import Network.Wai.Test (SResponse(..))
>> -import Test.HUnit (assertBool)
>> +import Test.Tasty.HUnit (assertBool)
>>  import Yesod hiding (get)
>>  import Yesod.Default.Config2 (ignoreEnv, loadYamlSettings)
>>  import qualified Data.Text as T
>> @@ -171,8 +171,8 @@ withBob = beforeWith makeBob
>>  
>>  -- ** The actual tests!
>>  
>> -spec :: Spec
>> -spec = mainSpecs >> authRouteSpec
>> +spec_authSite :: Spec
>> +spec_authSite = mainSpecs >> authRouteSpec
>>  
>>  -- | Having this defined separately is clumsy. It should be moved back into
>>  -- the right spot. The problem is that it needs a different value of
>> diff --git a/website/test/DiscourseSpec.hs b/website/test/DiscourseSpec.hs
>> index f00c084..e4cc0b0 100644
>> --- a/website/test/DiscourseSpec.hs
>> +++ b/website/test/DiscourseSpec.hs
>> @@ -13,30 +13,27 @@ import Crypto.MAC.HMAC (HMAC, hmac)
>>  import Data.ByteArray (ByteArray, ByteArrayAccess)
>>  import Data.ByteArray.Encoding (Base(Base16, Base64URLUnpadded), 
>> convertToBase)
>>  import Data.Text.Arbitrary ()
>> -import Test.Hspec.QuickCheck (prop)
>> -import Test.QuickCheck (Arbitrary, arbitrary, choose, oneof, vectorOf, 
>> NonEmptyList(..))
>> +import Test.Tasty.QuickCheck (Arbitrary, arbitrary, choose, oneof, 
>> vectorOf, NonEmptyList(..))
>>  
>>  import qualified Data.ByteString.Char8 as Char8
>>  
>>  {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
>>  
>> -spec :: Spec
>> -spec = do
>> -prop "validateSig" $ \(NonEmpty secret) (NonEmpty payload) -> do
>> -let secret' = pack secret
>> -payload' = pack payload
>> -
>> -validateSig (DiscourseSecret secret') payload'
>> -(base16 (h

[Snowdrift-dev] [PATCH] crowdmatch: Use (SqlPersistT env) monad to allow combining queries

2017-07-08 Thread fr33domlover
From: fr33domlover 

Before this commit, crowdmatch actions run database queries separately
inside them like a black box. That means in practice many applications
of `runDB`, one per query, so a transaction per query. This is an
unnecessary waste, and doesn't gain much (or anything at all, as this
commit's changes my demonstrate).

So this commit adds `SqlPersistT` on top of the crowdmatch env monad, so
that the actual running of SQL queries is controlled from outside
crowdmatch itself, and allows a single `runDB` to handle a batch of
persistent actions.

Both Snowdrift and the crowdmatch test suite have been updated to make
use of this new capability, which also happens to make the code more
readable (e.g. much much less occurences of `runDB`).
---
 crowdmatch/app/CrowdmatchMain.hs   |   2 +-
 crowdmatch/crowdmatch.cabal|   4 +-
 crowdmatch/src/Crowdmatch.hs   | 102 
 crowdmatch/test/main.hs| 136 +
 website/src/Handler/Dashboard.hs   |   3 +-
 website/src/Handler/PaymentInfo.hs |   6 +-
 website/src/Handler/Pledge.hs  |  11 +--
 website/src/Handler/Project.hs |   4 +-
 8 files changed, 136 insertions(+), 132 deletions(-)

diff --git a/crowdmatch/app/CrowdmatchMain.hs b/crowdmatch/app/CrowdmatchMain.hs
index 0a48c4a..bb12530 100644
--- a/crowdmatch/app/CrowdmatchMain.hs
+++ b/crowdmatch/app/CrowdmatchMain.hs
@@ -7,4 +7,4 @@ import RunPersist
 -- NB! The string passed to runPersistKeter must match the APPNAME used in
 -- keter.sh to deploy the app. Must fix.
 main :: IO ()
-main = crowdmatch (runPersistKeter "SnowdriftReboot")
+main = runPersistKeter "SnowdriftReboot" crowdmatch
diff --git a/crowdmatch/crowdmatch.cabal b/crowdmatch/crowdmatch.cabal
index bf93327..d9f58c5 100644
--- a/crowdmatch/crowdmatch.cabal
+++ b/crowdmatch/crowdmatch.cabal
@@ -1,5 +1,5 @@
 name: crowdmatch
-version: 0.1.0.0
+version: 0.2.0.0
 synopsis: Crowdmatch mechanism for Snowdrift.coop
 description:
 Provides an interface for managing pledges and donations. Includes
@@ -10,7 +10,7 @@ license: AGPL-3
 license-file: LICENSE
 author: Bryan Richter
 maintainer: disc...@lists.snowdrift.coop
-copyright: Bryan Richter and Snowdrift.coop, 2016
+copyright: Bryan Richter and Snowdrift.coop, 2016, 2017
 category: Database
 build-type: Simple
 -- extra-source-files:
diff --git a/crowdmatch/src/Crowdmatch.hs b/crowdmatch/src/Crowdmatch.hs
index b7b8a87..6894afd 100644
--- a/crowdmatch/src/Crowdmatch.hs
+++ b/crowdmatch/src/Crowdmatch.hs
@@ -100,14 +100,13 @@ data Project = Project
 
 -- | Record a 'TokenId' for a patron.
 storePaymentToken
-:: (ToCrowdmatchPatron usr, MonadIO io, MonadIO env)
-=> SqlRunner io env
--> StripeRunner
+:: (ToCrowdmatchPatron usr, MonadIO env)
+=> StripeRunner
 -> usr -- ^ your model's user, an instance of ToCrowdmatchPatron
 -> TokenId -- ^ you must independently get this from stripe
--> env (Either StripeError ())
-storePaymentToken db strp usr =
-runMech db . StorePaymentTokenI strp (usr ^. from external)
+-> SqlPersistT env (Either StripeError ())
+storePaymentToken strp usr =
+runMech . StorePaymentTokenI strp (usr ^. from external)
 
 -- NB: The "-- ^" in the following methods is intentional. It forces
 -- Haddocks to reformat the arguments in a pleasing way.
@@ -115,51 +114,45 @@ storePaymentToken db strp usr =
 -- | Delete the 'TokenId'. This will remove any existing pledges, since a
 -- a token is required for pledging.
 deletePaymentToken
-:: (ToCrowdmatchPatron usr, MonadIO io, MonadIO env)
-=> SqlRunner io env -- ^
--> StripeRunner
+:: (ToCrowdmatchPatron usr, MonadIO env)
+=> StripeRunner -- ^
 -> usr
--> env (Either StripeError ())
-deletePaymentToken db strp =
-runMech db . DeletePaymentTokenI strp . (^. from external)
+-> SqlPersistT env (Either StripeError ())
+deletePaymentToken strp =
+runMech . DeletePaymentTokenI strp . (^. from external)
 
 -- | Stores a pledge, joining the crowd. Requires the patron to already
 -- have a payment token available.
 storePledge
-:: (ToCrowdmatchPatron usr, MonadIO io, MonadIO env)
-=> SqlRunner io env -- ^
--> usr
--> env ()
-storePledge db = runMech db . StorePledgeI . (^. from external)
+:: (ToCrowdmatchPatron usr, MonadIO env)
+=> usr -- ^
+-> SqlPersistT env ()
+storePledge = runMech . StorePledgeI . (^. from external)
 
 -- | Delete a pledge, leaving the crowd.
 deletePledge
-:: (ToCrowdmatchPatron usr, MonadIO io, MonadIO env)
-=> SqlRunner io env -- ^
--> usr
--> env ()
-deletePledge db = runMech db . DeletePledgeI . (^. from external)
+:: (ToCrowdmatchPatron usr, MonadIO env)
+=> usr -- ^
+-> SqlPersistT env ()
+deletePledge = runMech . DeletePledgeI . (^. from external)
 
 -- | Retrieve info on the project.
 fetchProject
-:: (MonadIO io, MonadIO env)
-=> SqlRunner io env -- ^
--> env Project
-fetchProject 

Re: [Snowdrift-dev] [PATCH] crowdmatch: Use (SqlPersistT env) monad to allow combining queries

2017-07-08 Thread Bryan Richter
On Sun, Jul 09, 2017 at 04:56:29AM +0300, fr33domlover wrote:
> 
> Before this commit, crowdmatch actions run database queries separately
> inside them like a black box. That means in practice many applications
> of `runDB`, one per query, so a transaction per query. This is an
> unnecessary waste, and doesn't gain much (or anything at all, as this
> commit's changes my demonstrate).

Nice.

I'm finishing up make-payments right now, which will conflict with
this change, but once that's done (today) I will likely apply this
patch on top!


signature.asc
Description: Digital signature
___
Dev mailing list
Dev@lists.snowdrift.coop
https://lists.snowdrift.coop/mailman/listinfo/dev