by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Kasper Kondzielski
    @ghostbuster91
    @bplommer Could you give some example of how big are your case classes?
    Ben Plommer
    @bplommer
    @ghostbuster91 the one that was taking 12 seconds is a case class with 8 fields - most of the fields are case classes that wrap a single value of a refined type (from the refined library) - two of the fields are case classes that wrap two of those single-refined-value case classes, and one is a list of them. I'll put together a self-contained example later.
    Kasper Kondzielski
    @ghostbuster91
    Great, thanks. I tried to reproduce it by myself, but I saw only a decrease of 6 seconds after adding diffx to almost all the places in one of our projects.
    Ben Plommer
    @bplommer
    interesting
    xplosunn
    @xplosunn
    The link to diffx is broken on https://softwaremill.com/open-source/ (the link and title are "diffix" there)
    (maybe this is not the correct medium to report this but was unsure what is)
    Kasper Kondzielski
    @ghostbuster91
    @xplosunn It is good enough, thanks for reporting
    Kasper Kondzielski
    @ghostbuster91
    @xplosunn fixed ;)
    Spiridonov Sergey
    @Galefrei_gitlab

    Hello!

    Is it possible to exclude map keys from showed diff?

    I have a class

    case class OnlineInfo(
        Final: Map[String, Option[String]]
    )

    And whant to write something like

    implicit val modifiedFinalDiff: Diff[Map[String, Option[String]]] = Derived[Diff[Map[String, Option[String]]]].ignoreKey("CurrLocation").ignoreKey("DateTime")

    To see result where no diff found for keys CurrLocation and DateTime

    OnlineInfo(
         Final: Map(
              Tank1FuelUp: false
              AverageSpeed: 5.4700717787388884
              Signal: 7
              Overspeed: 0.0
              Park: true
              CurrLocation: 93° 29,95387' вд, 54° 39,60495' сш -> 93° 29,95387' E, 54° 39,60495' N
              Move: false
              Tank1FuelUpVol: 0.0
              Motion: 1
              FuelLevel1: 0.0
              Power: true
              Longitude: 93.499231212121231
              MaxSpeed: 10.641046217565703
              Speed: 0.0
              ParkCount: 2
              Tank1FuelLevel: 0.0
              Tank1FuelDn: false
              Tank1: 0
              Description: 0
              DateTime: /Date(1545543919000+0700)/ -> 2018-12-23T05:45:19
              Dist: 0.0
              Tank1FuelDnVol: 0.0
              Latitude: 54.6600825
              OverspeedCount: 0)

    How can I do that?

    P. S. Link for this gitter is broken in repository (https://github.com/softwaremill/diffx/blob/master/CONTRIBUTING.md).

    Kasper Kondzielski
    @ghostbuster91
    Thanks for letting me know, I've updated it
    Kasper Kondzielski
    @ghostbuster91
    In terms of ignoring value by a specific key, I am afraid that currently it is not possible. I will have to think how can it be hacked. And it might be a good idea to add it to diffx as well.
    Spiridonov Sergey
    @Galefrei_gitlab
    Right now I think about changing results manually in hashmap DiffResultMap
    Kasper Kondzielski
    @ghostbuster91
    Ah yes you can always do it but I was thinking about more elegant solution ;)
    Spiridonov Sergey
    @Galefrei_gitlab

    I tried to see how your code is working trought debugger and find some interesting places that might be helpfull.

    For full object called combine function in DiffMagnoliaDerivation trait.

    def combine[T](ctx: CaseClass[Typeclass, T]): Derived[Diff[T]] =
        Derived(new Diff[T] {
          override def apply(left: T, right: T, toIgnore: List[FieldPath]): DiffResult = {
            val map = ctx.parameters.map { p =>
              val lType = p.dereference(left)
              val pType = p.dereference(right)
              if (toIgnore.contains(List(p.label))) {
                p.label -> Identical(lType)
              } else {
                val nestedIgnore =
                  if (toIgnore.exists(_.headOption.exists(h => h == p.label))) toIgnore.map(_.drop(1)) else Nil
                p.label -> p.typeclass.value(lType, pType, nestedIgnore)
              }
            }.toMap
            if (map.values.forall(p => p.isIdentical)) {
              Identical(left)
            } else {
              DiffResultObject(ctx.typeName.short, map)
            }
          }
        })

    Because we not ignore changes in "Final" property, nestedIgnore variable is Nil. After that called DiffToMap apply method (inside p.typeclass.value(lType, pType, nestedIgnore))

    private[diffx] class DiffForMap[K, V, C[KK, VV] <: scala.collection.Map[KK, VV]](
        matcher: ObjectMatcher[K],
        diffKey: Diff[K],
        diffValue: Diff[Option[V]]
    ) extends Diff[C[K, V]] {
      override def apply(
          left: C[K, V],
          right: C[K, V],
          toIgnore: List[FieldPath]
      ): DiffResult = {
        val MatchingResults(unMatchedLeftKeys, unMatchedRightKeys, matchedKeys) =
          matching[K](left.keySet, right.keySet, matcher, diffKey, toIgnore)
        val leftDiffs = this.leftDiffs(left, unMatchedLeftKeys, unMatchedRightKeys)
        val rightDiffs = this.rightDiffs(right, unMatchedLeftKeys, unMatchedRightKeys)
        val matchedDiffs = this.matchedDiffs(matchedKeys, left, right, toIgnore)
        val diffs = leftDiffs ++ rightDiffs ++ matchedDiffs
        if (diffs.forall(p => p._1.isIdentical && p._2.isIdentical)) {
          Identical(left)
        } else {
          DiffResultMap(diffs.toMap)
        }
      }

    In this code i see two different places that can be useful to solve my problem

    1. matching function can ignore keys
    2. matchedDiffs method can build "identical" value for special keys

    Also, in matching function, as i understand code, toIgnore used to ignore map key properties. In matchedDiffs to ignore map value properties.

    Maybe, the solution for my problem is to change toIgnore variable signature to turple with list of ignored fields for keys and list of ignored fields for values.

    def apply(left: T, right: T, toIgnore: (List[FieldPath], List[FieldPath])): DiffResult

    And change matchedDiffs function.

    What do you think about that?

    Kasper Kondzielski
    @ghostbuster91
    @Galefrei_gitlab Sorry for this delayed response. This whole case is quite more complicated than that. At softwaremill we noticed that this pattern (generating unsafe string representation of chained calls) repeats also in tapir library and might appear in other places. Because of that we thought that it might be a good idea to extract it to a separate library. That's how the safepath was born - https://github.com/softwaremill/safepath. It isn't yet used in any of those because during the integration we found some problems which should be solved in more generic way, but once we solve them it should be possible to cover your case as well. Apart from that, based on what you wrote I can tell that your understanding is pretty good. But you are missing one crucial thing.Right now the Ignore macro omits synthetic functor (.each) because there is only one and it is always used in the same fashion - to access underlying collection elements. Because of that all functors (for a map, an option, an either etc ) are much more simplified and exists only in compile time. Having a functor at which would take an argument would mean that we would have to at least evaluate this argument. We would also need to distinguish between different functors.
    Jakub Kozłowski
    @kubukoz
    Hi, anyone else having issues with matchTo in scalatest 3.1.0?
    1 reply
    [E]      overloaded method value should with alternatives:
    [E]        (endWithWord: org.scalatest.matchers.dsl.EndWithWord)(implicit ev: List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent] <:< String)org.scalatest.matchers.should.Matchers.ResultOfEndWithWordForString <and>
    [E]        (startWithWord: org.scalatest.matchers.dsl.StartWithWord)(implicit ev: List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent] <:< String)org.scalatest.matchers.should.Matchers.ResultOfStartWithWordForString <and>
    [E]        (includeWord: org.scalatest.matchers.dsl.IncludeWord)(implicit ev: List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent] <:< String)org.scalatest.matchers.should.Matchers.ResultOfIncludeWordForString <and>
    [E]        (notExist: org.scalatest.matchers.dsl.ResultOfNotExist)(implicit existence: org.scalatest.enablers.Existence[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])org.scalatest.Assertion <and>
    [E]        (existWord: org.scalatest.matchers.dsl.ExistWord)(implicit existence: org.scalatest.enablers.Existence[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])org.scalatest.Assertion <and>
    [E]        (containWord: org.scalatest.matchers.dsl.ContainWord)org.scalatest.matchers.dsl.ResultOfContainWord[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]] <and>
    [E]        (haveWord: org.scalatest.matchers.dsl.HaveWord)org.scalatest.matchers.should.Matchers.ResultOfHaveWordForExtent[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]] <and>
    [E]        (beWord: org.scalatest.matchers.dsl.BeWord)org.scalatest.matchers.should.Matchers.ResultOfBeWordForAny[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]] <and>
    [E]        (inv: org.scalactic.TripleEqualsSupport.TripleEqualsInvocationOnSpread[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])(implicit ev: Numeric[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])org.scalatest.Assertion <and>
    [E]        [U](inv: org.scalactic.TripleEqualsSupport.TripleEqualsInvocation[U])(implicit constraint: org.scalactic.CanEqual[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent],U])org.scalatest.Assertion <and>
    [E]        (notWord: org.scalatest.matchers.dsl.NotWord)org.scalatest.matchers.dsl.ResultOfNotWordForAny[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]] <and>
    [E]        [TYPECLASS1[_], TYPECLASS2[_]](rightMatcherFactory2: org.scalatest.matchers.dsl.MatcherFactory2[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent],TYPECLASS1,TYPECLASS2])(implicit typeClass1: TYPECLASS1[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]], implicit typeClass2: TYPECLASS2[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])org.scalatest.Assertion <and>
    [E]        [TYPECLASS1[_]](rightMatcherFactory1: org.scalatest.matchers.dsl.MatcherFactory1[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent],TYPECLASS1])(implicit typeClass1: TYPECLASS1[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])org.scalatest.Assertion <and>
    [E]        (rightMatcherX1: org.scalatest.matchers.Matcher[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitEvent]])org.scalatest.Assertion
    [E]       cannot be applied to (com.softwaremill.diffx.scalatest.DiffMatcher.DiffForMatcher[List[com.ocado.ospnow.wms.order.events.hardlimit.HardLimitConfigChanged]])
    the code looks like foo.elems should matchTo(List(...))
    and I'm in a class that extends org.scalatest.matchers.should.Matchers
    btw. @ghostbuster91 I found this in 0.3.16 sources MatchResult(matches = false, "Matching error", "a co to?") xD
    3 replies
    Sergiusz Kierat
    @sergiuszkierat

    Hi @/all

    For the following example :

          import eu.timepit.refined.auto._
    
          case class A(name: String, u: eu.timepit.refined.types.numeric.PosLong)
    
          A("a", 1L) should matchTo(A("b", 2L))

    diffx fails with could not find implicit value for evidence parameter of type com.softwaremill.diffx.Diff[A] exception

    What is the best practice to deal with it?

    Kasper Kondzielski
    @ghostbuster91
    @sergiuszkierat Hi, I havn't tried diffx with refined types yet, it works with tagged types so I assume that it should be possible to make it work with refined types as well. I will check it and let you know
    Sergiusz Kierat
    @sergiuszkierat
    @ghostbuster91 thanks, let me know
    Jakub Kozłowski
    @kubukoz
    https://gitter.im/softwaremill/diffx?at=5e25e8d6a33d6607d5796bd8 now I'm pretty sure it was a variance/inference issue - basically when you have trait X; class Y extends X and (foo: List[X]) should matchTo(List(new Y))) it won't work. You need to widen the list to X.
    3 replies
    Jakub Kozłowski
    @kubukoz
    Is it just me or is are diffs for lists completely unreadable?
    image.png
    talking about the random ordering of elements
    disregard the weird coloring :P
    Kasper Kondzielski
    @ghostbuster91
    That looks weird indeed. I will look into it.
    Kasper Kondzielski
    @ghostbuster91
    @sergiuszkierat It seems like this simple trick works:
    implicit def drn2[T: Diff, P]: Derived[Diff[Refined[T, P]]] = Derived(Diff[T].contramap[Refined[T, P]](r => r.value))
    1 reply
    Kasper Kondzielski
    @ghostbuster91
    @kubukoz I have just released a fix for ordering. Thanks for reporting!
    Jakub Kozłowski
    @kubukoz
    Awesome! What was the issue?
    Kasper Kondzielski
    @ghostbuster91
    I was keeping data internally in hashmap ;)
    changing to other implementation solved that issue
    Michael Ahlers
    @michaelahlers

    I'm trying to use matchTo with a third-party class that wraps an Array[Byte]. I've provided a Diff[Array[Byte]] in scope, but it never seems to get used, and I always get matching errors similar to:

    value$access$0: BinaryData(
      value: [B@b468a17 -> [B@41888d84)

    Any advice?

    Kasper Kondzielski
    @ghostbuster91
    @michaelahlers Hi, array implements iterable interface and there is already an instance of Diff tc for it builtin into Diffx. If you want to override it you will need to wrap your definition with Dervied class, like so:
    implicit myArrayDiff: Derived[Diff[Array[Byte]] = Derived(your_code_goes_here)
    Let me know if that helps
    Wojtek Pituła
    @Krever

    Hey, I think diffx is having issues with refined types, resulting in

    Error:(89, 13) constructor Refined in class Refined cannot be accessed in <$anon: magnolia.CaseClass[com.softwaremill.diffx.Diff.Typeclass,foo.Bar>
        Diff.gen[Bar]

    when called explicitly. When summoned by implicitly it just refuses with missing implicit error.

    5 replies
    vonchav
    @voonchav_gitlab
    Hi, after I upgraded to the latest 0.3.24 diffx, my tapir stuff stopped compiling, erroring out on those json payloads in my tapir definitions, saying schemas not found... I think it could be a conflict with some dependency, say, magnolia, maybe?
    vonchav
    @voonchav_gitlab
    I'm only using diffx as a test dependency. but I think just by bringing it in, for some reason, it caused my main app to stop compiling (not just for my unit tests)...Once I went back to 0.3.23, my project compiles.
    Kasper Kondzielski
    @ghostbuster91
    Yes, it seems like a good clue. The newest version of diffx contains the latest version of magnolia. Which version of tapir do you use?
    Although that's really weird that it affects your main classpath
    vonchav
    @voonchav_gitlab
    @ghostbuster91 Yeah, it's a bit weird. All I did was bump the version of diffx. I'm using Tapir 0.12.28. Have yet to migrate to 0.13.1.
    vonchav
    @voonchav_gitlab
    BTW, @ghostbuster91, I have upgraded Tapir to 0.13.1. After that, I tried Diffx 0.3.24 with same errors. It still causes those line with json[ MY_ENTITY_CLASS ] to fail - the type of errors that Tapir typically shows when either codec/schema/validator is missing.
    Kasper Kondzielski
    @ghostbuster91
    @voonchav_gitlab and with previous diffx version all works fine?
    vonchav
    @voonchav_gitlab
    yes, no problem with 0.3.23. very weird.
    Kasper Kondzielski
    @ghostbuster91
    @voonchav_gitlab It is hard to say anything without seeing the code, could you prepare some example?
    vonchav
    @voonchav_gitlab
    @ghostbuster91 I think all things point to Magnolia. I just upgraded Tapir to 0.13.2 with diffx still at 0.3.23. I got the same error. I also use Caliban (grahql lib) which also lies on Magnolia. Now, with Tapir upgrade, I'm also getting errors from my Caliban code. I will try to come up with a code example.
    3 replies
    vonchav
    @voonchav_gitlab
    @ghostbuster91 you fixed the problem! I upgraded to 0.3.27 and finally my project compiles again. Great work. Thank you. What was the problem and how did you fix it? I think @adamw might need to do the same for Tapir 0.13.2 (0.13.1 works but 0.13.2 fails to compile)
    2 replies
    Maxim Miholap
    @maxmiholap
    does anyone know how to fix NoClassDefFoundError ? java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: reactivemongo/api/bson/BSONObjectID$<local child>
    Kasper Kondzielski
    @ghostbuster91
    @maxmiholap Can you give a little bit more details?