Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
332 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Cats module for PureConfig | ||
|
||
Adds support for selected [cats](http://typelevel.org/cats/) classes to PureConfig. | ||
|
||
## Add pureconfig-cats to your project | ||
|
||
In addition to [core pureconfig](https://github.com/pureconfig/pureconfig), you'll need: | ||
|
||
```scala | ||
libraryDependencies += "com.github.pureconfig" %% "pureconfig-cats" % "0.7.1" | ||
``` | ||
|
||
## Example | ||
|
||
To load a `NonEmptyList[Int]` into a configuration, we need a class to hold our configuration: | ||
|
||
```scala | ||
import cats.data.{NonEmptyList, NonEmptyVector} | ||
import com.typesafe.config.ConfigFactory.parseString | ||
import pureconfig._ | ||
import pureconfig.module.cats._ | ||
|
||
case class MyConfig(numbers: NonEmptyList[Int]) | ||
``` | ||
|
||
We can read a `MyConfig` like: | ||
```scala | ||
val conf = parseString("""{ numbers: [1,2,3] }""") | ||
// conf: com.typesafe.config.Config = Config(SimpleConfigObject({"numbers":[1,2,3]})) | ||
|
||
loadConfig[MyConfig](conf) | ||
// res1: Either[pureconfig.error.ConfigReaderFailures,MyConfig] = Right(MyConfig(NonEmptyList(1, 2, 3))) | ||
``` | ||
|
||
You can also load `NonEmptyVector`. First, define a case class for the config: | ||
|
||
```scala | ||
case class MyVecConfig(numbers: NonEmptyVector[Int]) | ||
``` | ||
|
||
then load the config: | ||
```scala | ||
loadConfig[MyVecConfig](conf) | ||
// res2: Either[pureconfig.error.ConfigReaderFailures,MyVecConfig] = Right(MyVecConfig(NonEmptyVector(1, 2, 3))) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
name := "pureconfig-cats" | ||
|
||
organization := "com.github.pureconfig" | ||
|
||
homepage := Some(url("https://github.com/pureconfig/pureconfig")) | ||
|
||
licenses := Seq("Mozilla Public License, version 2.0" -> url("https://www.mozilla.org/MPL/2.0/")) | ||
|
||
resolvers ++= Seq( | ||
Resolver.sonatypeRepo("releases"), | ||
Resolver.sonatypeRepo("snapshots") | ||
) | ||
|
||
libraryDependencies ++= Seq( | ||
"org.typelevel" %% "cats-core" % "0.9.0", | ||
Dependencies.scalaMacrosParadise, | ||
Dependencies.scalaTest, | ||
Dependencies.scalaCheck | ||
) | ||
|
||
publishMavenStyle := true | ||
|
||
publishTo := { | ||
val nexus = "https://oss.sonatype.org/" | ||
if (isSnapshot.value) | ||
Some("snapshots" at nexus + "content/repositories/snapshots") | ||
else | ||
Some("releases" at nexus + "service/local/staging/deploy/maven2") | ||
} | ||
|
||
publishArtifact in Test := false | ||
|
||
pomExtra := ( | ||
<scm> | ||
<url>git@github.com:pureconfig/pureconfig.git</url> | ||
<connection>scm:git:git@github.com:pureconfig/pureconfig.git</connection> | ||
</scm> | ||
<developers> | ||
<developer> | ||
<id>derekmorr</id> | ||
<name>Derek Morr</name> | ||
<url>https://github.com/derekmorr</url> | ||
</developer> | ||
</developers>) | ||
|
||
osgiSettings | ||
|
||
OsgiKeys.exportPackage := Seq("pureconfig.module.cats.*") | ||
|
||
OsgiKeys.privatePackage := Seq() | ||
|
||
OsgiKeys.importPackage := Seq(s"""scala.*;version="[${scalaBinaryVersion.value}.0,${scalaBinaryVersion.value}.50)"""", "*") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package pureconfig.module | ||
|
||
import pureconfig.error.{ ConfigReaderFailure, ConfigValueLocation } | ||
|
||
object Cats { | ||
|
||
/** | ||
* A failure representing an unexpected empty traversable | ||
* | ||
* @param typ the type that was attempted to be converted to from an empty string | ||
* @param location an optional location of the ConfigValue that raised the | ||
* failure | ||
* @param path an optional path to the value which was an unexpected empty string | ||
*/ | ||
final case class EmptyTraversableFound(typ: String, location: Option[ConfigValueLocation], path: Option[String]) extends ConfigReaderFailure { | ||
def description = s"Empty collection found when trying to convert to $typ." | ||
|
||
def withImprovedContext(parentKey: String, parentLocation: Option[ConfigValueLocation]) = | ||
this.copy(location = location orElse parentLocation, path = path.map(parentKey + "." + _) orElse Some(parentKey)) | ||
} | ||
|
||
} |
38 changes: 38 additions & 0 deletions
38
modules/cats/src/main/scala/pureconfig/module/package.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package pureconfig.module | ||
|
||
import scala.language.higherKinds | ||
import scala.reflect.ClassTag | ||
|
||
import _root_.cats.data.{ NonEmptyList, NonEmptyVector } | ||
import com.typesafe.config.ConfigValue | ||
import pureconfig.{ ConfigReader, ConfigWriter } | ||
import pureconfig.ConfigReader.{ fromFunction => fromFunctionReader } | ||
import pureconfig.ConfigWriter.{ fromFunction => fromFunctionWriter } | ||
import pureconfig.error.{ ConfigReaderFailures, ConfigValueLocation } | ||
import pureconfig.module.Cats.EmptyTraversableFound | ||
|
||
/** | ||
* [[ConfigReader]] and [[ConfigWriter]] instances for cats data structures. | ||
*/ | ||
package object cats { | ||
|
||
private[pureconfig] def fromNonEmpty[F[_], G[_], T](fromFT: F[T] => Option[G[T]])(configValue: ConfigValue)(implicit ct: ClassTag[F[T]], fReader: ConfigReader[F[T]]): Either[ConfigReaderFailures, G[T]] = | ||
fReader.from(configValue).right.flatMap { ft => | ||
fromFT(ft) match { | ||
case None => Left(ConfigReaderFailures(EmptyTraversableFound(ct.toString, ConfigValueLocation(configValue), None))) | ||
case Some(nonEmpty) => Right(nonEmpty) | ||
} | ||
} | ||
|
||
implicit def nonEmptyListReader[T](implicit listReader: ConfigReader[List[T]]): ConfigReader[NonEmptyList[T]] = | ||
fromFunctionReader(fromNonEmpty[List, NonEmptyList, T](NonEmptyList.fromList)) | ||
|
||
implicit def nonEmptyListWriter[T](implicit listWriter: ConfigWriter[List[T]]): ConfigWriter[NonEmptyList[T]] = | ||
fromFunctionWriter(nel => listWriter.to(nel.toList)) | ||
|
||
implicit def nonEmptyVectorReader[T](implicit vectorReader: ConfigReader[Vector[T]]): ConfigReader[NonEmptyVector[T]] = | ||
fromFunctionReader(fromNonEmpty[Vector, NonEmptyVector, T](NonEmptyVector.fromVector)) | ||
|
||
implicit def nonEmptyVectorWriter[T](implicit vectorWriter: ConfigWriter[Vector[T]]): ConfigWriter[NonEmptyVector[T]] = | ||
fromFunctionWriter(nonEmptyVector => vectorWriter.to(nonEmptyVector.toVector)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Cats module for PureConfig | ||
|
||
Adds support for selected [cats](http://typelevel.org/cats/) classes to PureConfig. | ||
|
||
## Add pureconfig-cats to your project | ||
|
||
In addition to [core pureconfig](https://github.com/pureconfig/pureconfig), you'll need: | ||
|
||
```scala | ||
libraryDependencies += "com.github.pureconfig" %% "pureconfig-cats" % "0.7.1" | ||
``` | ||
|
||
## Example | ||
|
||
To load a `NonEmptyList[Int]` into a configuration, we need a class to hold our configuration: | ||
|
||
```tut:silent | ||
import cats.data.{NonEmptyList, NonEmptyVector} | ||
import com.typesafe.config.ConfigFactory.parseString | ||
import pureconfig._ | ||
import pureconfig.module.cats._ | ||
case class MyConfig(numbers: NonEmptyList[Int]) | ||
``` | ||
|
||
We can read a `MyConfig` like: | ||
```tut:book | ||
val conf = parseString("""{ numbers: [1,2,3] }""") | ||
loadConfig[MyConfig](conf) | ||
``` | ||
|
||
You can also load `NonEmptyVector`. First, define a case class for the config: | ||
|
||
```tut:silent | ||
case class MyVecConfig(numbers: NonEmptyVector[Int]) | ||
``` | ||
|
||
then load the config: | ||
```tut:book | ||
loadConfig[MyVecConfig](conf) | ||
``` |
Oops, something went wrong.