diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 451de162..a306905c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,9 @@ jobs: build-linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.5.3 name: Checkout - - uses: cachix/install-nix-action@v20 + - uses: cachix/install-nix-action@v21 name: Install Nix - uses: cachix/cachix-action@v12 name: Set up Cachix @@ -21,9 +21,9 @@ jobs: build-macos: runs-on: macos-latest steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.5.3 name: Checkout - - uses: cachix/install-nix-action@v20 + - uses: cachix/install-nix-action@v21 name: Install Nix - uses: cachix/cachix-action@v12 name: Set up Cachix diff --git a/README.md b/README.md index 820fb8c6..9937467a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ have extended and released under the same [`LICENSE`](./LICENSE) Installation ------------ -**The current version of this library requires gRPC version 1.34.1. Newer versions may work but have not been tested.** +**The current version of this library requires gRPC version 1.42.0. Newer versions may work but have not been tested.** Usage ----- diff --git a/Setup.hs b/Setup.hs deleted file mode 100644 index 9a994af6..00000000 --- a/Setup.hs +++ /dev/null @@ -1,2 +0,0 @@ -import Distribution.Simple -main = defaultMain diff --git a/core/Setup.hs b/core/Setup.hs deleted file mode 120000 index 115f3bb9..00000000 --- a/core/Setup.hs +++ /dev/null @@ -1 +0,0 @@ -../Setup.hs \ No newline at end of file diff --git a/core/grpc-haskell-core.cabal b/core/grpc-haskell-core.cabal index c1690f9a..21c6f63e 100644 --- a/core/grpc-haskell-core.cabal +++ b/core/grpc-haskell-core.cabal @@ -96,7 +96,7 @@ test-suite tests , proto3-suite , transformers , safe - , clock >=0.6.0 && <0.8.0 + , clock >=0.6.0 && <0.9 , turtle >= 1.2.0 , text , QuickCheck >=2.8 && <3.0 diff --git a/examples/echo/echo-hs/Echo.hs b/examples/echo/echo-hs/Echo.hs index 5c269f35..beb8abc5 100644 --- a/examples/echo/echo-hs/Echo.hs +++ b/examples/echo/echo-hs/Echo.hs @@ -1,23 +1,25 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} -{-# OPTIONS_GHC -fno-warn-unused-imports #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-} -{-# OPTIONS_GHC -fno-warn-unused-matches #-} +{-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -fno-warn-missing-export-lists #-} +{-# OPTIONS_GHC -fno-warn-name-shadowing #-} +{-# OPTIONS_GHC -fno-warn-unused-imports #-} +{-# OPTIONS_GHC -fno-warn-unused-matches #-} -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT! module Echo where import qualified Prelude as Hs import qualified Proto3.Suite.Class as HsProtobuf -import qualified Proto3.Suite.DotProto as HsProtobuf +import qualified Proto3.Suite.DotProto as HsProtobufAST import qualified Proto3.Suite.JSONPB as HsJSONPB import Proto3.Suite.JSONPB ((.=), (.:)) import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Wire as HsProtobuf +import qualified Proto3.Wire.Decode as HsProtobuf + (Parser, RawField) import qualified Control.Applicative as Hs import Control.Applicative ((<*>), (<|>), (<$>)) import qualified Control.DeepSeq as Hs @@ -34,6 +36,8 @@ import qualified Data.Vector as Hs (Vector) import qualified Data.Word as Hs (Word16, Word32, Word64) import qualified GHC.Enum as Hs import qualified GHC.Generics as Hs +import qualified Google.Protobuf.Wrappers.Polymorphic as HsProtobuf + (Wrapped(..)) import qualified Unsafe.Coerce as Hs import Network.GRPC.HighLevel.Generated as HsGRPC import Network.GRPC.HighLevel.Client as HsGRPC @@ -78,7 +82,9 @@ echoClient client (HsGRPC.MethodName "/echo.Echo/DoEcho"))) newtype EchoRequest = EchoRequest{echoRequestMessage :: Hs.Text} - deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) + deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic) + +instance Hs.NFData EchoRequest instance HsProtobuf.Named EchoRequest where nameOf _ = (Hs.fromString "EchoRequest") @@ -90,26 +96,37 @@ instance HsProtobuf.Message EchoRequest where EchoRequest{echoRequestMessage = echoRequestMessage} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1) - echoRequestMessage)]) + (Hs.coerce @(Hs.Text) @(HsProtobuf.String Hs.Text) + (echoRequestMessage)))]) decodeMessage _ = (Hs.pure EchoRequest) <*> - (HsProtobuf.at HsProtobuf.decodeMessageField - (HsProtobuf.FieldNumber 1)) + (HsProtobuf.coerceOver @(HsProtobuf.String Hs.Text) @(Hs.Text) + (HsProtobuf.at HsProtobuf.decodeMessageField + (HsProtobuf.FieldNumber 1))) dotProto _ - = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1) - (HsProtobuf.Prim HsProtobuf.String) - (HsProtobuf.Single "message") + = [(HsProtobufAST.DotProtoField (HsProtobuf.FieldNumber 1) + (HsProtobufAST.Prim HsProtobufAST.String) + (HsProtobufAST.Single "message") [] "")] instance HsJSONPB.ToJSONPB EchoRequest where - toJSONPB (EchoRequest f1) = (HsJSONPB.object ["message" .= f1]) - toEncodingPB (EchoRequest f1) = (HsJSONPB.pairs ["message" .= f1]) + toJSONPB (EchoRequest f1) + = (HsJSONPB.object + ["message" .= + (Hs.coerce @(Hs.Text) @(HsProtobuf.String Hs.Text) (f1))]) + toEncodingPB (EchoRequest f1) + = (HsJSONPB.pairs + ["message" .= + (Hs.coerce @(Hs.Text) @(HsProtobuf.String Hs.Text) (f1))]) instance HsJSONPB.FromJSONPB EchoRequest where parseJSONPB = (HsJSONPB.withObject "EchoRequest" - (\ obj -> (Hs.pure EchoRequest) <*> obj .: "message")) + (\ obj -> + (Hs.pure EchoRequest) <*> + (HsProtobuf.coerceOver @(HsProtobuf.String Hs.Text) @(Hs.Text) + (obj .: "message")))) instance HsJSONPB.ToJSON EchoRequest where toJSON = HsJSONPB.toAesonValue @@ -122,7 +139,9 @@ instance HsJSONPB.ToSchema EchoRequest where declareNamedSchema _ = do let declare_message = HsJSONPB.declareSchemaRef echoRequestMessage <- declare_message Proxy.Proxy - let _ = Hs.pure EchoRequest <*> HsJSONPB.asProxy declare_message + let _ = Hs.pure EchoRequest <*> + (HsProtobuf.coerceOver @(HsProtobuf.String Hs.Text) @(Hs.Text) + (HsJSONPB.asProxy declare_message)) Hs.return (HsJSONPB.NamedSchema{HsJSONPB._namedSchemaName = Hs.Just "EchoRequest", @@ -135,7 +154,9 @@ instance HsJSONPB.ToSchema EchoRequest where [("message", echoRequestMessage)]}}) newtype EchoResponse = EchoResponse{echoResponseMessage :: Hs.Text} - deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) + deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic) + +instance Hs.NFData EchoResponse instance HsProtobuf.Named EchoResponse where nameOf _ = (Hs.fromString "EchoResponse") @@ -147,26 +168,37 @@ instance HsProtobuf.Message EchoResponse where EchoResponse{echoResponseMessage = echoResponseMessage} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1) - echoResponseMessage)]) + (Hs.coerce @(Hs.Text) @(HsProtobuf.String Hs.Text) + (echoResponseMessage)))]) decodeMessage _ = (Hs.pure EchoResponse) <*> - (HsProtobuf.at HsProtobuf.decodeMessageField - (HsProtobuf.FieldNumber 1)) + (HsProtobuf.coerceOver @(HsProtobuf.String Hs.Text) @(Hs.Text) + (HsProtobuf.at HsProtobuf.decodeMessageField + (HsProtobuf.FieldNumber 1))) dotProto _ - = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1) - (HsProtobuf.Prim HsProtobuf.String) - (HsProtobuf.Single "message") + = [(HsProtobufAST.DotProtoField (HsProtobuf.FieldNumber 1) + (HsProtobufAST.Prim HsProtobufAST.String) + (HsProtobufAST.Single "message") [] "")] instance HsJSONPB.ToJSONPB EchoResponse where - toJSONPB (EchoResponse f1) = (HsJSONPB.object ["message" .= f1]) - toEncodingPB (EchoResponse f1) = (HsJSONPB.pairs ["message" .= f1]) + toJSONPB (EchoResponse f1) + = (HsJSONPB.object + ["message" .= + (Hs.coerce @(Hs.Text) @(HsProtobuf.String Hs.Text) (f1))]) + toEncodingPB (EchoResponse f1) + = (HsJSONPB.pairs + ["message" .= + (Hs.coerce @(Hs.Text) @(HsProtobuf.String Hs.Text) (f1))]) instance HsJSONPB.FromJSONPB EchoResponse where parseJSONPB = (HsJSONPB.withObject "EchoResponse" - (\ obj -> (Hs.pure EchoResponse) <*> obj .: "message")) + (\ obj -> + (Hs.pure EchoResponse) <*> + (HsProtobuf.coerceOver @(HsProtobuf.String Hs.Text) @(Hs.Text) + (obj .: "message")))) instance HsJSONPB.ToJSON EchoResponse where toJSON = HsJSONPB.toAesonValue @@ -179,7 +211,9 @@ instance HsJSONPB.ToSchema EchoResponse where declareNamedSchema _ = do let declare_message = HsJSONPB.declareSchemaRef echoResponseMessage <- declare_message Proxy.Proxy - let _ = Hs.pure EchoResponse <*> HsJSONPB.asProxy declare_message + let _ = Hs.pure EchoResponse <*> + (HsProtobuf.coerceOver @(HsProtobuf.String Hs.Text) @(Hs.Text) + (HsJSONPB.asProxy declare_message)) Hs.return (HsJSONPB.NamedSchema{HsJSONPB._namedSchemaName = Hs.Just "EchoResponse", @@ -189,4 +223,5 @@ instance HsJSONPB.ToSchema EchoResponse where Hs.Just HsJSONPB.SwaggerObject}, HsJSONPB._schemaProperties = HsJSONPB.insOrdFromList - [("message", echoResponseMessage)]}}) \ No newline at end of file + [("message", echoResponseMessage)]}}) + diff --git a/examples/tutorial/Arithmetic.hs b/examples/tutorial/Arithmetic.hs index c99e5143..d8b1f349 100644 --- a/examples/tutorial/Arithmetic.hs +++ b/examples/tutorial/Arithmetic.hs @@ -1,23 +1,25 @@ -{-# LANGUAGE DeriveGeneric #-} -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} -{-# OPTIONS_GHC -fno-warn-unused-imports #-} -{-# OPTIONS_GHC -fno-warn-name-shadowing #-} -{-# OPTIONS_GHC -fno-warn-unused-matches #-} +{-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -fno-warn-missing-export-lists #-} +{-# OPTIONS_GHC -fno-warn-name-shadowing #-} +{-# OPTIONS_GHC -fno-warn-unused-imports #-} +{-# OPTIONS_GHC -fno-warn-unused-matches #-} -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT! module Arithmetic where import qualified Prelude as Hs import qualified Proto3.Suite.Class as HsProtobuf -import qualified Proto3.Suite.DotProto as HsProtobuf +import qualified Proto3.Suite.DotProto as HsProtobufAST import qualified Proto3.Suite.JSONPB as HsJSONPB import Proto3.Suite.JSONPB ((.=), (.:)) import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Wire as HsProtobuf +import qualified Proto3.Wire.Decode as HsProtobuf + (Parser, RawField) import qualified Control.Applicative as Hs import Control.Applicative ((<*>), (<|>), (<$>)) import qualified Control.DeepSeq as Hs @@ -34,6 +36,8 @@ import qualified Data.Vector as Hs (Vector) import qualified Data.Word as Hs (Word16, Word32, Word64) import qualified GHC.Enum as Hs import qualified GHC.Generics as Hs +import qualified Google.Protobuf.Wrappers.Polymorphic as HsProtobuf + (Wrapped(..)) import qualified Unsafe.Coerce as Hs import Network.GRPC.HighLevel.Generated as HsGRPC import Network.GRPC.HighLevel.Client as HsGRPC @@ -98,7 +102,9 @@ arithmeticClient client (HsGRPC.MethodName "/arithmetic.Arithmetic/RunningSum"))) data TwoInts = TwoInts{twoIntsX :: Hs.Int32, twoIntsY :: Hs.Int32} - deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) + deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic) + +instance Hs.NFData TwoInts instance HsProtobuf.Named TwoInts where nameOf _ = (Hs.fromString "TwoInts") @@ -120,14 +126,14 @@ instance HsProtobuf.Message TwoInts where (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2)) dotProto _ - = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1) - (HsProtobuf.Prim HsProtobuf.Int32) - (HsProtobuf.Single "x") + = [(HsProtobufAST.DotProtoField (HsProtobuf.FieldNumber 1) + (HsProtobufAST.Prim HsProtobufAST.Int32) + (HsProtobufAST.Single "x") [] ""), - (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) - (HsProtobuf.Prim HsProtobuf.Int32) - (HsProtobuf.Single "y") + (HsProtobufAST.DotProtoField (HsProtobuf.FieldNumber 2) + (HsProtobufAST.Prim HsProtobufAST.Int32) + (HsProtobufAST.Single "y") [] "")] @@ -168,7 +174,9 @@ instance HsJSONPB.ToSchema TwoInts where [("x", twoIntsX), ("y", twoIntsY)]}}) newtype OneInt = OneInt{oneIntResult :: Hs.Int32} - deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) + deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic) + +instance Hs.NFData OneInt instance HsProtobuf.Named OneInt where nameOf _ = (Hs.fromString "OneInt") @@ -185,9 +193,9 @@ instance HsProtobuf.Message OneInt where (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1)) dotProto _ - = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1) - (HsProtobuf.Prim HsProtobuf.Int32) - (HsProtobuf.Single "result") + = [(HsProtobufAST.DotProtoField (HsProtobuf.FieldNumber 1) + (HsProtobufAST.Prim HsProtobufAST.Int32) + (HsProtobufAST.Single "result") [] "")] @@ -220,4 +228,5 @@ instance HsJSONPB.ToSchema OneInt where Hs.Just HsJSONPB.SwaggerObject}, HsJSONPB._schemaProperties = HsJSONPB.insOrdFromList - [("result", oneIntResult)]}}) \ No newline at end of file + [("result", oneIntResult)]}}) + diff --git a/nix/dhall.nix b/nix/dhall.nix new file mode 100644 index 00000000..978b3c5b --- /dev/null +++ b/nix/dhall.nix @@ -0,0 +1,54 @@ +{ mkDerivation, aeson, aeson-pretty, ansi-terminal, atomic-write +, base, bytestring, case-insensitive, cborg, cborg-json, containers +, contravariant, cryptonite, data-fix, deepseq, Diff, directory +, doctest, dotgen, either, exceptions, filepath, foldl, gauge +, generic-random, half, hashable, haskeline, http-client +, http-client-tls, http-types, lens-family-core, lib, megaparsec +, memory, mmorph, mockery, mtl, network-uri, optparse-applicative +, parser-combinators, parsers, pretty-simple, prettyprinter +, prettyprinter-ansi-terminal, profunctors, QuickCheck +, quickcheck-instances, repline, scientific, serialise +, special-values, spoon, tasty, tasty-expected-failure, tasty-hunit +, tasty-quickcheck, tasty-silver, template-haskell, text +, text-manipulate, th-lift-instances, transformers +, transformers-compat, turtle, unordered-containers, uri-encode +, vector +}: +mkDerivation { + pname = "dhall"; + version = "1.38.1"; + sha256 = "f3e95cfa0ef1a89d5ca29591b7925db51551150a27f3fd02717ce69699e8e03c"; + revision = "2"; + editedCabalFile = "02z0jmzzp20yj46iz6i384xwc6k2anxb33smvc4yhpmhqjs0aq8a"; + isLibrary = true; + isExecutable = true; + enableSeparateDataOutput = true; + libraryHaskellDepends = [ + aeson aeson-pretty ansi-terminal atomic-write base bytestring + case-insensitive cborg cborg-json containers contravariant + cryptonite data-fix deepseq Diff directory dotgen either exceptions + filepath half hashable haskeline http-client http-client-tls + http-types lens-family-core megaparsec memory mmorph mtl + network-uri optparse-applicative parser-combinators parsers + pretty-simple prettyprinter prettyprinter-ansi-terminal profunctors + repline scientific serialise template-haskell text text-manipulate + th-lift-instances transformers transformers-compat + unordered-containers uri-encode vector + ]; + executableHaskellDepends = [ base ]; + testHaskellDepends = [ + base bytestring cborg containers data-fix deepseq directory doctest + either filepath foldl generic-random http-client http-client-tls + lens-family-core megaparsec mockery prettyprinter QuickCheck + quickcheck-instances scientific serialise special-values spoon + tasty tasty-expected-failure tasty-hunit tasty-quickcheck + tasty-silver template-haskell text transformers turtle + unordered-containers vector + ]; + benchmarkHaskellDepends = [ + base bytestring containers directory gauge text + ]; + doCheck = false; + description = "A configuration language guaranteed to terminate"; + license = lib.licenses.bsd3; +} diff --git a/nix/grpc.nix b/nix/grpc.nix deleted file mode 100644 index 92cf619a..00000000 --- a/nix/grpc.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ lib, stdenv, fetchFromGitHub, fetchpatch, cmake, zlib, c-ares, pkg-config, openssl, protobuf -, gflags, abseil-cpp, libnsl -}: - -stdenv.mkDerivation rec { - version = "1.34.1"; # N.B: if you change this, change pythonPackages.grpcio-tools to a matching version too - pname = "grpc"; - src = fetchFromGitHub { - owner = "grpc"; - repo = "grpc"; - rev = "v${version}"; - sha256 = "0p6si9i0gg885ag2x87a7jyzhgd5lhx2bh2vjj2ra1jn6y3vg6qk"; - fetchSubmodules = true; - }; - patches = [ - # Fix build on armv6l (https://github.com/grpc/grpc/pull/21341) - (fetchpatch { - url = "https://github.com/grpc/grpc/commit/2f4cf1d9265c8e10fb834f0794d0e4f3ec5ae10e.patch"; - sha256 = "0ams3jmgh9yzwmxcg4ifb34znamr7pb4qm0609kvil9xqvkqz963"; - }) - ]; - - nativeBuildInputs = [ cmake pkg-config ]; - buildInputs = [ zlib c-ares c-ares.cmake-config openssl protobuf gflags abseil-cpp ] - ++ lib.optionals stdenv.isLinux [ libnsl ]; - - cmakeFlags = - [ "-DgRPC_ZLIB_PROVIDER=package" - "-DgRPC_CARES_PROVIDER=package" - "-DgRPC_SSL_PROVIDER=package" - "-DgRPC_PROTOBUF_PROVIDER=package" - "-DgRPC_GFLAGS_PROVIDER=package" - "-DgRPC_ABSL_PROVIDER=package" - "-DBUILD_SHARED_LIBS=ON" - "-DCMAKE_SKIP_BUILD_RPATH=OFF" - ]; - - # CMake creates a build directory by default, this conflicts with the - # basel BUILD file on case-insensitive filesystems. - preConfigure = '' - rm -vf BUILD - ''; - - preBuild = '' - export LD_LIBRARY_PATH=$(pwd)''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH - ''; - - NIX_CFLAGS_COMPILE = lib.optionalString stdenv.cc.isClang "-Wno-error=unknown-warning-option"; - - enableParallelBuilds = true; - - meta = with lib; { - description = "The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)"; - license = licenses.asl20; - maintainers = [ maintainers.lnl7 maintainers.marsam ]; - homepage = "https://grpc.io/"; - platforms = platforms.all; - changelog = "https://github.com/grpc/grpc/releases/tag/v${version}"; - }; -} diff --git a/nix/large-generics.nix b/nix/large-generics.nix new file mode 100644 index 00000000..72838af3 --- /dev/null +++ b/nix/large-generics.nix @@ -0,0 +1,24 @@ +{ mkDerivation, aeson, base, deepseq, fetchgit, generic-deriving +, generics-sop, lib, microlens, mtl, primitive, QuickCheck +, sop-core, tasty, tasty-hunit, tasty-quickcheck +}: +mkDerivation { + pname = "large-generics"; + version = "0.2.0.0"; + src = fetchgit { + url = "https://github.com/well-typed/large-records.git"; + sha256 = "0rzssshn6jjdp2l0gx2k60wca17ha62gxq51xyd4rl3vgh2ql7n0"; + rev = "f13dd4514a247dca4a24a7668d702695748f8105"; + fetchSubmodules = true; + }; + postUnpack = "sourceRoot+=/large-generics; echo source root reset to $sourceRoot"; + libraryHaskellDepends = [ + aeson base deepseq generics-sop primitive sop-core + ]; + testHaskellDepends = [ + aeson base generic-deriving generics-sop microlens mtl QuickCheck + sop-core tasty tasty-hunit tasty-quickcheck + ]; + description = "Generic programming API for large-records and large-anon"; + license = lib.licenses.bsd3; +} diff --git a/nix/large-records.nix b/nix/large-records.nix new file mode 100644 index 00000000..624d3e48 --- /dev/null +++ b/nix/large-records.nix @@ -0,0 +1,27 @@ +{ mkDerivation, base, containers, fetchgit, generic-deriving, ghc +, large-generics, lib, mtl, newtype, primitive +, record-dot-preprocessor, record-hasfield, syb, tasty, tasty-hunit +, template-haskell, transformers +}: +mkDerivation { + pname = "large-records"; + version = "0.2.2.0"; + src = fetchgit { + url = "https://github.com/well-typed/large-records.git"; + sha256 = "0rzssshn6jjdp2l0gx2k60wca17ha62gxq51xyd4rl3vgh2ql7n0"; + rev = "f13dd4514a247dca4a24a7668d702695748f8105"; + fetchSubmodules = true; + }; + postUnpack = "sourceRoot+=/large-records; echo source root reset to $sourceRoot"; + libraryHaskellDepends = [ + base containers ghc large-generics mtl primitive record-hasfield + syb template-haskell transformers + ]; + testHaskellDepends = [ + base generic-deriving large-generics mtl newtype + record-dot-preprocessor record-hasfield tasty tasty-hunit + template-haskell transformers + ]; + description = "Efficient compilation for large records, linear in the size of the record"; + license = lib.licenses.bsd3; +} diff --git a/nix/parameterized.patch b/nix/parameterized.patch deleted file mode 100644 index 08e03e8f..00000000 --- a/nix/parameterized.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs b/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs -index a39d181..1999e57 100644 ---- a/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs -+++ b/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs -@@ -91,7 +91,7 @@ whichIntBoolStringReader = do - manyIntMaybeReader :: ReaderT (Many '[Int]) Maybe String - manyIntMaybeReader = do - a <- ask -- let r = fetch @Int a -+ let r = grab @Int a - case r of - 0 -> empty - r' -> pure $ show r' -@@ -99,7 +99,7 @@ manyIntMaybeReader = do - manyBoolMaybeReader :: ReaderT (Many '[Bool]) Maybe String - manyBoolMaybeReader = do - a <- ask -- let r = fetch @Bool a -+ let r = grab @Bool a - case r of - False -> empty - r' -> pure $ show r' -diff --git a/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs b/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs -index 7dfd46c..4777c13 100644 ---- a/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs -+++ b/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs -@@ -26,7 +26,7 @@ main = hspec spec - manyIntMaybeState :: StateT (Many '[Int]) Maybe String - manyIntMaybeState= do - s <- get -- let r = fetch @Int s -+ let r = grab @Int s - case r of - 0 -> empty - r' -> do -@@ -36,7 +36,7 @@ manyIntMaybeState= do - manyBoolMaybeState :: StateT (Many '[Bool]) Maybe String - manyBoolMaybeState = do - s <- get -- let r = fetch @Bool s -+ let r = grab @Bool s - case r of - False -> empty - r' -> do diff --git a/nix/proto3-suite.nix b/nix/proto3-suite.nix index ce96ae4b..72fc0d77 100644 --- a/nix/proto3-suite.nix +++ b/nix/proto3-suite.nix @@ -1,21 +1,22 @@ { mkDerivation, aeson, aeson-pretty, attoparsec, base , base64-bytestring, binary, bytestring, cereal, containers -, contravariant, deepseq, doctest, fetchgit, filepath, foldl -, generic-arbitrary, hashable, haskell-src -, insert-ordered-containers, lens, lib, mtl, neat-interpolation -, optparse-applicative, optparse-generic, parsec, parsers, pretty -, pretty-show, proto3-wire, QuickCheck, quickcheck-instances -, range-set-list, safe, swagger2, system-filepath, tasty -, tasty-hunit, tasty-quickcheck, text, time, transformers, turtle -, vector +, contravariant, deepseq, dhall, doctest, fetchgit, filepath, foldl +, generic-arbitrary, hashable, haskell-src, hedgehog +, insert-ordered-containers, large-generics, large-records, lens +, lib, mtl, neat-interpolation, optparse-applicative +, optparse-generic, parsec, parsers, pretty, pretty-show +, proto3-wire, QuickCheck, quickcheck-instances, range-set-list +, safe, split, swagger2, system-filepath, tasty, tasty-hedgehog +, tasty-hunit, tasty-quickcheck, text, text-short, time +, transformers, turtle, vector }: mkDerivation { pname = "proto3-suite"; - version = "0.4.3"; + version = "0.6.0"; src = fetchgit { url = "https://github.com/awakesecurity/proto3-suite.git"; - sha256 = "0bjqczi6wddxv0n7qmfbrr19ajgq66xdkxx8vfcgbmv8ygma3vlw"; - rev = "7af7d76dcf9cc71ddada3aa4a38abf46f65550ca"; + sha256 = "1bvivy1rw84gln3kvb704wcsaz8l5xmgfibbbammbkmnjcgfs1y5"; + rev = "1f2c156b1178599d3853dac941beb3f29e2bdf5e"; fetchSubmodules = true; }; isLibrary = true; @@ -23,11 +24,12 @@ mkDerivation { enableSeparateDataOutput = true; libraryHaskellDepends = [ aeson aeson-pretty attoparsec base base64-bytestring binary - bytestring cereal containers contravariant deepseq filepath foldl - hashable haskell-src insert-ordered-containers lens mtl - neat-interpolation parsec parsers pretty pretty-show proto3-wire - QuickCheck quickcheck-instances safe swagger2 system-filepath text - time transformers turtle vector + bytestring cereal containers contravariant deepseq dhall filepath + foldl hashable haskell-src insert-ordered-containers large-generics + large-records lens mtl neat-interpolation parsec parsers pretty + pretty-show proto3-wire QuickCheck quickcheck-instances safe split + swagger2 system-filepath text text-short time transformers turtle + vector ]; executableHaskellDepends = [ base containers mtl optparse-applicative optparse-generic @@ -35,9 +37,10 @@ mkDerivation { ]; testHaskellDepends = [ aeson attoparsec base base64-bytestring bytestring cereal - containers deepseq doctest generic-arbitrary mtl pretty-show - proto3-wire QuickCheck swagger2 tasty tasty-hunit tasty-quickcheck - text transformers turtle vector + containers deepseq doctest generic-arbitrary hedgehog + large-generics large-records mtl parsec pretty pretty-show + proto3-wire QuickCheck swagger2 tasty tasty-hedgehog tasty-hunit + tasty-quickcheck text text-short transformers turtle vector ]; description = "A higher-level API to the proto3-wire library"; license = lib.licenses.asl20; diff --git a/nix/proto3-wire.nix b/nix/proto3-wire.nix index 40179552..6922ac52 100644 --- a/nix/proto3-wire.nix +++ b/nix/proto3-wire.nix @@ -1,21 +1,28 @@ -{ mkDerivation, base, bytestring, cereal, containers, deepseq -, doctest, ghc-prim, hashable, lib, parameterized, primitive -, QuickCheck, safe, tasty, tasty-hunit, tasty-quickcheck, text -, transformers, unordered-containers, vector +{ mkDerivation, base, bytestring, cereal, containers, criterion +, deepseq, doctest, fetchgit, ghc-prim, hashable, lib +, parameterized, primitive, QuickCheck, random, safe, tasty +, tasty-hunit, tasty-quickcheck, template-haskell, text, text-short +, transformers, unordered-containers, vector, word-compat }: mkDerivation { pname = "proto3-wire"; - version = "1.2.2"; - sha256 = "8d409536a89a0187f0576711966d2ef45d43acab7b6a3a1c5ee12f6d01adbfb9"; + version = "1.4.1"; + src = fetchgit { + url = "https://github.com/awakesecurity/proto3-wire.git"; + sha256 = "189dzkxdwnfscq8ylfalxkh95x7kkjlawz9wqkwbdblg5a5k1y7i"; + rev = "13962d58dbfb3cfbb539702746afe94ec02189ce"; + fetchSubmodules = true; + }; libraryHaskellDepends = [ base bytestring cereal containers deepseq ghc-prim hashable - parameterized primitive QuickCheck safe text transformers - unordered-containers vector + parameterized primitive QuickCheck safe template-haskell text + text-short transformers unordered-containers vector word-compat ]; testHaskellDepends = [ base bytestring cereal doctest QuickCheck tasty tasty-hunit - tasty-quickcheck text transformers vector + tasty-quickcheck text text-short transformers vector ]; + benchmarkHaskellDepends = [ base bytestring criterion random ]; description = "A low-level implementation of the Protocol Buffers (version 3) wire format"; license = lib.licenses.asl20; } diff --git a/nix/range-set-list.nix b/nix/range-set-list.nix new file mode 100644 index 00000000..6b975309 --- /dev/null +++ b/nix/range-set-list.nix @@ -0,0 +1,17 @@ +{ mkDerivation, base, containers, deepseq, hashable, lib, tasty +, tasty-quickcheck +}: +mkDerivation { + pname = "range-set-list"; + version = "0.1.3.1"; + sha256 = "12e8d9cb99a2847da32934ed7f44a5acedaa59d8fa19eff0f46aa77921460c55"; + revision = "5"; + editedCabalFile = "17a016lbs5p94bclgzqkyld4vhp4rnv4rg8xk4qhqyagggrvq9k7"; + libraryHaskellDepends = [ base containers deepseq hashable ]; + testHaskellDepends = [ + base containers deepseq hashable tasty tasty-quickcheck + ]; + homepage = "https://github.com/phadej/range-set-list#readme"; + description = "Memory efficient sets with ranges of elements"; + license = lib.licenses.mit; +} diff --git a/nix/record-dot-preprocessor.nix b/nix/record-dot-preprocessor.nix new file mode 100644 index 00000000..b3e65010 --- /dev/null +++ b/nix/record-dot-preprocessor.nix @@ -0,0 +1,16 @@ +{ mkDerivation, base, extra, filepath, ghc, lib, record-hasfield +, uniplate +}: +mkDerivation { + pname = "record-dot-preprocessor"; + version = "0.2.16"; + sha256 = "2c067163a6308a61e65f88e168558ac5062e41b86cad9346898bdd77e72b1a80"; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ base extra ghc uniplate ]; + executableHaskellDepends = [ base extra ]; + testHaskellDepends = [ base extra filepath record-hasfield ]; + homepage = "https://github.com/ndmitchell/record-dot-preprocessor#readme"; + description = "Preprocessor to allow record.field syntax"; + license = lib.licenses.bsd3; +} diff --git a/nix/word-compat.nix b/nix/word-compat.nix new file mode 100644 index 00000000..da64f558 --- /dev/null +++ b/nix/word-compat.nix @@ -0,0 +1,10 @@ +{ mkDerivation, base, ghc-prim, lib }: +mkDerivation { + pname = "word-compat"; + version = "0.0.6"; + sha256 = "305c2a9f9aab68cd5a8c9babaa9bc845d296ec5697b7e4ac4a2b368243fb278a"; + libraryHaskellDepends = [ base ghc-prim ]; + testHaskellDepends = [ base ]; + description = "Compatibility shim for the Int/Word internal change in GHC 9.2"; + license = lib.licenses.bsd3; +} diff --git a/nixpkgs.nix b/nixpkgs.nix index 1c22fafa..175ff216 100644 --- a/nixpkgs.nix +++ b/nixpkgs.nix @@ -7,6 +7,7 @@ # The SHA256 will be printed as the last line of stdout. import (builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/dd9f73e7d34486b09b966738ace161e621a0480b.tar.gz"; - sha256 = "0s674386v5b24a9fia26439gw9wsyhif85k2nzpxkp61293v3n3h"; + # nixos-21.11 as on 2023-06-15 + url = "https://github.com/NixOS/nixpkgs/archive/eabc38219184cc3e04a974fe31857d8e0eac098d.tar.gz"; + sha256 = "04ffwp2gzq0hhz7siskw6qh9ys8ragp7285vi1zh8xjksxn1msc5"; }) diff --git a/release.nix b/release.nix index 40df4637..7c2a5fef 100644 --- a/release.nix +++ b/release.nix @@ -68,20 +68,16 @@ let overlay = pkgsNew: pkgsOld: { - grpc = pkgsNew.callPackage ./nix/grpc.nix { }; - haskellPackages = pkgsOld.haskellPackages.override { overrides = haskellPackagesNew: haskellPackagesOld: rec { - parameterized = - pkgsNew.haskell.lib.overrideCabal - haskellPackagesOld.parameterized - (old: { - broken = false; - patches = (old.patches or [ ]) ++ [ ./nix/parameterized.patch ]; - }); + dhall = + haskellPackagesNew.callPackage ./nix/dhall.nix { }; + + large-generics = + haskellPackagesNew.callPackage ./nix/large-generics.nix { }; - haskell-src = - haskellPackagesNew.callHackage "haskell-src" "1.0.3.1" {}; + large-records = + haskellPackagesNew.callPackage ./nix/large-records.nix { }; proto3-wire = haskellPackagesNew.callPackage ./nix/proto3-wire.nix { }; @@ -90,6 +86,15 @@ let pkgsNew.haskell.lib.dontCheck (haskellPackagesNew.callPackage ./nix/proto3-suite.nix {}); + range-set-list = + haskellPackagesNew.callPackage ./nix/range-set-list.nix { }; + + record-dot-preprocessor = + haskellPackagesNew.callPackage ./nix/record-dot-preprocessor.nix { }; + + word-compat = + haskellPackagesNew.callPackage ./nix/word-compat.nix { }; + grpc-haskell-core = pkgsNew.haskell.lib.buildFromSdist (pkgsNew.usesGRPC (haskellPackagesNew.callCabal2nix "grpc-haskell-core" ./core { @@ -115,11 +120,12 @@ let pkgs.grpc-haskell-no-tests # Include some additional packages in this custom ghc for # running tests in the nix-shell environment. + pkgs.tasty-hunit pkgs.tasty-quickcheck pkgs.turtle ]); - python = pkgsNew.python.withPackages (pkgs: [ + python = pkgsNew.python310.withPackages (pkgs: [ pkgs.grpcio-tools ]); @@ -136,6 +142,9 @@ let # And likewise for c2hs haskellPackagesNew.c2hs + + # For compile-proto-file + haskellPackagesNew.proto3-suite ]; patches = diff --git a/tests/GeneratedTests.hs b/tests/GeneratedTests.hs index a9a06721..edbe6b4f 100644 --- a/tests/GeneratedTests.hs +++ b/tests/GeneratedTests.hs @@ -26,6 +26,8 @@ testServerGeneration = testCase "server generation" $ do , extraInstanceFiles = [] , inputProto = "simple.proto" , outputDir = hsTmpDir + , stringType = StringType "Data.Text.Lazy" "Text" + , recordStyle = LargeRecords } compileDotProtoFileOrDie args @@ -60,6 +62,8 @@ testClientGeneration = testCase "client generation" $ do , extraInstanceFiles = [] , inputProto = "simple.proto" , outputDir = hsTmpDir + , stringType = StringType "Data.Text.Lazy" "Text" + , recordStyle = LargeRecords } compileDotProtoFileOrDie args diff --git a/tests/TestClient.hs b/tests/TestClient.hs index 353bdaa1..ffbb6834 100644 --- a/tests/TestClient.hs +++ b/tests/TestClient.hs @@ -33,22 +33,22 @@ import System.Random import Test.Tasty import Test.Tasty.HUnit ((@?=), assertFailure, testCase) -testNormalCall client = testCase "Normal call" $ +testNormalCall SimpleService{..} = testCase "Normal call" $ do randoms <- fromList <$> replicateM 1000 (randomRIO (1, 1000)) let req = SimpleServiceRequest "NormalRequest" randoms - res <- simpleServicenormalCall client + res <- simpleServicenormalCall (ClientNormalRequest req 10 mempty) case res of ClientErrorResponse err -> assertFailure ("ClientErrorResponse: " <> show err) - ClientNormalResponse res _ _ stsCode _ -> + ClientNormalResponse SimpleServiceResponse{..} _ _ stsCode _ -> do stsCode @?= StatusOk - simpleServiceResponseResponse res @?= "NormalRequest" - simpleServiceResponseNum res @?= sum randoms + simpleServiceResponseResponse @?= "NormalRequest" + simpleServiceResponseNum @?= sum randoms -testClientStreamingCall client = testCase "Client-streaming call" $ +testClientStreamingCall SimpleService{..} = testCase "Client-streaming call" $ do iterationCount <- randomRIO (5, 50) v <- newEmptyMVar - res <- simpleServiceclientStreamingCall client . ClientWriterRequest 10 mempty $ \send -> + res <- simpleServiceclientStreamingCall . ClientWriterRequest 10 mempty $ \send -> do (finalName, totalSum) <- fmap ((mconcat *** (sum . mconcat)) . unzip) . replicateM iterationCount $ @@ -62,12 +62,12 @@ testClientStreamingCall client = testCase "Client-streaming call" $ case res of ClientErrorResponse err -> assertFailure ("ClientErrorResponse: " <> show err) ClientWriterResponse Nothing _ _ _ _ -> assertFailure "No response received" - ClientWriterResponse (Just res) _ _ stsCode _ -> + ClientWriterResponse (Just SimpleServiceResponse{..}) _ _ stsCode _ -> do stsCode @?= StatusOk - simpleServiceResponseResponse res @?= finalName - simpleServiceResponseNum res @?= totalSum + simpleServiceResponseResponse @?= finalName + simpleServiceResponseNum @?= totalSum -testServerStreamingCall client = testCase "Server-streaming call" $ +testServerStreamingCall SimpleService{..} = testCase "Server-streaming call" $ do numCount <- randomRIO (50, 500) nums <- replicateM numCount randomIO @@ -86,7 +86,7 @@ testServerStreamingCall client = testCase "Server-streaming call" $ do response @?= "Test" num @?= expNum checkResults nums recv - res <- simpleServiceserverStreamingCall client $ + res <- simpleServiceserverStreamingCall $ ClientReaderRequest (SimpleServiceRequest "Test" (fromList nums)) 10 mempty (\_ _ -> checkResults nums) case res of @@ -94,7 +94,7 @@ testServerStreamingCall client = testCase "Server-streaming call" $ ClientReaderResponse _ sts _ -> sts @?= StatusOk -testBiDiStreamingCall client = testCase "Bidi-streaming call" $ +testBiDiStreamingCall SimpleService{..} = testCase "Bidi-streaming call" $ do let handleRequests (0 :: Int) _ _ done = done >> pure () handleRequests n recv send done = do numCount <- randomRIO (10, 1000) @@ -113,7 +113,7 @@ testBiDiStreamingCall client = testCase "Bidi-streaming call" $ iterations <- randomRIO (50, 500) - res <- simpleServicebiDiStreamingCall client $ + res <- simpleServicebiDiStreamingCall $ ClientBiDiRequest 10 mempty (\_ _ -> handleRequests iterations) case res of ClientErrorResponse err -> assertFailure ("ClientErrorResponse: " <> show err) @@ -125,11 +125,11 @@ main = do threadDelay 10000000 withGRPC $ \grpc -> withClient grpc (ClientConfig "localhost:50051" [] Nothing Nothing) $ \client -> - do service <- simpleServiceClient client + do service@SimpleService{..} <- simpleServiceClient client (defaultMain $ testGroup "Send gRPC requests" [ testNormalCall service , testClientStreamingCall service , testServerStreamingCall service , testBiDiStreamingCall service ]) `finally` - (simpleServicedone service (ClientNormalRequest SimpleServiceDone 10 mempty)) + (simpleServicedone (ClientNormalRequest SimpleServiceDone 10 mempty)) diff --git a/tests/test-client.py b/tests/test-client.py index e9e1a233..43e8d9db 100644 --- a/tests/test-client.py +++ b/tests/test-client.py @@ -3,32 +3,32 @@ import grpc from uuid import uuid4 import random -import Queue +import queue -print "Starting python client" +print("Starting python client") channel = grpc.insecure_channel('localhost:50051') stub = SimpleServiceStub(channel) def runTests(): # Test normal call: return a sum of all numbers sent to it - print "Test 100 random sums" - for i in xrange(100): - randints = [random.randint(0, 1000) for _ in xrange(random.randint(10, 1000))] + print("Test 100 random sums") + for i in range(100): + randints = [random.randint(0, 1000) for _ in range(random.randint(10, 1000))] name = "test%d" % i response = stub.normalCall(SimpleServiceRequest(request = name, num = randints), timeout = 10) assert response.response == name assert response.num == sum(randints) # Test streaming call: The server response will be the sum of all numbers sent in the request along with a concatenation of the request name - print "Test 100 random sums (client streaming)" - for i in xrange(100): + print("Test 100 random sums (client streaming)") + for i in range(100): # avoid globals expected_sum = [0] expected_response_name = [''] def send_requests(esum, ename): - for _ in xrange(random.randint(5, 50)): - nums = [random.randint(0, 1000) for _ in xrange(random.randint(10, 100))] + for _ in range(random.randint(5, 50)): + nums = [random.randint(0, 1000) for _ in range(random.randint(10, 100))] name = str(uuid4()) esum[0] += sum(nums) ename[0] += name @@ -38,9 +38,9 @@ def send_requests(esum, ename): assert response.num == expected_sum[0] # Test server streaming call: The server should respond once for each number in the request - print "Test 100 random server streaming calls" - for i in xrange(100): - nums = [random.randint(0, 1000) for _ in xrange(random.randint(0, 1000))] + print("Test 100 random server streaming calls") + for i in range(100): + nums = [random.randint(0, 1000) for _ in range(random.randint(0, 1000))] for response in stub.serverStreamingCall(SimpleServiceRequest(request = "server streaming", num = nums), timeout = 60): assert response.num == nums[0] @@ -48,12 +48,12 @@ def send_requests(esum, ename): nums = nums[1:] # Test bidirectional streaming: for each request, we should get a response indicating the sum of all numbers sent in the last request - print "Test bidirectional streaming" - for i in xrange(100): - requests = Queue.Queue() + print("Test bidirectional streaming") + for i in range(100): + requests = queue.Queue() def send_requests(): - for _ in xrange(random.randint(5, 50)): - nums = [random.randint(0, 1000) for _ in xrange(random.randint(10, 100))] + for _ in range(random.randint(5, 50)): + nums = [random.randint(0, 1000) for _ in range(random.randint(10, 100))] name = str(uuid4()) requests.put((name, sum(nums))) @@ -66,18 +66,18 @@ def send_requests(): assert response.response == exp_name assert response.num == exp_sum - print "Sending DONE message to server" + print("Sending DONE message to server") stub.done(SimpleServiceDone(), timeout = 10) - print "All python client tests against the generated server were successful" + print("All python client tests against the generated server were successful") try: runTests() except Exception as e: - print "Python client test exception caught: " - print e.__doc__ - print e.message - print "Sending DONE message to server before exiting" + print("Python client test exception caught: ") + print(e.__doc__) + print(e.message) + print("Sending DONE message to server before exiting") stub.done(SimpleServiceDone(), timeout = 10) - print "Exiting with failure status" + print("Exiting with failure status") exit(1) diff --git a/tests/test-server.py b/tests/test-server.py index a58f4446..388f9389 100644 --- a/tests/test-server.py +++ b/tests/test-server.py @@ -3,12 +3,12 @@ from uuid import uuid4 from concurrent import futures import random -import Queue +import queue import grpc -print "Starting python server" +print("Starting python server") -done_queue = Queue.Queue() +done_queue = queue.Queue() class SimpleServiceServer(simple_pb2_grpc.SimpleServiceServicer): def done(self, request, context):