Skip to content
This repository was archived by the owner on Jan 24, 2025. It is now read-only.

Commit 07df052

Browse files
Migrate documentation to rtd (#263)
* Setup rtd * Setup rtd * Setup rtd * Setup rtd * Setup rtd * Restore default index.md * configure md * Use md parser * rtd * rtd * rtd * Add doc-tree to index * Working toctree * Add integrations * Add missing files * Add summary * Add docs on usage(ignoring and output) * Note about themes and env variable * Fix wording * Derivation * Change DiffDerivation to AutoDerivation * Extending * Fix approximate * Replacing * Fix mdoc compilation * Remove content from the readme and redirect to microsite * Fix indent * replacement/ignoring * sequences * Update readme * Fix ignoring example * Configure rtd edit on gh button * Fix badge url * Update version
1 parent f5f5087 commit 07df052

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1789
-542
lines changed

.readthedocs.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Required
2+
version: 2
3+
4+
sphinx:
5+
configuration: generated-docs/out/conf.py
6+
7+
# Optionally set the version of Python and requirements required to build your docs
8+
python:
9+
version: 3.7
10+
install:
11+
- requirements: generated-docs/out/requirements.pip

README.md

Lines changed: 8 additions & 279 deletions
Original file line numberDiff line numberDiff line change
@@ -1,294 +1,23 @@
11
![diffx](https://github.com/softwaremill/diffx/raw/master/banner.png)
22

3-
[![Build Status](https://travis-ci.org/softwaremill/diffx.svg?branch=master)](https://travis-ci.org/softwaremill/diffx)
3+
[![Build Status](https://img.shields.io/github/workflow/status/softwaremill/diffx/CI/master)](https://github.com/softwaremill/diffx/actions)
44
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.softwaremill.diffx/diffx-core_2.13/badge.svg)](https://search.maven.org/search?q=g:com.softwaremill.diffx)
55
[![Gitter](https://badges.gitter.im/softwaremill/diffx.svg)](https://gitter.im/softwaremill/diffx?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
66
[![Mergify Status](https://img.shields.io/endpoint.svg?url=https://gh.mergify.io/badges/softwaremill/diffx&style=flat)](https://mergify.io)
77
[![Scala Steward badge](https://img.shields.io/badge/Scala_Steward-helping-brightgreen.svg?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org)
88

9-
Pretty diffs for case classes.
9+
Pretty diffs for case classes.
1010

11-
The library is published for Scala 2.12 and 2.13.
11+
## Documentation
1212

13-
## Table of contents
14-
- [goals of the project](#goals-of-the-project)
15-
- [teaser](#teaser)
16-
- [derivation](#derivation)
17-
- [colors](#colors)
18-
- integrations
19-
- [scalatest](#scalatest-integration)
20-
- [specs2](#specs2-integration)
21-
- [utest](#utest-integration)
22-
- [other](#other-3rd-party-libraries-support)
23-
- [ignoring](#ignoring)
24-
- [customization](#customization)
25-
- [similar projects](#similar-projects)
26-
- [commercial support](#commercial-support)
13+
diffx documentation is available at [diffx-scala.readthedocs.io](https://diffx-scala.readthedocs.io).
2714

28-
## Goals of the project
15+
## Modifying documentation
16+
The documentation is typechecked using `mdoc`. The sources for the documentation exist in `docs-sources`. Don't modify the generated documentation in `generated-docs`, as these files will get overwritten!
2917

30-
- human-readable case class diffs
31-
- support for popular testing frameworks
32-
- OOTB collections support
33-
- OOTB non-case class support
34-
- smaller compilation overhead compared to shapless based solutions (thanks to magnolia <3)
35-
- programmer friendly and type safe api for partial ignore
18+
When generating documentation, it's best to set the version to the current one, so that the generated doc files don't include modifications with the current snapshot version.
3619

37-
## Teaser
38-
Add the following dependency:
39-
40-
```scala
41-
"com.softwaremill.diffx" %% "diffx-core" % "0.5.0"
42-
```
43-
44-
```scala
45-
sealed trait Parent
46-
case class Bar(s: String, i: Int) extends Parent
47-
case class Foo(bar: Bar, b: List[Int], parent: Option[Parent]) extends Parent
48-
49-
val right: Foo = Foo(
50-
Bar("asdf", 5),
51-
List(123, 1234),
52-
Some(Bar("asdf", 5))
53-
)
54-
// right: Foo = Foo(
55-
// bar = Bar(s = "asdf", i = 5),
56-
// b = List(123, 1234),
57-
// parent = Some(value = Bar(s = "asdf", i = 5))
58-
// )
59-
60-
val left: Foo = Foo(
61-
Bar("asdf", 66),
62-
List(1234),
63-
Some(right)
64-
)
65-
// left: Foo = Foo(
66-
// bar = Bar(s = "asdf", i = 66),
67-
// b = List(1234),
68-
// parent = Some(
69-
// value = Foo(
70-
// bar = Bar(s = "asdf", i = 5),
71-
// b = List(123, 1234),
72-
// parent = Some(value = Bar(s = "asdf", i = 5))
73-
// )
74-
// )
75-
// )
76-
77-
import com.softwaremill.diffx.generic.auto._
78-
import com.softwaremill.diffx._
79-
compare(left, right)
80-
// res0: DiffResult = DiffResultObject(
81-
// name = "Foo",
82-
// fields = ListMap(
83-
// "bar" -> DiffResultObject(
84-
// name = "Bar",
85-
// fields = ListMap(
86-
// "s" -> Identical(value = "asdf"),
87-
// "i" -> DiffResultValue(left = 66, right = 5)
88-
// )
89-
// ),
90-
// "b" -> DiffResultObject(
91-
// name = "List",
92-
// fields = ListMap(
93-
// "0" -> DiffResultValue(left = 1234, right = 123),
94-
// "1" -> DiffResultMissing(value = 1234)
95-
// )
96-
// ),
97-
// "parent" -> DiffResultValue(
98-
// left = "repl.MdocSession.App.Foo",
99-
// right = "repl.MdocSession.App.Bar"
100-
// )
101-
// )
102-
// )
103-
```
104-
105-
Will result in:
106-
107-
![example](https://github.com/softwaremill/diff-x/blob/master/example.png?raw=true)
108-
109-
110-
## Derivation
111-
112-
Diffx supports auto and semi-auto derivation.
113-
114-
For semi-auto derivation you don't need any additional import, just define your instances using:
115-
```scala
116-
case class Product(name: String)
117-
case class Basket(products: List[Product])
118-
119-
implicit val productDiff = Diff.derived[Product]
120-
implicit val basketDiff = Diff.derived[Basket]
121-
```
122-
123-
To use auto derivation add following import
124-
125-
`import com.softwaremill.diffx.generic.auto._`
126-
127-
or
128-
129-
extend trait
130-
131-
`com.softwaremill.diffx.generic.DiffDerivation`
132-
133-
**Auto derivation will have a huge impact on compilation times**, because of that it is recommended to use `semi-auto` derivation.
134-
135-
136-
## Colors
137-
138-
When running tests through sbt, default diffx's colors work well on both dark and light backgrounds.
139-
Unfortunately Intellij Idea forces the default color to red when displaying test's error.
140-
This means that it is impossible to print something with the standard default color (either white or black depending on the color scheme).
141-
142-
To have better colors, external information about the desired theme is required.
143-
Specify environment variable `DIFFX_COLOR_THEME` and set it to either `light` or `dark`.
144-
I had to specify it in `/etc/environment` rather than home profile for Intellij Idea to picked it up.
145-
146-
If anyone has an idea how this could be improved, I am open for suggestions.
147-
148-
## Scalatest integration
149-
150-
To use with scalatest, add the following dependency:
151-
152-
```scala
153-
"com.softwaremill.diffx" %% "diffx-scalatest" % "0.5.0" % Test
154-
```
155-
156-
Then, extend the `com.softwaremill.diffx.scalatest.DiffMatcher` trait or `import com.softwaremill.diffx.scalatest.DiffMatcher._`.
157-
After that you will be able to use syntax such as:
158-
159-
```scala
160-
import org.scalatest.matchers.should.Matchers._
161-
import com.softwaremill.diffx.scalatest.DiffMatcher._
162-
163-
left should matchTo(right)
164-
```
165-
166-
Giving you nice error messages:
167-
168-
## Specs2 integration
169-
170-
To use with specs2, add the following dependency:
171-
172-
```scala
173-
"com.softwaremill.diffx" %% "diffx-specs2" % "0.5.0" % Test
174-
```
175-
176-
Then, extend the `com.softwaremill.diffx.specs2.DiffMatcher` trait or `import com.softwaremill.diffx.specs2.DiffMatcher._`.
177-
After that you will be able to use syntax such as:
178-
179-
```scala
180-
import org.specs2.matcher.MustMatchers.{left => _, right => _, _}
181-
import com.softwaremill.diffx.specs2.DiffMatcher._
182-
183-
left must matchTo(right)
184-
```
185-
186-
## Utest integration
187-
188-
To use with utest, add following dependency:
189-
190-
```scala
191-
"com.softwaremill.diffx" %% "diffx-utest" % "0.5.0" % Test
192-
```
193-
194-
Then, mixin `DiffxAssertions` trait or add `import com.softwaremill.diffx.utest.DiffxAssertions._` to your test code.
195-
To assert using diffx use `assertEquals` as follows:
196-
197-
```scala
198-
import com.softwaremill.diffx.utest.DiffxAssertions._
199-
assertEqual(left, right)
200-
```
201-
202-
## Ignoring
203-
204-
Fields can be excluded from comparision by calling the `ignore` method on the `Diff` instance.
205-
Since `Diff` instances are immutable, the `ignore` method creates a copy of the instance with modified logic.
206-
You can use this instance explicitly.
207-
If you still would like to use it implicitly, you first need to summon the instance of the `Diff` typeclass using
208-
the `Derived` typeclass wrapper: `Derived[Diff[Person]]`. Thanks to that trick, later you will be able to put your modified
209-
instance of the `Diff` typeclass into the implicit scope. The whole process looks as follows:
210-
211-
```scala
212-
case class Person(name:String, age:Int)
213-
implicit val modifiedDiff: Diff[Person] = Derived[Diff[Person]].ignore(_.name)
214-
```
215-
216-
## Customization
217-
218-
If you'd like to implement custom matching logic for the given type, create an implicit `Diff` instance for that
219-
type, and make sure it's in scope when any `Diff` instances depending on that type are created.
220-
221-
Consider following example with `NonEmptyList` from cats. `NonEmptyList` is implemented as case class so diffx
222-
will create a `Diff[NonEmptyList]` typeclass instance using magnolia derivation.
223-
224-
Obviously that's not what we usually want. In most of the cases we would like `NonEmptyList` to be compared as a list.
225-
Diffx already has an instance of a typeclass for a list. One more thing to do is to use that typeclass by converting `NonEmptyList` to list which can be done using `contramap` method.
226-
227-
The final code looks as follows:
228-
229-
```scala
230-
import cats.data.NonEmptyList
231-
implicit def nelDiff[T: Diff]: Diff[NonEmptyList[T]] =
232-
Diff[List[T]].contramap[NonEmptyList[T]](_.toList)
233-
```
234-
235-
And here's an example of customizing the `Diff` instance for a child class of a sealed trait
236-
237-
```scala
238-
sealed trait ABParent
239-
case class A(id: String, name: String) extends ABParent
240-
case class B(id: String, name: String) extends ABParent
241-
242-
implicit val diffA: Diff[A] = Derived[Diff[A]].ignore(_.id)
243-
```
244-
```scala
245-
val a1: ABParent = A("1", "X")
246-
// a1: ABParent = A(id = "1", name = "X")
247-
val a2: ABParent = A("2", "X")
248-
// a2: ABParent = A(id = "2", name = "X")
249-
250-
compare(a1, a2)
251-
// res6: DiffResult = Identical(value = A(id = "1", name = "X"))
252-
```
253-
254-
As you can see instead of summoning bare instance of `Diff` for given `A` we summoned `Derived[Diff[A]]`.
255-
This is required in order to workaround self reference error.
256-
257-
You may need to add `-Wmacros:after` Scala compiler option to make sure to check for unused implicits
258-
after macro expansion.
259-
If you get warnings from Magnolia which looks like `magnolia: using fallback derivation for TYPE`,
260-
you can use the [Silencer](https://github.com/ghik/silencer) compiler plugin to silent the warning
261-
with the compiler option `"-P:silencer:globalFilters=^magnolia: using fallback derivation.*$"`
262-
263-
## Other 3rd party libraries support
264-
265-
- [com.softwaremill.common.tagging](https://github.com/softwaremill/scala-common)
266-
```scala
267-
"com.softwaremill.diffx" %% "diffx-tagging" % "0.5.0"
268-
```
269-
`com.softwaremill.diffx.tagging.DiffTaggingSupport`
270-
- [eu.timepit.refined](https://github.com/fthomas/refined)
271-
```scala
272-
"com.softwaremill.diffx" %% "diffx-refined" % "0.5.0"
273-
```
274-
`com.softwaremill.diffx.refined.RefinedSupport`
275-
- [org.typelevel.cats](https://github.com/typelevel/cats)
276-
```scala
277-
"com.softwaremill.diffx" %% "diffx-cats" % "0.5.0"
278-
```
279-
`com.softwaremill.diffx.cats.DiffCatsInstances`
280-
281-
## Similar projects
282-
283-
There is a number of similar projects from which diffx draws inspiration.
284-
285-
Below is a list of some of them, which I am aware of, with their main differences:
286-
- [xotai/diff](https://github.com/xdotai/diff) - based on shapeless, seems not to be activly developed anymore
287-
- [ratatool-diffy](https://github.com/spotify/ratatool/tree/master/ratatool-diffy) - the main purpose is to compare large data sets stored on gs or hdfs
288-
289-
## Commercial Support
290-
291-
We offer commercial support for diffx and related technologies, as well as development services. [Contact us](https://softwaremill.com) to learn more about our offer!
20+
That is, in sbt run: `set version := "0.5.0"`, before running `mdoc` in `docs`.
29221

29322
## Copyright
29423

build.sbt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@ lazy val commonSettings: Seq[Def.Setting[_]] = commonSmlBuildSettings ++ ossPubl
1616
scmInfo := Some(ScmInfo(url("https://github.com/softwaremill/diffx"), "[email protected]:softwaremill/diffx.git")),
1717
ideSkipProject := (scalaVersion.value != scalaIdeaVersion) || thisProjectRef.value.project.contains("JS"),
1818
updateDocs := Def.taskDyn {
19-
val files1 =
20-
UpdateVersionInDocs(sLog.value, organization.value, version.value, List(file("docs-sources") / "README.md"))
19+
val files1 = UpdateVersionInDocs(sLog.value, organization.value, version.value)
2120
Def.task {
2221
(docs.jvm(scala213) / mdoc).toTask("").value
23-
files1 ++ Seq(file("README.md"))
22+
files1 ++ Seq(file("generated-docs/out"))
2423
}
2524
}.value
2625
)
@@ -188,9 +187,9 @@ lazy val docs = (projectMatrix in file("generated-docs")) // important: it must
188187
mdocVariables := Map(
189188
"VERSION" -> version.value
190189
),
191-
mdocOut := file(".")
190+
mdocOut := file("generated-docs/out")
192191
)
193-
.dependsOn(core, scalatest, specs2, utest, refined, tagging)
192+
.dependsOn(core, scalatest, specs2, utest, refined, tagging, cats)
194193
.jvmPlatform(scalaVersions = List(scala213))
195194

196195
val testJVM = taskKey[Unit]("Test JVM projects")

core/src/main/scala/com/softwaremill/diffx/Diff.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ object Diff extends MiddlePriorityDiff with TupleInstances {
3939
/** Create a Diff instance using [[Object#equals]] */
4040
def useEquals[T]: Diff[T] = Diff.fallback[T]
4141

42-
def approximateNumericDiff[T: Numeric](epsilon: T): Diff[T] =
42+
def approximate[T: Numeric](epsilon: T): Diff[T] =
4343
new ApproximateDiffForNumeric[T](epsilon)
4444

4545
def derived[T]: Derived[Diff[T]] = macro MagnoliaDerivedMacro.derivedGen[T]

core/src/main/scala/com/softwaremill/diffx/generic/auto/DiffDerivation.scala renamed to core/src/main/scala/com/softwaremill/diffx/generic/auto/AutoDerivation.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package com.softwaremill.diffx.generic
22

33
import com.softwaremill.diffx.{Derived, Diff}
44

5-
package object auto extends DiffDerivation
5+
package object auto extends AutoDerivation
66

7-
trait DiffDerivation extends DiffMagnoliaDerivation {
7+
trait AutoDerivation extends DiffMagnoliaDerivation {
88
implicit def diffForCaseClass[T]: Derived[Diff[T]] = macro MagnoliaDerivedMacro.derivedGen[T]
99

1010
// Implicit conversion

core/src/main/scala/com/softwaremill/diffx/instances/ApproximateDiffForNumeric.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import com.softwaremill.diffx._
55
private[diffx] class ApproximateDiffForNumeric[T: Numeric](epsilon: T) extends Diff[T] {
66
override def apply(left: T, right: T, context: DiffContext): DiffResult = {
77
val numeric = implicitly[Numeric[T]]
8-
if (numeric.lt(numeric.abs(numeric.minus(left, right)), epsilon)) {
8+
if (numeric.lt(epsilon, numeric.abs(numeric.minus(left, right)))) {
99
DiffResultValue(left, right)
1010
} else {
1111
Identical(left)

core/src/test/scala/com/softwaremill/diffx/test/DiffTest.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ class DiffTest extends AnyFreeSpec with Matchers {
2424
"contravariant" in {
2525
compare(Some(1), Option(1)) shouldBe Identical(1)
2626
}
27+
"approximate - identical" in {
28+
val diff = Diff.approximate[Double](0.05)
29+
diff(0.12, 0.14) shouldBe Identical(0.12)
30+
}
31+
"approximate - different" in {
32+
val diff = Diff.approximate[Double](0.05)
33+
diff(0.12, 0.19) shouldBe DiffResultValue(0.12, 0.19)
34+
}
2735
}
2836

2937
"options" - {
@@ -287,7 +295,7 @@ class DiffTest extends AnyFreeSpec with Matchers {
287295
"compare lists using object matcher comparator" in {
288296
val o1 = Organization(List(p1, p2))
289297
val o2 = Organization(List(p2, p1))
290-
implicit val om: ObjectMatcher[(Int, Person)] = ObjectMatcher.byValue[Int, Person](ObjectMatcher.by(_.name))
298+
implicit val om: ObjectMatcher[(Int, Person)] = ObjectMatcher.byValue(ObjectMatcher.by(_.name))
291299
compare(o1, o2) shouldBe Identical(Organization(List(p1, p2)))
292300
}
293301

docs-sources/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_build
2+
_build_html

0 commit comments

Comments
 (0)