Skip to content

Commit

Permalink
Merge branch 'master' into custom-render-options
Browse files Browse the repository at this point in the history
  • Loading branch information
ruippeixotog committed Aug 17, 2018
2 parents a04d128 + 6c7f8a9 commit 01a0cae
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 19 deletions.
Expand Up @@ -55,6 +55,7 @@ object ConvertFailure {
/**
* A failure occurred because a list of files to load was empty.
*/
@deprecated("`loadConfigFromFiles` won't return this failure anymore", "0.10.0")
case object NoFilesToRead extends ConfigReaderFailure {
def description = "The config files to load must not be empty."
def location = None
Expand Down
33 changes: 17 additions & 16 deletions core/src/main/scala/pureconfig/package.scala
Expand Up @@ -276,27 +276,28 @@ package object pureconfig {
}

/**
* Loads `files` in order, allowing values in later files to backstop missing values from prior, and converts them into a `Config`.
* Loads `files` in order, allowing values in later files to backstop missing values from prior, and converts them
* into a `Config`.
*
* This is a convenience method which enables having default configuration which backstops local configuration.
*
* Note: If an element of `files` references a file which doesn't exist or can't be read, it will silently be ignored.
* The behavior of the method if an element of `files` references a file which doesn't exist or can't be read is
* defined by the `failOnReadError` flag. With `failOnReadError = false`, such files will silently be ignored while
* otherwise they would yield a failure (a `Left` value).
*
* @param files Files ordered in decreasing priority containing part or all of a `Config`. Must not be empty.
* @param files Files ordered in decreasing priority containing part or all of a `Config`
*/
def loadConfigFromFiles[Config](files: Traversable[Path])(implicit reader: Derivation[ConfigReader[Config]]): Either[ConfigReaderFailures, Config] = {
if (files.isEmpty) {
Left(ConfigReaderFailures(NoFilesToRead))
} else {
files
.map(parseFile)
.foldLeft[Either[ConfigReaderFailures, Seq[TypesafeConfig]]](Right(Seq())) {
case (c1, Left(failures)) if failures.toList.exists(_.isInstanceOf[CannotReadFile]) => c1
case (c1, c2) => ConfigConvert.combineResults(c1, c2)(_ :+ _)
}
.right.map(_.reduce(_.withFallback(_)).resolve)
.right.flatMap(loadConfig[Config])
}
def loadConfigFromFiles[Config](files: Traversable[Path], failOnReadError: Boolean = false)(implicit reader: Derivation[ConfigReader[Config]]): Either[ConfigReaderFailures, Config] = {
files.map(parseFile)
.map {
case Left(failures) if failures.toList.exists(_.isInstanceOf[CannotReadFile]) && !failOnReadError =>
Right(ConfigFactory.empty())
case conf => conf
}
.foldLeft[Either[ConfigReaderFailures, TypesafeConfig]](Right(ConfigFactory.empty())) {
case (c1, c2) => ConfigConvert.combineResults(c1, c2)(_.withFallback(_))
}
.right.flatMap { conf => loadConfig[Config](conf.resolve) }
}

/**
Expand Down
12 changes: 9 additions & 3 deletions core/src/test/scala/pureconfig/ApiSuite.scala
Expand Up @@ -155,18 +155,24 @@ class ApiSuite extends BaseSuite {
loadConfigFromFiles[Conf](files) shouldBe Right(Conf(0.99F))
}

it should "fail if the list of files is empty" in {
it should "use an empty config if the list of files is empty" in {
case class Conf(f: Float)
val files = Set.empty[Path]
loadConfigFromFiles[Conf](files) should failWithType[NoFilesToRead.type]
loadConfigFromFiles[Conf](files) should failWithType[KeyNotFound] // f is missing
}

it should "ignore files that don't exist" in {
it should "ignore files that don't exist when failOnReadError is false" in {
case class Conf(b: Boolean, d: Double)
val files = listResourcesFromNames("/conf/loadConfigFromFiles/priority2.conf") :+ nonExistingPath
loadConfigFromFiles[Conf](files) shouldBe Right(Conf(false, 0.001D))
}

it should "fail if any of the files doesn't exist and failOnReadError is true" in {
case class Conf(f: Float)
val files = listResourcesFromNames("/conf/loadConfigFromFiles/priority2.conf") :+ nonExistingPath
loadConfigFromFiles[Conf](files, failOnReadError = true) should failWithType[CannotReadFile]
}

"loadConfigWithFallback" should "fallback if no config keys are found" in {
case class Conf(f: Float, o: Option[Int], d: Double)
val priority1Conf = ConfigFactory.load("conf/loadConfigFromFiles/priority1.conf")
Expand Down

0 comments on commit 01a0cae

Please sign in to comment.