-
Notifications
You must be signed in to change notification settings - Fork 323
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
211 additions
and
41 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
28 changes: 28 additions & 0 deletions
28
lib/scala/editions/src/main/scala/org/enso/editions/EditionName.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,28 @@ | ||
package org.enso.editions | ||
|
||
import io.circe.Decoder | ||
|
||
/** A helper type to handle special parsing logic of edition names. | ||
* | ||
* The issue is that if an edition is called `2021.4` and it is written | ||
* unquoted inside of a YAML file, that is treated as a floating point | ||
* number, so special care must be taken to correctly parse it. | ||
*/ | ||
case class EditionName(name: String) extends AnyVal | ||
|
||
object EditionName { | ||
|
||
/** A helper method for constructing an [[EditionName]]. */ | ||
def apply(name: String): EditionName = new EditionName(name) | ||
|
||
/** A [[Decoder]] instance for [[EditionName]] that accepts not only strings | ||
* but also numbers as valid edition names. | ||
*/ | ||
implicit val editionNameDecoder: Decoder[EditionName] = { json => | ||
json | ||
.as[String] | ||
.orElse(json.as[Int].map(_.toString)) | ||
.orElse(json.as[Float].map(_.toString)) | ||
.map(EditionName(_)) | ||
} | ||
} |
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
9 changes: 7 additions & 2 deletions
9
lib/scala/editions/src/main/scala/org/enso/editions/repository/Manifest.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 |
---|---|---|
@@ -1,17 +1,22 @@ | ||
package org.enso.editions.repository | ||
|
||
import io.circe._ | ||
import org.enso.editions.EditionName | ||
|
||
case class Manifest(editions: Seq[String]) | ||
/** The Edition Repository manifest, which lists all editions that the | ||
* repository provides. | ||
*/ | ||
case class Manifest(editions: Seq[EditionName]) | ||
|
||
object Manifest { | ||
object Fields { | ||
val editions = "editions" | ||
} | ||
|
||
/** A [[Decoder]] instance for parsing [[Manifest]]. */ | ||
implicit val decoder: Decoder[Manifest] = { json => | ||
for { | ||
editions <- json.get[Seq[String]](Fields.editions) | ||
editions <- json.get[Seq[EditionName]](Fields.editions) | ||
} yield Manifest(editions) | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
lib/scala/editions/src/main/scala/org/enso/yaml/ParseError.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,19 @@ | ||
package org.enso.yaml | ||
|
||
import cats.Show | ||
|
||
/** Indicates a parse failure, usually meaning that the input data has | ||
* unexpected format (like missing fields or wrong field types). | ||
*/ | ||
case class ParseError(message: String, cause: io.circe.Error) | ||
extends RuntimeException(message, cause) | ||
|
||
object ParseError { | ||
|
||
/** Wraps a [[io.circe.Error]] into a more user-friendly [[ParseError]]. */ | ||
def apply(error: io.circe.Error): ParseError = { | ||
val errorMessage = | ||
implicitly[Show[io.circe.Error]].show(error) | ||
ParseError(errorMessage, error) | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
lib/scala/editions/src/main/scala/org/enso/yaml/YamlHelper.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,17 @@ | ||
package org.enso.yaml | ||
|
||
import io.circe.{yaml, Decoder} | ||
|
||
/** A helper for parsing YAML configs. */ | ||
object YamlHelper { | ||
|
||
/** Parses a string representation of a YAML configuration of type `R`. */ | ||
def parseString[R]( | ||
yamlString: String | ||
)(implicit decoder: Decoder[R]): Either[ParseError, R] = | ||
yaml.parser | ||
.parse(yamlString) | ||
.flatMap(_.as[R]) | ||
.left | ||
.map(ParseError(_)) | ||
} |
32 changes: 32 additions & 0 deletions
32
lib/scala/editions/src/test/scala/org/enso/editions/LibraryNameSpec.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,32 @@ | ||
package org.enso.editions | ||
|
||
import org.enso.testkit.EitherValue | ||
import org.enso.yaml.YamlHelper | ||
import org.scalatest.EitherValues | ||
import org.scalatest.matchers.should.Matchers | ||
import org.scalatest.wordspec.AnyWordSpec | ||
|
||
class LibraryNameSpec | ||
extends AnyWordSpec | ||
with Matchers | ||
with EitherValue | ||
with EitherValues { | ||
"LibraryName" should { | ||
"parse and serialize to the same thing" in { | ||
val str = "Foo.Bar" | ||
val libraryName = LibraryName.fromString(str).rightValue | ||
libraryName.qualifiedName shouldEqual str | ||
libraryName.name shouldEqual "Bar" | ||
libraryName.prefix shouldEqual "Foo" | ||
|
||
val yamlParsed = YamlHelper.parseString[LibraryName](str).rightValue | ||
yamlParsed shouldEqual libraryName | ||
} | ||
|
||
"fail to parse if there are too many parts" in { | ||
LibraryName.fromString("A.B.C") shouldEqual Left( | ||
"`A.B.C` is not a valid library name." | ||
) | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
lib/scala/editions/src/test/scala/org/enso/editions/repository/ManifestParserSpec.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,25 @@ | ||
package org.enso.editions.repository | ||
|
||
import org.enso.editions.EditionName | ||
import org.enso.testkit.EitherValue | ||
import org.enso.yaml.YamlHelper | ||
import org.scalatest.matchers.should.Matchers | ||
import org.scalatest.wordspec.AnyWordSpec | ||
|
||
class ManifestParserSpec extends AnyWordSpec with Matchers with EitherValue { | ||
"Manifest" should { | ||
"be parsed from YAML format" in { | ||
val str = | ||
"""editions: | ||
|- foo | ||
|- 2021.4 | ||
|- bar | ||
|""".stripMargin | ||
YamlHelper.parseString[Manifest](str).rightValue.editions shouldEqual Seq( | ||
EditionName("foo"), | ||
EditionName("2021.4"), | ||
EditionName("bar") | ||
) | ||
} | ||
} | ||
} |
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
53 changes: 53 additions & 0 deletions
53
...c/test/scala/org/enso/librarymanager/published/repository/LibraryManifestParserSpec.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,53 @@ | ||
package org.enso.librarymanager.published.repository | ||
|
||
import org.enso.editions.LibraryName | ||
import org.enso.testkit.EitherValue | ||
import org.enso.yaml.YamlHelper | ||
import org.scalatest.matchers.should.Matchers | ||
import org.scalatest.wordspec.AnyWordSpec | ||
|
||
class LibraryManifestParserSpec | ||
extends AnyWordSpec | ||
with Matchers | ||
with EitherValue { | ||
"LibraryManifest" should { | ||
"be parsed from YAML format" in { | ||
val str = | ||
"""archives: | ||
|- main.tgz | ||
|- tests.tgz | ||
|dependencies: | ||
|- Standard.Base | ||
|- Foo.Bar | ||
|tag-line: Foo Bar | ||
|description: Foo bar baz. | ||
|""".stripMargin | ||
YamlHelper | ||
.parseString[LibraryManifest](str) | ||
.rightValue shouldEqual LibraryManifest( | ||
archives = Seq("main.tgz", "tests.tgz"), | ||
dependencies = Seq( | ||
LibraryName.fromString("Standard.Base").rightValue, | ||
LibraryName.fromString("Foo.Bar").rightValue | ||
), | ||
tagLine = Some("Foo Bar"), | ||
description = Some("Foo bar baz.") | ||
) | ||
} | ||
|
||
"require only a minimal set of fields to parse" in { | ||
val str = | ||
"""archives: | ||
|- main.tgz | ||
|""".stripMargin | ||
YamlHelper | ||
.parseString[LibraryManifest](str) | ||
.rightValue shouldEqual LibraryManifest( | ||
archives = Seq("main.tgz"), | ||
dependencies = Seq(), | ||
tagLine = None, | ||
description = None | ||
) | ||
} | ||
} | ||
} |