by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Jan 31 2019 15:23
    ashabhasa starred pureconfig/pureconfig
  • Jan 30 2019 20:03

    ruippeixotog on master

    Update cats-effect, fs2 and htt… Merge pull request #448 from ba… (compare)

  • Jan 30 2019 20:03
    ruippeixotog closed #448
  • Jan 30 2019 08:05
    Mao1990 starred pureconfig/pureconfig
  • Jan 29 2019 13:08
    bardurdam opened #448
  • Jan 29 2019 10:20
    PatrykRudnicki starred pureconfig/pureconfig
  • Jan 28 2019 18:52

    ruippeixotog on master

    Create a FluentConfigCursor Merge branch 'master' into flue… Fix yaml module on Scala 2.11 and 3 more (compare)

  • Jan 28 2019 18:52
    ruippeixotog closed #443
  • Jan 28 2019 18:02
    ruippeixotog synchronize #443
  • Jan 28 2019 18:02

    ruippeixotog on fluent-cursor

    Create scalaz module for pureco… Merge branch 'master' into scal… Update module with latest Confi… and 19 more (compare)

  • Jan 27 2019 14:09
    esumitra starred pureconfig/pureconfig
  • Jan 27 2019 01:55

    ruippeixotog on master

    Create scalaz module for pureco… Merge branch 'master' into scal… Update module with latest Confi… and 6 more (compare)

  • Jan 27 2019 01:55
    ruippeixotog closed #444
  • Jan 27 2019 01:19
    ruippeixotog synchronize #444
  • Jan 27 2019 01:19

    ruippeixotog on master

    Add cron4s module - add cron4s… Merge pull request #446 from ba… (compare)

  • Jan 27 2019 01:19
    ruippeixotog closed #446
  • Jan 26 2019 22:51
    ChernikovP synchronize #444
  • Jan 26 2019 22:37
    bardurdam synchronize #446
  • Jan 26 2019 22:36
    bardurdam commented #446
  • Jan 26 2019 22:31
    bardurdam synchronize #446
Joao Azevedo
@jcazevedo
That's odd. I was able to get your example compiling here.
ChernikovP
@ChernikovP
I restarted the REPL and it indeed worked. Thanks!
ChernikovP
@ChernikovP

Yeah, the actual reason , why I started digging is that with current setup:

sealed trait T
object T {
  case object O extends T
  case class I(i: Int) extends T
  object I {
    implicit val convert = semiauto.deriveConvert[I]
  }
  case class S(s: String) extends T
  object S {
    implicit val convert = semiauto.deriveConvert[S]
  }
  implicit val hint = new FieldCoproductHint[T]("mode")
}

case class Conf(t: T)
object Conf {
   implicit val cc = semiauto.deriveConvert[Conf]
}

results in could not find Lazy implicit value of type pureconfig.generic.DerivedConfigReader[Conf].

ChernikovP
@ChernikovP

Interestingly, if you put some extras to Conf companion object, everything will compile just fine:

object Conf {
  implicit val crt: DerivedConfigReader[T] = implicitly[DerivedConfigReader[T]]
  implicit val cwt: DerivedConfigWriter[T] = implicitly[DerivedConfigWriter[T]]
  implicit val cc = semiauto.deriveConvert[Conf]
}

What's even more interesting, that explicit types are required for crt and cwt variables to compile...

ChernikovP
@ChernikovP
@jcazevedo , is that behavior expected or this is bug when trying to get sealed families to work with semiauto?
Joao Azevedo
@jcazevedo
In order to derive a ConfigConvert for Conf, you need a ConfigConvert for T, which doesn't seem to be provided.
If you're going with a semiauto approach, you should also have a semiauto.deriveConvert[T] in scope.
I recommend having it in the companion object of T, so that it is available in the implicit scope of that type.
With your implicitly[DerivedConfig...] calls, you're providing a ConfigReader and ConfigWriter for T, but you shouldn't need to rely on implicitly nor on the DerivedConfigReader and DerivedConfigWriter types.
ChernikovP
@ChernikovP
So, you're saying I have to put implicit val cc: ConfigConvert[T] = semiauto.deriveConvert[T] in T's companion object along with FieldCoproductHint?
I'm getting:
 error: could not find Lazy implicit value of type pureconfig.generic.DerivedConfigReader[T]
  implicit val cc = semiauto.deriveConvert[T]
Joao Azevedo
@jcazevedo
I think that you might also be missing a ConfigConvert for O.
ChernikovP
@ChernikovP
Oh... Yeah... My sincere apologies for taking that much of your time ...
Joao Azevedo
@jcazevedo
No worries. :)
ChernikovP
@ChernikovP
And thanks a ton!
Leif Wickland
@leifwickland

Thanks, @jcazevedo!

For posterity here's a fully working example of using sealed families with semiauto derivation:

import pureconfig.generic.semiauto

sealed trait T extends Product with Serializable

object T {
  case object O extends T
  implicit val convertO: ConfigConvert[O.type] = semiauto.deriveConvert[O.type]

  case class I(i: Int) extends T
  object I {
    implicit val convert = semiauto.deriveConvert[I]
  }

  case class S(s: String) extends T
  object S {
    implicit val convert = semiauto.deriveConvert[S]
  }

  implicit val hint = new FieldCoproductHint[T]("mode")
  implicit val convertT: ConfigConvert[T] = semiauto.deriveConvert[T]
}

case class Conf2(t: T)
object Conf2 {
  implicit val cc = semiauto.deriveConvert[Conf2]
}

object Conf2M {
  def main(args: Array[String]): Unit = {
    println(ConfigSource.string("""t = { mode=i, i=1}""").loadOrThrow[Conf2])
    println(ConfigSource.string("""t = { mode=o}""").loadOrThrow[Conf2])
    println(ConfigSource.string("""t = { mode=s, s=foo}""").loadOrThrow[Conf2])
  }
}

Prints:

Conf2(I(1))
Conf2(O)
Conf2(S(foo))
@jcazevedo How would you feel about me sending a PR to add an example of semiauto to https://pureconfig.github.io/docs/overriding-behavior-for-sealed-families.html?
Joao Azevedo
@jcazevedo
I think it makes sense, yes. We might also want to revise how derivations other than full-auto are presented. We assume a full-auto approach in most of our documentation.
Leif Wickland
@leifwickland
That's true. The docs do assume auto. Do you think it'd make more sense to split the docs so that semiauto is more of an advanced topic covered separately and later? I'm afraid that mixing the two approaches will be confusing.
Joao Azevedo
@jcazevedo
Our current approach is to present semiauto as an advanced topic. Assuming that approach, I think the example of deriving sealed families with semiauto fits better inside https://pureconfig.github.io/docs/non-automatic-derivation.html.
Leif Wickland
@leifwickland
Oh, you're right. I'd forgotten that. I'll send a PR against that.
Rui Gonçalves
@ruippeixotog

Our current approach is to present semiauto as an advanced topic. Assuming that approach, I think the example of deriving sealed families with semiauto fits better inside https://pureconfig.github.io/docs/non-automatic-derivation.html.

^ this :) It's also important to note that this would be likely straightforward to debug using the -Xmacro-settings:materialize-derivations compiler option, as shown in https://pureconfig.github.io/docs/faq.html#how-do-i-debug-implicit-not-found-errors

Glen Marchesani
@fizzy33
I just found pure config great to see it
looking for parsing hocon in the browser...
Wondering if anyone has an intuition about the level of effort to get it working in scala js ?
I ask that based on seeing various non-scala js deps in the build.sbt from a quick cursory glance.
Rui Gonçalves
@ruippeixotog
Typesafe Config is written in Java, which is a dealbreaker for us to support scala js
Glen Marchesani
@fizzy33
oooooh @ruippeixotog you aren't a scala re-implementation of the parser. Okay thanks. Somehow I thought it was a scala implementation of the parser.
Erik Erlandson
@erikerlandson
[announce] the latest release of coulomb includes 3-way integration of coulomb+pureconfig+refined, for unit-aware and constraint-aware value i/o
https://github.com/erikerlandson/coulomb/tree/develop/coulomb-pureconfig-refined#examples
caoguangshun
@caoguangshun
has any one come across the following error?
image.png
the scala version is 2.11.7 the pureconfig is 0.11.1, and i check the ConfigReader, it does not have "traversableReader" function
eyal farago
@eyalfa
guys, pureconfig/pureconfig#769 , will u accept a PR for this?
David Leonhart
@leozilla

Hi, I am a happy user of pureconfig and I have a question which I could not figure out myself so far.
Whats the best way to get an empty Map (or List or whatever collection type) when reading a config which does not contain the necessary section to parse the collection.
Example:

case class Example(myMap: Map[String, String])

When parsing a config which does not define the my-map section, I would like to get an empty Map instead of an error but if the parsing fails for some other reason (eg key format invalid) then the parsing of the whole config should fail.

Joao Azevedo
@jcazevedo
I think you have a couple of options. If changing your type to an Option[Map[String, String]] is OK, then you get that behaviour out of the box, but you have to deal with the Option.
If you allow using default arguments (which the default ProductHint does), you can also have a default argument for that field, which would be the empty map.
You can also have a specific implementation of ConfigReader for Map[String, String] used by the ConfigReader of Example which handles the missing key case.
You can take a look at https://pureconfig.github.io/docs/overriding-behavior-for-case-classes.html#missing-keys for an example of how to do that.
David Leonhart
@leozilla
Oh ok, I havent considered using default arguments, I think thats the best solution
fnqista
@fnqista

Hi. Is there an easy way to do cross-field derivation? For example, if I have a config like this:

  duration {
    format = yyyy-MM-dd
    start = 2020-05-26
    end = 2020-06-26
  }

I wanted to map it to a case class like this:

case class DateRange(formatter: DateTimeFormatter, start: LocalDate, end: LocalDate)

So basically, I want to validate first if duration.format is a valid SimpleDateFormat pattern, and then use it to create a DateTimeFormatter instance and parse the given duration.start and duration.end into java.time.LocalDate instances. If it helps to describe the use case, this is used to find HDFS partitions from a hadoop file system.

Any help would be very much appreciated.

Sergey Rublev
@narma
Hey! Can we release 0.12.4 now? Due to scala/scala#8933 latest release (0.12.3) give me incorrect results with scala 2.13.3 and valid results with latest master.
test case
import pureconfig.syntax._
import pureconfig._
import pureconfig.generic.auto._

case class Config(configValue: Int = 15)

object Hello extends App {
  val c = Config()
  println(c.toConfig.render())
}
scala 2.13.3 + pureconfig 0.12.3:
{
    # hardcoded value
    "ymbol-(config-value-)" : 15
}
scala 2.13.3 + pureconfig master:
{
    # hardcoded value
    "config-value" : 15
}
Sergey Rublev
@narma
I also created issue pureconfig/pureconfig#782 about it
Joao Azevedo
@jcazevedo
@narma: Thanks for the report! We'll try to release a new version soon.
Sergey Rublev
@narma
Thanks!
Rui Gonçalves
@ruippeixotog

Hi. Is there an easy way to do cross-field derivation? For example, if I have a config like this:

  duration {
    format = yyyy-MM-dd
    start = 2020-05-26
    end = 2020-06-26
  }

I wanted to map it to a case class like this:

case class DateRange(formatter: DateTimeFormatter, start: LocalDate, end: LocalDate)

So basically, I want to validate first if duration.format is a valid SimpleDateFormat pattern, and then use it to create a DateTimeFormatter instance and parse the given duration.start and duration.end into java.time.LocalDate instances. If it helps to describe the use case, this is used to find HDFS partitions from a hadoop file system.

Any help would be very much appreciated.

@fnqista I think your best solution is to create a custom ConfigReader for DateRange that will read the three fields individually and create a DateRange accordingly. I think that a cursor-based implementation would be fairly straightforward - please take a look at https://pureconfig.github.io/docs/config-cursors.html

Leif Wickland
@leifwickland

@fnqista My team often follow the first approach Rui described in a way that looks roughly like this:

case class DateRange(start:LocalDate, end:LocalDate)
object DateRange {
  implicit val reader: ConfigReader[DateRange] = {
    private case class Raw(format: String, start: String, end: String) {
      def orFail[A](a: () => A)(err: String): Either[FailureReason, A] =
        Try(a).toEither.left.map(ex => new FailureReason { def description = s"$err: ${ex.getMessage}" })
      def toDateRange: Either[FailureReason, DateRange] = for {
        f <- orFail(new DateTimeFormatter(format))("Could not read 'format'")
        s <- orFail(f.parse(start))("Could not read 'start'")
        e <- orFail(f.parse(end))("Could not read 'end'")
      } yield(DateRange(s,e))
    }
    deriveReader[Raw].emap(_.toDateRange)
  }
}

(Warning: I just hammered that out without checking if it compiles.)

fnqista
@fnqista
Thanks @ruippeixotog for the ideas - was able to try out a possible solution using for-comprehension via cursors. Also @leifwickland this is a great example since it uses the error mechanism of pureconfig. Super thanks!